blob: 5aa58a2eeb72162faeeb97e736ca644e018f7b54 [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;
321 thread->getThreadloopExecutor().defer(
322 [track = wp<TrackBase>::fromExisting(this)] {
323 const auto actual = track.promote();
324 if (actual) actual->restartIfDisabled();
325 });
326}
327
Andy Hung8d31fd22023-06-26 19:20:57 -0700328PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700329 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800330 : mProxy(proxy)
331{
332 if (timeout) {
333 setPeerTimeout(*timeout);
334 } else {
335 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700336 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
337 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800338 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
339 }
340}
341
Andy Hung8d31fd22023-06-26 19:20:57 -0700342void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800343 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
344 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
345}
346
347
Eric Laurent81784c32012-11-19 14:55:58 -0800348// ----------------------------------------------------------------------------
349// Playback
350// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700351#undef LOG_TAG
352#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800353
Andy Hunga5a7fc92023-06-23 19:27:19 -0700354class TrackHandle : public android::media::BnAudioTrack {
355public:
Andy Hungd29af632023-06-23 19:27:19 -0700356 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700357 ~TrackHandle() override;
358
359 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
360 binder::Status start(int32_t* _aidl_return) final;
361 binder::Status stop() final;
362 binder::Status flush() final;
363 binder::Status pause() final;
364 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
365 binder::Status setParameters(const std::string& keyValuePairs,
366 int32_t* _aidl_return) final;
367 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
368 int32_t* _aidl_return) final;
369 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
370 int32_t* _aidl_return) final;
371 binder::Status signal() final;
372 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
373 const media::VolumeShaperOperation& operation,
374 int32_t* _aidl_return) final;
375 binder::Status getVolumeShaperState(
376 int32_t id,
377 std::optional<media::VolumeShaperState>* _aidl_return) final;
378 binder::Status getDualMonoMode(
379 media::audio::common::AudioDualMonoMode* _aidl_return) final;
380 binder::Status setDualMonoMode(
381 media::audio::common::AudioDualMonoMode mode) final;
382 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
383 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
384 binder::Status getPlaybackRateParameters(
385 media::audio::common::AudioPlaybackRate* _aidl_return) final;
386 binder::Status setPlaybackRateParameters(
387 const media::audio::common::AudioPlaybackRate& playbackRate) final;
388
389private:
Andy Hungd29af632023-06-23 19:27:19 -0700390 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700391};
392
393/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700394sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700395 return sp<TrackHandle>::make(track);
396}
397
Andy Hungd29af632023-06-23 19:27:19 -0700398TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800399 : BnAudioTrack(),
400 mTrack(track)
401{
Andy Hung225aef62022-12-06 16:33:20 -0800402 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -0700403 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -0800404}
405
Andy Hunga5a7fc92023-06-23 19:27:19 -0700406TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800407 // just stop the track on deletion, associated resources
408 // will be freed from the main thread once all pending buffers have
409 // been played. Unless it's not in the active track list, in which
410 // case we free everything now...
411 mTrack->destroy();
412}
413
Andy Hunga5a7fc92023-06-23 19:27:19 -0700414Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800415 std::optional<media::SharedFileRegion>* _aidl_return) {
416 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
417 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800418}
419
Andy Hunga5a7fc92023-06-23 19:27:19 -0700420Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 *_aidl_return = mTrack->start();
422 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800423}
424
Andy Hunga5a7fc92023-06-23 19:27:19 -0700425Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800426 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800427 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800428}
429
Andy Hunga5a7fc92023-06-23 19:27:19 -0700430Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800431 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hunga5a7fc92023-06-23 19:27:19 -0700435Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800436 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800437 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800438}
439
Andy Hunga5a7fc92023-06-23 19:27:19 -0700440Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800441 int32_t* _aidl_return) {
442 *_aidl_return = mTrack->attachAuxEffect(effectId);
443 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800444}
445
Andy Hunga5a7fc92023-06-23 19:27:19 -0700446Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800447 int32_t* _aidl_return) {
448 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
449 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700450}
451
Andy Hunga5a7fc92023-06-23 19:27:19 -0700452Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800453 int32_t* _aidl_return) {
454 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
455 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800456}
457
Andy Hunga5a7fc92023-06-23 19:27:19 -0700458Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 int32_t* _aidl_return) {
460 AudioTimestamp legacy;
461 *_aidl_return = mTrack->getTimestamp(legacy);
462 if (*_aidl_return != OK) {
463 return Status::ok();
464 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000465
466 // restrict position modulo INT_MAX to avoid integer sanitization abort
467 legacy.mPosition &= INT_MAX;
468
Andy Hung973638a2020-12-08 20:47:45 -0800469 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800470 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800471}
472
Andy Hunga5a7fc92023-06-23 19:27:19 -0700473Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800474 mTrack->signal();
475 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800476}
477
Andy Hunga5a7fc92023-06-23 19:27:19 -0700478Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800479 const media::VolumeShaperConfiguration& configuration,
480 const media::VolumeShaperOperation& operation,
481 int32_t* _aidl_return) {
482 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
483 *_aidl_return = conf->readFromParcelable(configuration);
484 if (*_aidl_return != OK) {
485 return Status::ok();
486 }
487
488 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
489 *_aidl_return = op->readFromParcelable(operation);
490 if (*_aidl_return != OK) {
491 return Status::ok();
492 }
493
494 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
495 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700496}
497
Andy Hunga5a7fc92023-06-23 19:27:19 -0700498Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800499 int32_t id,
500 std::optional<media::VolumeShaperState>* _aidl_return) {
501 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
502 if (legacy == nullptr) {
503 _aidl_return->reset();
504 return Status::ok();
505 }
506 media::VolumeShaperState aidl;
507 legacy->writeToParcelable(&aidl);
508 *_aidl_return = aidl;
509 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800510}
511
Andy Hunga5a7fc92023-06-23 19:27:19 -0700512Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000513 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800514{
515 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
516 const status_t status = mTrack->getDualMonoMode(&mode)
517 ?: AudioValidator::validateDualMonoMode(mode);
518 if (status == OK) {
519 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
520 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
521 }
522 return binderStatusFromStatusT(status);
523}
524
Andy Hunga5a7fc92023-06-23 19:27:19 -0700525Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000526 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800527{
528 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
529 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
530 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
531 ?: mTrack->setDualMonoMode(localMonoMode));
532}
533
Andy Hunga5a7fc92023-06-23 19:27:19 -0700534Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800535{
536 float leveldB = -std::numeric_limits<float>::infinity();
537 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
538 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
539 if (status == OK) *_aidl_return = leveldB;
540 return binderStatusFromStatusT(status);
541}
542
Andy Hunga5a7fc92023-06-23 19:27:19 -0700543Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800544{
545 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
546 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
547}
548
Andy Hunga5a7fc92023-06-23 19:27:19 -0700549Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000550 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800551{
552 audio_playback_rate_t localPlaybackRate{};
553 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
554 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
555 if (status == NO_ERROR) {
556 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
557 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
558 }
559 return binderStatusFromStatusT(status);
560}
561
Andy Hunga5a7fc92023-06-23 19:27:19 -0700562Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000563 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800564{
565 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
566 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
567 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
568 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
569}
570
Eric Laurent81784c32012-11-19 14:55:58 -0800571// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800572// AppOp for audio playback
573// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700574
575// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700576sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700577 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000578 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700579 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800580{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700581 Vector<String16> packages;
582 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000583 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700584 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700585 if (packages.isEmpty()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000586 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700587 uid);
588 return nullptr;
589 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800590 }
591 // stream type has been filtered by audio policy to indicate whether it can be muted
592 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700593 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700594 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800595 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700596 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
597 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
598 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
599 id, attr.flags);
600 return nullptr;
601 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700602 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700603}
604
Andy Hung87c693c2023-07-06 20:56:16 -0700605OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700606 const AttributionSourceState& attributionSource,
607 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700608 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700609 mHasOpPlayAudio(true),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700610 mUsage((int32_t)usage),
611 mId(id),
612 mUid(uid),
613 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
614 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800615
Andy Hung8d31fd22023-06-26 19:20:57 -0700616OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800617{
618 if (mOpCallback != 0) {
619 mAppOpsManager.stopWatchingMode(mOpCallback);
620 }
621 mOpCallback.clear();
622}
623
Andy Hung8d31fd22023-06-26 19:20:57 -0700624void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700625{
Vlad Popad5859592023-08-02 18:36:04 -0700626 // make sure not to broadcast the initial state since it is not needed and could
627 // cause a deadlock since this method can be called with the mThread->mLock held
628 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000629 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700630 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000631 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
632 } else {
633 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700634 }
635}
636
Andy Hung8d31fd22023-06-26 19:20:57 -0700637bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800638 return mHasOpPlayAudio.load();
639}
640
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700641// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800642// - not called from constructor due to check on UID,
643// - not called from PlayAudioOpCallback because the callback is not installed in this case
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000644void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
645 const bool hasAppOps =
646 mPackageName.size() &&
647 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
648 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700649
650 bool shouldChange = !hasAppOps; // check if we need to update.
651 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000652 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000653 String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
Vlad Popad5859592023-08-02 18:36:04 -0700654 if (doBroadcast) {
655 auto thread = mThread.promote();
656 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
657 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hungc5007f82023-08-29 14:26:09 -0700658 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad5859592023-08-02 18:36:04 -0700659 thread->broadcast_l();
660 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700661 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800662 }
663}
664
Andy Hung8d31fd22023-06-26 19:20:57 -0700665OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800666 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
667{ }
668
Andy Hung8d31fd22023-06-26 19:20:57 -0700669void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800670 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800671 if (op != AppOpsManager::OP_PLAY_AUDIO) {
672 return;
673 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000674
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000675 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800676 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
677 if (monitor != NULL) {
Vlad Popad5859592023-08-02 18:36:04 -0700678 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800679 }
680}
681
Eric Laurent9066ad32019-05-20 14:40:10 -0700682// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700683void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700684 uid_t uid, Vector<String16>& packages)
685{
686 PermissionController permissionController;
687 permissionController.getPackagesForUid(uid, packages);
688}
689
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800690// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700691#undef LOG_TAG
692#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800693
Andy Hung8d31fd22023-06-26 19:20:57 -0700694/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700695sp<IAfTrack> IAfTrack::create(
696 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700697 const sp<Client>& client,
698 audio_stream_type_t streamType,
699 const audio_attributes_t& attr,
700 uint32_t sampleRate,
701 audio_format_t format,
702 audio_channel_mask_t channelMask,
703 size_t frameCount,
704 void *buffer,
705 size_t bufferSize,
706 const sp<IMemory>& sharedBuffer,
707 audio_session_t sessionId,
708 pid_t creatorPid,
709 const AttributionSourceState& attributionSource,
710 audio_output_flags_t flags,
711 track_type type,
712 audio_port_handle_t portId,
713 /** default behaviour is to start when there are as many frames
714 * ready as possible (aka. Buffer is full). */
715 size_t frameCountToBeReady,
716 float speed,
717 bool isSpatialized,
Andy Hung6b137d12024-08-27 22:35:17 +0000718 bool isBitPerfect,
719 float volume) {
Andy Hung87c693c2023-07-06 20:56:16 -0700720 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700721 client,
722 streamType,
723 attr,
724 sampleRate,
725 format,
726 channelMask,
727 frameCount,
728 buffer,
729 bufferSize,
730 sharedBuffer,
731 sessionId,
732 creatorPid,
733 attributionSource,
734 flags,
735 type,
736 portId,
737 frameCountToBeReady,
738 speed,
739 isSpatialized,
Andy Hung6b137d12024-08-27 22:35:17 +0000740 isBitPerfect,
741 volume);
Andy Hung8d31fd22023-06-26 19:20:57 -0700742}
743
Eric Laurent81784c32012-11-19 14:55:58 -0800744// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700745Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700746 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800747 const sp<Client>& client,
748 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700749 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800750 uint32_t sampleRate,
751 audio_format_t format,
752 audio_channel_mask_t channelMask,
753 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700754 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700755 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800756 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800757 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700758 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000759 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700760 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800761 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100762 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000763 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200764 float speed,
jiabinc658e452022-10-21 20:52:21 +0000765 bool isSpatialized,
Andy Hung6b137d12024-08-27 22:35:17 +0000766 bool isBitPerfect,
767 float volume)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700768 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700769 // TODO: Using unsecurePointer() has some associated security pitfalls
770 // (see declaration for details).
771 // Either document why it is safe in this case or address the
772 // issue (e.g. by copying).
773 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700774 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700775 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000776 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700777 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800778 type,
779 portId,
780 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700781 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800782 // mRetryCount initialized later when needed
783 mSharedBuffer(sharedBuffer),
784 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700785 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800786 mAuxBuffer(NULL),
787 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700788 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700789 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700790 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700791 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700792 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800793 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800794 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700795 /* The track might not play immediately after being active, similarly as if its volume was 0.
796 * When the track starts playing, its volume will be computed. */
797 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800798 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700799 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000800 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200801 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000802 mIsSpatialized(isSpatialized),
Andy Hung6b137d12024-08-27 22:35:17 +0000803 mIsBitPerfect(isBitPerfect),
804 mVolume(volume)
Eric Laurent81784c32012-11-19 14:55:58 -0800805{
Eric Laurent83b88082014-06-20 18:31:16 -0700806 // client == 0 implies sharedBuffer == 0
807 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
808
Andy Hung9d84af52018-09-12 18:03:44 -0700809 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700810 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700811
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700812 if (mCblk == NULL) {
813 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800814 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700815
Svet Ganov33761132021-05-13 22:51:08 +0000816 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700817 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
818 ALOGE("%s(%d): no more tracks available", __func__, mId);
819 releaseCblk(); // this makes the track invalid.
820 return;
821 }
822
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700823 if (sharedBuffer == 0) {
824 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700825 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700826 } else {
827 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100828 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700829 }
830 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700831 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700832
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700833 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700834 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700835 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
836 // race with setSyncEvent(). However, if we call it, we cannot properly start
837 // static fast tracks (SoundPool) immediately after stopping.
838 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700839 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
840 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700841 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700842 // FIXME This is too eager. We allocate a fast track index before the
843 // fast track becomes active. Since fast tracks are a scarce resource,
844 // this means we are potentially denying other more important fast tracks from
845 // being created. It would be better to allocate the index dynamically.
846 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700847 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700848 }
Andy Hung8946a282018-04-19 20:04:56 -0700849
Andy Hung6b137d12024-08-27 22:35:17 +0000850 populateUsageAndContentTypeFromStreamType();
851
852 // Audio patch and call assistant volume are always max
853 if (mAttr.usage == AUDIO_USAGE_CALL_ASSISTANT
854 || mAttr.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
855 mVolume = 1.0f;
856 }
857
Dean Wheatley7b036912020-06-18 16:22:11 +1000858 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700859#ifdef TEE_SINK
860 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800861 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700862#endif
jiabin57303cc2018-12-18 15:45:57 -0800863
jiabineb3bda02020-06-30 14:07:03 -0700864 if (thread->supportsHapticPlayback()) {
865 // If the track is attached to haptic playback thread, it is potentially to have
866 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
867 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800868 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000869 std::string packageName = attributionSource.packageName.has_value() ?
870 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800871 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700872 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800873 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800874
875 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700876 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800877 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800878}
879
Andy Hung6b137d12024-08-27 22:35:17 +0000880// When attributes are undefined, derive default values from stream type.
881// See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
882void Track::populateUsageAndContentTypeFromStreamType() {
883 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
884 switch (mStreamType) {
885 case AUDIO_STREAM_VOICE_CALL:
886 mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
887 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
888 break;
889 case AUDIO_STREAM_SYSTEM:
890 mAttr.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
891 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
892 break;
893 case AUDIO_STREAM_RING:
894 mAttr.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
895 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
896 break;
897 case AUDIO_STREAM_MUSIC:
898 mAttr.usage = AUDIO_USAGE_MEDIA;
899 mAttr.content_type = AUDIO_CONTENT_TYPE_MUSIC;
900 break;
901 case AUDIO_STREAM_ALARM:
902 mAttr.usage = AUDIO_USAGE_ALARM;
903 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
904 break;
905 case AUDIO_STREAM_NOTIFICATION:
906 mAttr.usage = AUDIO_USAGE_NOTIFICATION;
907 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
908 break;
909 case AUDIO_STREAM_DTMF:
910 mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
911 mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
912 break;
913 case AUDIO_STREAM_ACCESSIBILITY:
914 mAttr.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
915 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
916 break;
917 case AUDIO_STREAM_ASSISTANT:
918 mAttr.usage = AUDIO_USAGE_ASSISTANT;
919 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
920 break;
921 case AUDIO_STREAM_REROUTING:
922 case AUDIO_STREAM_PATCH:
923 mAttr.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
924 // unknown content type
925 break;
926 case AUDIO_STREAM_CALL_ASSISTANT:
927 mAttr.usage = AUDIO_USAGE_CALL_ASSISTANT;
928 mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
929 break;
930 default:
931 break;
932 }
933 }
934}
935
Andy Hung8d31fd22023-06-26 19:20:57 -0700936Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800937{
Andy Hung9d84af52018-09-12 18:03:44 -0700938 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700939
940 // The destructor would clear mSharedBuffer,
941 // but it will not push the decremented reference count,
942 // leaving the client's IMemory dangling indefinitely.
943 // This prevents that leak.
944 if (mSharedBuffer != 0) {
945 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700946 }
Eric Laurent81784c32012-11-19 14:55:58 -0800947}
948
Andy Hung8d31fd22023-06-26 19:20:57 -0700949status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700950{
951 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700952 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700953 status = NO_MEMORY;
954 }
955 return status;
956}
957
Andy Hung8d31fd22023-06-26 19:20:57 -0700958void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800959{
960 // NOTE: destroyTrack_l() can remove a strong reference to this Track
961 // by removing it from mTracks vector, so there is a risk that this Tracks's
962 // destructor is called. As the destructor needs to lock mLock,
963 // we must acquire a strong reference on this Track before locking mLock
964 // here so that the destructor is called only when exiting this function.
965 // On the other hand, as long as Track::destroy() is only called by
966 // TrackHandle destructor, the TrackHandle still holds a strong ref on
967 // this Track with its member mTrack.
968 sp<Track> keep(this);
969 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700970 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700971 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800972 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -0800973 audio_utils::unique_lock ul(thread->mutex());
974 thread->waitWhileThreadBusy_l(ul);
975
Andy Hung87c693c2023-07-06 20:56:16 -0700976 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700977 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000978 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700979 }
980 if (isExternalTrack() && !wasActive) {
Andy Hung6c498e92023-12-05 17:28:17 -0800981 // If the track is not active, the TrackHandle is responsible for
982 // releasing the port id, not the ThreadBase::threadLoop().
983 // At this point, there is no concurrency issue as the track is going away.
Eric Laurentd7fe0862018-07-14 16:48:01 -0700984 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800985 }
986 }
987}
988
Andy Hung8d31fd22023-06-26 19:20:57 -0700989void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800990{
Eric Laurent973db022018-11-20 14:54:31 -0800991 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700992 " Format Chn mask SRate "
993 "ST Usg CT "
Andy Hung6b137d12024-08-27 22:35:17 +0000994 " G db L dB R dB VS dB PortVol dB "
jiabin220eea12024-05-17 17:55:20 +0000995 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700996 "%s\n",
997 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800998}
999
Andy Hung8d31fd22023-06-26 19:20:57 -07001000void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08001001{
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001002 char trackType;
1003 switch (mType) {
1004 case TYPE_DEFAULT:
1005 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -07001006 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001007 trackType = 'S'; // static
1008 } else {
1009 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -08001010 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001011 break;
1012 case TYPE_PATCH:
1013 trackType = 'P';
1014 break;
1015 default:
1016 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -08001017 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001018
1019 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -07001020 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001021 } else {
Andy Hungc0691382018-09-12 18:01:57 -07001022 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001023 }
1024
Eric Laurent81784c32012-11-19 14:55:58 -08001025 char nowInUnderrun;
1026 switch (mObservedUnderruns.mBitFields.mMostRecent) {
1027 case UNDERRUN_FULL:
1028 nowInUnderrun = ' ';
1029 break;
1030 case UNDERRUN_PARTIAL:
1031 nowInUnderrun = '<';
1032 break;
1033 case UNDERRUN_EMPTY:
1034 nowInUnderrun = '*';
1035 break;
1036 default:
1037 nowInUnderrun = '?';
1038 break;
1039 }
Andy Hungda540db2017-04-20 14:06:17 -07001040
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001041 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -07001042 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001043 case FS_INVALID:
1044 fillingStatus = 'I';
1045 break;
1046 case FS_FILLING:
1047 fillingStatus = 'f';
1048 break;
1049 case FS_FILLED:
1050 fillingStatus = 'F';
1051 break;
1052 case FS_ACTIVE:
1053 fillingStatus = 'A';
1054 break;
1055 default:
1056 fillingStatus = '?';
1057 break;
1058 }
1059
1060 // clip framesReadySafe to max representation in dump
1061 const size_t framesReadySafe =
1062 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
1063
1064 // obtain volumes
1065 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1066 const std::pair<float /* volume */, bool /* active */> vsVolume =
1067 mVolumeHandler->getLastVolume();
1068
1069 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
1070 // as it may be reduced by the application.
1071 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
1072 // Check whether the buffer size has been modified by the app.
1073 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
1074 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
1075 ? 'e' /* error */ : ' ' /* identical */;
1076
Eric Laurent973db022018-11-20 14:54:31 -08001077 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001078 "%08X %08X %6u "
1079 "%2u %3x %2x "
Andy Hung6b137d12024-08-27 22:35:17 +00001080 "%5.2g %5.2g %5.2g %5.2g%c %11.2g "
jiabin220eea12024-05-17 17:55:20 +00001081 "%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
Marco Nelissenb2208842014-02-07 14:00:50 -08001082 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001083 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001084 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001085 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001086 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001087 mCblk->mFlags,
1088
Eric Laurent81784c32012-11-19 14:55:58 -08001089 mFormat,
1090 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001091 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001092
1093 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001094 mAttr.usage,
1095 mAttr.content_type,
1096
1097 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001098 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1099 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001100 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1101 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung6b137d12024-08-27 22:35:17 +00001102 20.0 * log10(mVolume),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001103
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001104 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001105 bufferSizeInFrames,
1106 modifiedBufferChar,
1107 framesReadySafe,
1108 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001109 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001110 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001111 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
jiabin220eea12024-05-17 17:55:20 +00001112 isBitPerfect() ? "true" : "false",
1113 getInternalMute() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001114 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001115
1116 if (isServerLatencySupported()) {
1117 double latencyMs;
1118 bool fromTrack;
1119 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1120 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1121 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1122 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001123 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001124 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001125 }
1126 }
1127 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001128}
1129
Andy Hung8d31fd22023-06-26 19:20:57 -07001130uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001131 return mAudioTrackServerProxy->getSampleRate();
1132}
1133
Eric Laurent81784c32012-11-19 14:55:58 -08001134// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001135status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001136{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001137 ServerProxy::Buffer buf;
1138 size_t desiredFrames = buffer->frameCount;
1139 buf.mFrameCount = desiredFrames;
1140 status_t status = mServerProxy->obtainBuffer(&buf);
1141 buffer->frameCount = buf.mFrameCount;
1142 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001143 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001144 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001145 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001146 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001147 } else {
1148 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001149 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001150 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001151}
1152
Andy Hung8d31fd22023-06-26 19:20:57 -07001153void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001154{
1155 interceptBuffer(*buffer);
1156 TrackBase::releaseBuffer(buffer);
1157}
1158
1159// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001160void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001161 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001162 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001163 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001164 if (frameCount == 0) {
1165 return; // No audio to intercept.
1166 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1167 // does not allow 0 frame size request contrary to getNextBuffer
1168 }
Jiabin Huang73f97052023-12-12 20:08:03 +00001169 TeePatches teePatches;
1170 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1171 // Cache a copy of tee patches in case it is updated while using.
1172 teePatches = mTeePatches;
1173 mTeePatchesRWLock.unlock();
1174 }
1175 for (auto& teePatch : teePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001176 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001177 const size_t framesWritten = patchRecord->writeFrames(
1178 sourceBuffer.i8, frameCount, mFrameSize);
1179 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001180 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001181 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001182 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001183 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001184 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1185 using namespace std::chrono_literals;
1186 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001187 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang73f97052023-12-12 20:08:03 +00001188 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001189}
1190
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001191// ExtendedAudioBufferProvider interface
1192
Andy Hung27876c02014-09-09 18:07:55 -07001193// framesReady() may return an approximation of the number of frames if called
1194// from a different thread than the one calling Proxy->obtainBuffer() and
1195// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1196// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001197size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001198 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1199 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1200 // The remainder of the buffer is not drained.
1201 return 0;
1202 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001203 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001204}
1205
Andy Hung8d31fd22023-06-26 19:20:57 -07001206int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001207{
1208 return mAudioTrackServerProxy->framesReleased();
1209}
1210
Andy Hung8d31fd22023-06-26 19:20:57 -07001211void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001212{
1213 // This call comes from a FastTrack and should be kept lockless.
1214 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001215 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001216
Andy Hung818e7a32016-02-16 18:08:07 -08001217 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001218
1219 // Compute latency.
1220 // TODO: Consider whether the server latency may be passed in by FastMixer
1221 // as a constant for all active FastTracks.
1222 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1223 mServerLatencyFromTrack.store(true);
1224 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001225}
1226
Eric Laurent81784c32012-11-19 14:55:58 -08001227// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001228bool Track::isReady() const {
1229 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001230 return true;
1231 }
1232
Eric Laurent16498512014-03-17 17:22:08 -07001233 if (isStopping()) {
1234 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001235 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001236 }
Eric Laurent81784c32012-11-19 14:55:58 -08001237 return true;
1238 }
1239
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001240 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001241 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1242 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1243 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1244 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001245
1246 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1247 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1248 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001249 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001250 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001251 return true;
1252 }
1253 return false;
1254}
1255
Andy Hung8d31fd22023-06-26 19:20:57 -07001256status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001257 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001258{
1259 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001260 ALOGV("%s(%d): calling pid %d session %d",
1261 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001262
Andy Hung87c693c2023-07-06 20:56:16 -07001263 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001264 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001265 if (isOffloaded()) {
Andy Hung954b9712023-08-28 18:36:53 -07001266 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hungab65b182023-09-06 19:41:47 -07001267 const bool nonOffloadableGlobalEffectEnabled =
1268 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hungc5007f82023-08-29 14:26:09 -07001269 audio_utils::lock_guard _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001270 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hungab65b182023-09-06 19:41:47 -07001271 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001272 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001273 invalidate();
1274 return PERMISSION_DENIED;
1275 }
1276 }
Andy Hung6c498e92023-12-05 17:28:17 -08001277 audio_utils::unique_lock ul(thread->mutex());
1278 thread->waitWhileThreadBusy_l(ul);
1279
Eric Laurent81784c32012-11-19 14:55:58 -08001280 track_state state = mState;
1281 // here the track could be either new, or restarted
1282 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001283
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001284 // initial state-stopping. next state-pausing.
1285 // What if resume is called ?
1286
Zhou Song1ed46a22020-08-17 15:36:56 +08001287 if (state == FLUSHED) {
1288 // avoid underrun glitches when starting after flush
1289 reset();
1290 }
1291
kuowei.li576f1362021-05-11 18:02:32 +08001292 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1293 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001294 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001295 if (mResumeToStopping) {
1296 // happened we need to resume to STOPPING_1
1297 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001298 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1299 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001300 } else {
1301 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001302 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1303 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001304 }
Eric Laurent81784c32012-11-19 14:55:58 -08001305 } else {
1306 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001307 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1308 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001309 }
1310
Andy Hung87c693c2023-07-06 20:56:16 -07001311 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001312
1313 // states to reset position info for pcm tracks
1314 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001315 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1316 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001317
Dorin Drimusb882d482024-01-17 18:30:02 +01001318 if (!isFastTrack()) {
yucliu6cfb5932022-07-20 17:40:39 -07001319 // Start point of track -> sink frame map. If the HAL returns a
1320 // frame position smaller than the first written frame in
1321 // updateTrackFrameInfo, the timestamp can be interpolated
1322 // instead of using a larger value.
1323 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1324 playbackThread->framesWritten());
1325 }
Andy Hunge10393e2015-06-12 13:59:33 -07001326 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001327 if (isFastTrack()) {
1328 // refresh fast track underruns on start because that field is never cleared
1329 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1330 // after stop.
1331 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1332 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001333 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001334 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001335 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001336 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001337 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001338 mState = state;
1339 }
1340 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001341
Andy Hungb68f5eb2019-12-03 16:49:17 -08001342 // Audio timing metrics are computed a few mix cycles after starting.
1343 {
1344 mLogStartCountdown = LOG_START_COUNTDOWN;
1345 mLogStartTimeNs = systemTime();
1346 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001347 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1348 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001349 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001350 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001351
Andy Hung1d3556d2018-03-29 16:30:14 -07001352 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1353 // for streaming tracks, remove the buffer read stop limit.
1354 mAudioTrackServerProxy->start();
1355 }
1356
Eric Laurentbfb1b832013-01-07 09:53:42 -08001357 // track was already in the active list, not a problem
1358 if (status == ALREADY_EXISTS) {
1359 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001360 } else {
1361 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1362 // It is usually unsafe to access the server proxy from a binder thread.
1363 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1364 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1365 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001366 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001367 ServerProxy::Buffer buffer;
1368 buffer.mFrameCount = 1;
1369 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001370 }
jiabin7434e812023-06-27 18:22:35 +00001371 if (status == NO_ERROR) {
1372 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1373 }
Eric Laurent81784c32012-11-19 14:55:58 -08001374 } else {
1375 status = BAD_VALUE;
1376 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001377 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001378 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001379 const sp<IAudioManager> audioManager =
1380 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001381 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1382 std::unique_ptr<os::PersistableBundle> bundle =
1383 std::make_unique<os::PersistableBundle>();
1384 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1385 isSpatialized());
1386 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1387 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1388 status_t result = audioManager->portEvent(mPortId,
1389 PLAYER_UPDATE_FORMAT, bundle);
1390 if (result != OK) {
1391 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1392 __func__, mPortId, result);
1393 }
1394 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001395 }
Eric Laurent81784c32012-11-19 14:55:58 -08001396 return status;
1397}
1398
Andy Hung8d31fd22023-06-26 19:20:57 -07001399void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001400{
Andy Hungc0691382018-09-12 18:01:57 -07001401 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001402 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001403 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001404 audio_utils::unique_lock ul(thread->mutex());
1405 thread->waitWhileThreadBusy_l(ul);
1406
Eric Laurent81784c32012-11-19 14:55:58 -08001407 track_state state = mState;
1408 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1409 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001410 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1411 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001412 reset();
1413 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001414 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1415 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1416 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001417 mState = STOPPED;
1418 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001419 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1420 // presentation is complete
1421 // For an offloaded track this starts a drain and state will
1422 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001423 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001424 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001425 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001426 }
Eric Laurent81784c32012-11-19 14:55:58 -08001427 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001428 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001429 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1430 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001431 }
jiabin7434e812023-06-27 18:22:35 +00001432 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001433 }
1434}
1435
Andy Hung8d31fd22023-06-26 19:20:57 -07001436void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001437{
Andy Hungc0691382018-09-12 18:01:57 -07001438 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001439 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001440 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001441 audio_utils::unique_lock ul(thread->mutex());
1442 thread->waitWhileThreadBusy_l(ul);
1443
Andy Hung87c693c2023-07-06 20:56:16 -07001444 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001445 switch (mState) {
1446 case STOPPING_1:
1447 case STOPPING_2:
1448 if (!isOffloaded()) {
1449 /* nothing to do if track is not offloaded */
1450 break;
1451 }
1452
1453 // Offloaded track was draining, we need to carry on draining when resumed
1454 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001455 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001456 case ACTIVE:
1457 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001458 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001459 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1460 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001461 if (isOffloadedOrDirect()) {
1462 mPauseHwPending = true;
1463 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001464 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001465 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001466
Eric Laurentbfb1b832013-01-07 09:53:42 -08001467 default:
1468 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001469 }
jiabin7434e812023-06-27 18:22:35 +00001470 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1471 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001472 }
1473}
1474
Andy Hung8d31fd22023-06-26 19:20:57 -07001475void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001476{
Andy Hungc0691382018-09-12 18:01:57 -07001477 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001478 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001479 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001480 audio_utils::unique_lock ul(thread->mutex());
1481 thread->waitWhileThreadBusy_l(ul);
1482
Andy Hung87c693c2023-07-06 20:56:16 -07001483 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001484
Phil Burk4bb650b2016-09-09 12:11:17 -07001485 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1486 // Otherwise the flush would not be done until the track is resumed.
1487 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001488 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001489 (void)mServerProxy->flushBufferIfNeeded();
1490 }
1491
Eric Laurentbfb1b832013-01-07 09:53:42 -08001492 if (isOffloaded()) {
1493 // If offloaded we allow flush during any state except terminated
1494 // and keep the track active to avoid problems if user is seeking
1495 // rapidly and underlying hardware has a significant delay handling
1496 // a pause
1497 if (isTerminated()) {
1498 return;
1499 }
1500
Andy Hung9d84af52018-09-12 18:03:44 -07001501 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001502 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001503
1504 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001505 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1506 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001507 mState = ACTIVE;
1508 }
1509
Haynes Mathew George7844f672014-01-15 12:32:55 -08001510 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001511 mResumeToStopping = false;
1512 } else {
1513 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1514 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1515 return;
1516 }
1517 // No point remaining in PAUSED state after a flush => go to
1518 // FLUSHED state
1519 mState = FLUSHED;
1520 // do not reset the track if it is still in the process of being stopped or paused.
1521 // this will be done by prepareTracks_l() when the track is stopped.
1522 // prepareTracks_l() will see mState == FLUSHED, then
1523 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001524 if (isDirect()) {
1525 mFlushHwPending = true;
1526 }
Andy Hung87c693c2023-07-06 20:56:16 -07001527 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001528 reset();
1529 }
Eric Laurent81784c32012-11-19 14:55:58 -08001530 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001531 // Prevent flush being lost if the track is flushed and then resumed
1532 // before mixer thread can run. This is important when offloading
1533 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001534 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001535 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1536 // new data
1537 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001538 }
1539}
1540
Haynes Mathew George7844f672014-01-15 12:32:55 -08001541// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001542void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001543{
Andy Hung920f6572022-10-06 12:09:49 -07001544 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001545 return;
Andy Hung920f6572022-10-06 12:09:49 -07001546 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001547
Phil Burk4bb650b2016-09-09 12:11:17 -07001548 // Clear the client ring buffer so that the app can prime the buffer while paused.
1549 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1550 mServerProxy->flushBufferIfNeeded();
1551
Haynes Mathew George7844f672014-01-15 12:32:55 -08001552 mFlushHwPending = false;
1553}
1554
Andy Hung8d31fd22023-06-26 19:20:57 -07001555void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001556{
1557 mPauseHwPending = false;
1558}
1559
Andy Hung8d31fd22023-06-26 19:20:57 -07001560void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001561{
1562 // Do not reset twice to avoid discarding data written just after a flush and before
1563 // the audioflinger thread detects the track is stopped.
1564 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001565 // Force underrun condition to avoid false underrun callback until first data is
1566 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001567 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001568 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001569 mResetDone = true;
1570 if (mState == FLUSHED) {
1571 mState = IDLE;
1572 }
1573 }
1574}
1575
Andy Hung8d31fd22023-06-26 19:20:57 -07001576status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001577{
Andy Hung87c693c2023-07-06 20:56:16 -07001578 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001579 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001580 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001581 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001582 } else if (thread->type() == IAfThreadBase::DIRECT
1583 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001584 return thread->setParameters(keyValuePairs);
1585 } else {
1586 return PERMISSION_DENIED;
1587 }
1588}
1589
Andy Hung8d31fd22023-06-26 19:20:57 -07001590status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001591 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001592 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001593 if (thread == 0) {
1594 ALOGE("thread is dead");
1595 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001596 } else if (thread->type() == IAfThreadBase::DIRECT
1597 || thread->type() == IAfThreadBase::OFFLOAD) {
1598 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001599 return directOutputThread->selectPresentation(presentationId, programId);
1600 }
1601 return INVALID_OPERATION;
1602}
1603
Andy Hungd571fab2024-08-28 21:59:25 -07001604void Track::setPortVolume(float volume) {
1605 mVolume = volume;
1606 if (mType != TYPE_PATCH) {
1607 // Do not recursively propagate a PatchTrack setPortVolume to
1608 // downstream PatchTracks.
1609 forEachTeePatchTrack_l([volume](const auto& patchTrack) {
1610 patchTrack->setPortVolume(volume); });
1611 }
1612}
1613
Andy Hung8d31fd22023-06-26 19:20:57 -07001614VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001615 const sp<VolumeShaper::Configuration>& configuration,
1616 const sp<VolumeShaper::Operation>& operation)
1617{
Andy Hung398ffa22022-12-13 19:19:53 -08001618 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001619
1620 if (isOffloadedOrDirect()) {
1621 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001622 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001623 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001624 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001625 thread->broadcast_l();
1626 }
1627 }
1628 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001629}
1630
Andy Hung8d31fd22023-06-26 19:20:57 -07001631sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001632{
1633 // Note: We don't check if Thread exists.
1634
1635 // mVolumeHandler is thread safe.
1636 return mVolumeHandler->getVolumeShaperState(id);
1637}
1638
Andy Hung8d31fd22023-06-26 19:20:57 -07001639void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001640{
jiabin76d94692022-12-15 21:51:21 +00001641 mFinalVolumeLeft = volumeLeft;
1642 mFinalVolumeRight = volumeRight;
1643 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001644 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1645 mFinalVolume = volume;
1646 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001647 mLogForceVolumeUpdate = true;
1648 }
1649 if (mLogForceVolumeUpdate) {
1650 mLogForceVolumeUpdate = false;
1651 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001652 }
1653}
1654
Andy Hung8d31fd22023-06-26 19:20:57 -07001655void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001656{
Eric Laurent49e39282022-06-24 18:42:45 +02001657 // Do not forward metadata for PatchTrack with unspecified stream type
1658 if (mStreamType == AUDIO_STREAM_PATCH) {
1659 return;
1660 }
1661
Eric Laurent94579172020-11-20 18:41:04 +01001662 playback_track_metadata_v7_t metadata;
1663 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001664 .usage = mAttr.usage,
1665 .content_type = mAttr.content_type,
1666 .gain = mFinalVolume,
1667 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001668
Eric Laurent78b07302022-10-07 16:20:34 +02001669 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001670 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1671 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001672}
1673
Andy Hung8d31fd22023-06-26 19:20:57 -07001674void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001675 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001676 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang73f97052023-12-12 20:08:03 +00001677 {
1678 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1679 mTeePatches = std::move(mTeePatchesToUpdate.value());
1680 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001681 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1682 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001683 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001684 }
1685 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001686 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001687}
1688
Andy Hung16ed0da2023-07-14 11:45:38 -07001689void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001690 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1691 "%s, existing tee patches to update will be ignored", __func__);
1692 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1693}
1694
Vlad Popae8d99472022-06-30 16:02:48 +02001695// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001696void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001697 IAudioManager>& audioManager, mute_state_t muteState)
1698{
1699 if (mMuteState == muteState) {
1700 // mute state did not change, do nothing
1701 return;
1702 }
1703
1704 status_t result = UNKNOWN_ERROR;
1705 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1706 if (mMuteEventExtras == nullptr) {
1707 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1708 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001709 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001710
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001711 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001712 }
1713
1714 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001715 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
Andy Hung0e26ec62024-02-20 16:32:57 -08001716 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001717 mMuteState = muteState;
1718 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001719 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1720 mPortId, result);
Vlad Popae8d99472022-06-30 16:02:48 +02001721 }
1722}
1723
Andy Hung8d31fd22023-06-26 19:20:57 -07001724status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001725{
Andy Hung818e7a32016-02-16 18:08:07 -08001726 if (!isOffloaded() && !isDirect()) {
1727 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001728 }
Andy Hung87c693c2023-07-06 20:56:16 -07001729 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001730 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001731 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001732 }
Phil Burk6140c792015-03-19 14:30:21 -07001733
Andy Hungc5007f82023-08-29 14:26:09 -07001734 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001735 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001736 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001737}
1738
Andy Hung8d31fd22023-06-26 19:20:57 -07001739status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001740{
Andy Hung87c693c2023-07-06 20:56:16 -07001741 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001742 if (thread == nullptr) {
1743 return DEAD_OBJECT;
1744 }
Eric Laurent81784c32012-11-19 14:55:58 -08001745
Andy Hung87c693c2023-07-06 20:56:16 -07001746 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001747 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001748 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001749 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001750 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001751
Eric Laurent6c796322019-04-09 14:13:17 -07001752 if (EffectId != 0 && status == NO_ERROR) {
1753 status = dstThread->attachAuxEffect(this, EffectId);
1754 if (status == NO_ERROR) {
1755 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001756 }
Eric Laurent6c796322019-04-09 14:13:17 -07001757 }
1758
1759 if (status != NO_ERROR && srcThread != nullptr) {
1760 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001761 }
1762 return status;
1763}
1764
Andy Hung8d31fd22023-06-26 19:20:57 -07001765void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001766{
1767 mAuxEffectId = EffectId;
1768 mAuxBuffer = buffer;
1769}
1770
Andy Hung59de4262021-06-14 10:53:54 -07001771// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001772bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001773 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001774{
Andy Hung818e7a32016-02-16 18:08:07 -08001775 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1776 // This assists in proper timestamp computation as well as wakelock management.
1777
Eric Laurent81784c32012-11-19 14:55:58 -08001778 // a track is considered presented when the total number of frames written to audio HAL
1779 // corresponds to the number of frames written when presentationComplete() is called for the
1780 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001781 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1782 // to detect when all frames have been played. In this case framesWritten isn't
1783 // useful because it doesn't always reflect whether there is data in the h/w
1784 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001785 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1786 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001787 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001788 if (mPresentationCompleteFrames == 0) {
1789 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001790 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001791 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1792 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001793 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001794 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001795
Andy Hungc54b1ff2016-02-23 14:07:07 -08001796 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001797 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001798 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001799 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1800 __func__, mId, (complete ? "complete" : "waiting"),
1801 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001802 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001803 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001804 && mAudioTrackServerProxy->isDrained();
1805 }
1806
1807 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001808 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001809 return true;
1810 }
1811 return false;
1812}
1813
Andy Hung59de4262021-06-14 10:53:54 -07001814// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001815bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001816{
1817 // For Offloaded or Direct tracks.
1818
1819 // For a direct track, we incorporated time based testing for presentationComplete.
1820
1821 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1822 // to detect when all frames have been played. In this case latencyMs isn't
1823 // useful because it doesn't always reflect whether there is data in the h/w
1824 // buffers, particularly if a track has been paused and resumed during draining
1825
1826 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1827 if (mPresentationCompleteTimeNs == 0) {
1828 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1829 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1830 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1831 }
1832
1833 bool complete;
1834 if (isOffloaded()) {
1835 complete = true;
1836 } else { // Direct
1837 complete = systemTime() >= mPresentationCompleteTimeNs;
1838 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1839 }
1840 if (complete) {
1841 notifyPresentationComplete();
1842 return true;
1843 }
1844 return false;
1845}
1846
Andy Hung8d31fd22023-06-26 19:20:57 -07001847void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001848{
1849 // This only triggers once. TODO: should we enforce this?
1850 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1851 mAudioTrackServerProxy->setStreamEndDone();
1852}
1853
Andy Hung8d31fd22023-06-26 19:20:57 -07001854void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001855{
Andy Hung068e08e2023-05-15 19:02:55 -07001856 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1857 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001858 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001859 (*it)->trigger();
1860 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001861 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001862 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001863 }
1864 }
1865}
1866
1867// implement VolumeBufferProvider interface
1868
Andy Hung8d31fd22023-06-26 19:20:57 -07001869gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001870{
1871 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1872 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001873 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1874 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1875 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001876 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001877 if (vl > GAIN_FLOAT_UNITY) {
1878 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001879 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001880 if (vr > GAIN_FLOAT_UNITY) {
1881 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001882 }
1883 // now apply the cached master volume and stream type volume;
1884 // this is trusted but lacks any synchronization or barrier so may be stale
1885 float v = mCachedVolume;
1886 vl *= v;
1887 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001888 // re-combine into packed minifloat
1889 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001890 // FIXME look at mute, pause, and stop flags
1891 return vlr;
1892}
1893
Andy Hung8d31fd22023-06-26 19:20:57 -07001894status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001895 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001896{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001897 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001898 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1899 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001900 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1901 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001902 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001903 event->cancel();
1904 return INVALID_OPERATION;
1905 }
1906 (void) TrackBase::setSyncEvent(event);
1907 return NO_ERROR;
1908}
1909
Andy Hung8d31fd22023-06-26 19:20:57 -07001910void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001911{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001912 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001913 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001914}
1915
Andy Hung8d31fd22023-06-26 19:20:57 -07001916void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001917{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001918 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001919 signalClientFlag(CBLK_DISABLED);
1920}
1921
Eric Laurent022a5132024-04-12 17:02:51 +00001922bool Track::isDisabled() const {
1923 audio_track_cblk_t* cblk = mCblk;
1924 return (cblk != nullptr)
1925 && ((android_atomic_release_load(&cblk->mFlags) & CBLK_DISABLED) != 0);
1926}
1927
Andy Hung8d31fd22023-06-26 19:20:57 -07001928void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001929{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001930 // FIXME should use proxy, and needs work
1931 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001932 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001933 android_atomic_release_store(0x40000000, &cblk->mFutex);
1934 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001935 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001936}
1937
Andy Hung8d31fd22023-06-26 19:20:57 -07001938void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001939{
Andy Hung87c693c2023-07-06 20:56:16 -07001940 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001941 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001942 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001943 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001944 t->broadcast_l();
1945 }
1946}
1947
Andy Hung8d31fd22023-06-26 19:20:57 -07001948status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001949{
1950 status_t status = INVALID_OPERATION;
1951 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001952 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001953 if (thread != nullptr) {
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());
Andy Hung87c693c2023-07-06 20:56:16 -07001956 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001957 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1958 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1959 }
1960 }
1961 return status;
1962}
1963
Andy Hung8d31fd22023-06-26 19:20:57 -07001964status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001965{
1966 status_t status = INVALID_OPERATION;
1967 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001968 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001969 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001970 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001971 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001972 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001973 if (status == NO_ERROR) {
1974 mDualMonoMode = mode;
1975 }
1976 }
1977 }
1978 return status;
1979}
1980
Andy Hung8d31fd22023-06-26 19:20:57 -07001981status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001982{
1983 status_t status = INVALID_OPERATION;
1984 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001985 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001986 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001987 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001988 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001989 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001990 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1991 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1992 }
1993 }
1994 return status;
1995}
1996
Andy Hung8d31fd22023-06-26 19:20:57 -07001997status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001998{
1999 status_t status = INVALID_OPERATION;
2000 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002001 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002002 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002003 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002004 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002005 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002006 if (status == NO_ERROR) {
2007 mAudioDescriptionMixLevel = leveldB;
2008 }
2009 }
2010 }
2011 return status;
2012}
2013
Andy Hung8d31fd22023-06-26 19:20:57 -07002014status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07002015 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002016{
2017 status_t status = INVALID_OPERATION;
2018 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002019 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002020 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002021 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002022 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002023 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002024 ALOGD_IF((status == NO_ERROR) &&
2025 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
2026 "%s: playbackRate inconsistent", __func__);
2027 }
2028 }
2029 return status;
2030}
2031
Andy Hung8d31fd22023-06-26 19:20:57 -07002032status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002033 const audio_playback_rate_t& playbackRate)
2034{
2035 status_t status = INVALID_OPERATION;
2036 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002037 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002038 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002039 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002040 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002041 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002042 if (status == NO_ERROR) {
2043 mPlaybackRateParameters = playbackRate;
2044 }
2045 }
2046 }
2047 return status;
2048}
2049
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002050//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002051bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07002052 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002053 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002054 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002055 /* Resume is pending if track was stopping before pause was called */
2056 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07002057 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002058 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002059 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002060
2061 return false;
2062}
2063
2064//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002065void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07002066 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002067 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07002068 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002069
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002070 // Other possibility of pending resume is stopping_1 state
2071 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002072 // drain being called.
2073 if (mState == STOPPING_1) {
2074 mResumeToStopping = false;
2075 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002076}
Andy Hunge10393e2015-06-12 13:59:33 -07002077
2078//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002079void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002080 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002081 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002082 // Make the kernel frametime available.
2083 const FrameTime ft{
2084 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2085 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2086 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2087 mKernelFrameTime.store(ft);
2088 if (!audio_is_linear_pcm(mFormat)) {
2089 return;
2090 }
2091
Andy Hung818e7a32016-02-16 18:08:07 -08002092 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002093 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002094
2095 // adjust server times and set drained state.
2096 //
2097 // Our timestamps are only updated when the track is on the Thread active list.
2098 // We need to ensure that tracks are not removed before full drain.
2099 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002100 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002101 bool checked = false;
2102 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2103 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2104 // Lookup the track frame corresponding to the sink frame position.
2105 if (local.mTimeNs[i] > 0) {
2106 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2107 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002108 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002109 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002110 checked = true;
2111 }
2112 }
Andy Hunge10393e2015-06-12 13:59:33 -07002113 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002114
Andy Hung93bb5732023-05-04 21:16:34 -07002115 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2116 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002117 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002118 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002119 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002120 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002121
2122 // Compute latency info.
2123 const bool useTrackTimestamp = !drained;
2124 const double latencyMs = useTrackTimestamp
2125 ? local.getOutputServerLatencyMs(sampleRate())
2126 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2127
2128 mServerLatencyFromTrack.store(useTrackTimestamp);
2129 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002130
Andy Hung62921122020-05-18 10:47:31 -07002131 if (mLogStartCountdown > 0
2132 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2133 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2134 {
2135 if (mLogStartCountdown > 1) {
2136 --mLogStartCountdown;
2137 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2138 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002139 // startup is the difference in times for the current timestamp and our start
2140 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002141 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002142 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002143 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2144 * 1e3 / mSampleRate;
2145 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2146 " localTime:%lld startTime:%lld"
2147 " localPosition:%lld startPosition:%lld",
2148 __func__, latencyMs, startUpMs,
2149 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002150 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002151 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002152 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002153 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002154 }
Andy Hung62921122020-05-18 10:47:31 -07002155 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002156 }
Andy Hunge10393e2015-06-12 13:59:33 -07002157}
2158
Andy Hung8d31fd22023-06-26 19:20:57 -07002159bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002160 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002161 if (thread != 0) {
2162 // Lock for updating mHapticPlaybackEnabled.
Andy Hungc5007f82023-08-29 14:26:09 -07002163 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002164 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002165 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002166 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002167 ALOGD("%s, haptic playback was %s for track %d",
2168 __func__, muted ? "muted" : "unmuted", mTrack->id());
2169 mTrack->setHapticPlaybackEnabled(!muted);
2170 return true;
jiabin57303cc2018-12-18 15:45:57 -08002171 }
2172 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002173 return false;
2174}
2175
Andy Hung8d31fd22023-06-26 19:20:57 -07002176binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002177 /*out*/ bool *ret) {
2178 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002179 return binder::Status::ok();
2180}
2181
Andy Hung8d31fd22023-06-26 19:20:57 -07002182binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002183 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002184 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002185 return binder::Status::ok();
2186}
2187
Eric Laurent81784c32012-11-19 14:55:58 -08002188// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002189#undef LOG_TAG
2190#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002191
Andy Hung8d31fd22023-06-26 19:20:57 -07002192/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002193sp<IAfOutputTrack> IAfOutputTrack::create(
2194 IAfPlaybackThread* playbackThread,
2195 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002196 uint32_t sampleRate,
2197 audio_format_t format,
2198 audio_channel_mask_t channelMask,
2199 size_t frameCount,
2200 const AttributionSourceState& attributionSource) {
2201 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002202 playbackThread,
2203 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002204 sampleRate,
2205 format,
2206 channelMask,
2207 frameCount,
2208 attributionSource);
2209}
2210
2211OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002212 IAfPlaybackThread* playbackThread,
2213 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002214 uint32_t sampleRate,
2215 audio_format_t format,
2216 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002217 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002218 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002219 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Andy Hung6b137d12024-08-27 22:35:17 +00002220 AUDIO_ATTRIBUTES_INITIALIZER ,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002221 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002222 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002223 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002224 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002225 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002226{
Eric Laurent81784c32012-11-19 14:55:58 -08002227 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002228 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002229 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002230 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002231 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002232 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002233 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002234 // since client and server are in the same process,
2235 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002236 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2237 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002238 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002239 mClientProxy->setSendLevel(0.0);
2240 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002241 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002242 ALOGW("%s(%d): Error creating output track on thread %d",
2243 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002244 }
2245}
2246
Andy Hung8d31fd22023-06-26 19:20:57 -07002247OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002248{
2249 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002250 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002251}
2252
Andy Hung8d31fd22023-06-26 19:20:57 -07002253status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002254 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002255{
2256 status_t status = Track::start(event, triggerSession);
2257 if (status != NO_ERROR) {
2258 return status;
2259 }
2260
2261 mActive = true;
2262 mRetryCount = 127;
2263 return status;
2264}
2265
Andy Hung8d31fd22023-06-26 19:20:57 -07002266void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002267{
2268 Track::stop();
2269 clearBufferQueue();
2270 mOutBuffer.frameCount = 0;
2271 mActive = false;
2272}
2273
Andy Hung8d31fd22023-06-26 19:20:57 -07002274ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002275{
Eric Laurent19952e12023-04-20 10:08:29 +02002276 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002277 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002278 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002279 // preload one silent buffer to trigger mixer on start()
2280 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2281 status_t status = mClientProxy->obtainBuffer(&buf);
2282 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2283 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2284 return 0;
2285 }
2286 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2287 mClientProxy->releaseBuffer(&buf);
2288
2289 (void) start();
2290
2291 // wait for HAL stream to start before sending actual audio. Doing this on each
2292 // OutputTrack makes that playback start on all output streams is synchronized.
2293 // If another OutputTrack has already started it can underrun but this is OK
2294 // as only silence has been played so far and the retry count is very high on
2295 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002296 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002297 if (!pt->waitForHalStart()) {
2298 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2299 stop();
2300 return 0;
2301 }
2302
2303 // enqueue the first buffer and exit so that other OutputTracks will also start before
2304 // write() is called again and this buffer actually consumed.
2305 Buffer firstBuffer;
2306 firstBuffer.frameCount = frames;
2307 firstBuffer.raw = data;
2308 queueBuffer(firstBuffer);
2309 return frames;
2310 } else {
2311 (void) start();
2312 }
2313 }
2314
Eric Laurent81784c32012-11-19 14:55:58 -08002315 Buffer *pInBuffer;
2316 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002317 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002318 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002319 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002320 while (waitTimeLeftMs) {
2321 // First write pending buffers, then new data
2322 if (mBufferQueue.size()) {
2323 pInBuffer = mBufferQueue.itemAt(0);
2324 } else {
2325 pInBuffer = &inBuffer;
2326 }
2327
2328 if (pInBuffer->frameCount == 0) {
2329 break;
2330 }
2331
2332 if (mOutBuffer.frameCount == 0) {
2333 mOutBuffer.frameCount = pInBuffer->frameCount;
2334 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002335 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002336 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002337 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2338 __func__, mId,
2339 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002340 break;
2341 }
2342 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2343 if (waitTimeLeftMs >= waitTimeMs) {
2344 waitTimeLeftMs -= waitTimeMs;
2345 } else {
2346 waitTimeLeftMs = 0;
2347 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002348 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002349 deferRestartIfDisabled();
Eric Laurent4d231dc2016-03-11 18:38:23 -08002350 continue;
2351 }
Eric Laurent81784c32012-11-19 14:55:58 -08002352 }
2353
2354 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2355 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002356 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002357 Proxy::Buffer buf;
2358 buf.mFrameCount = outFrames;
2359 buf.mRaw = NULL;
2360 mClientProxy->releaseBuffer(&buf);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002361 deferRestartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002362 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002363 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002364 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002365 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002366
2367 if (pInBuffer->frameCount == 0) {
2368 if (mBufferQueue.size()) {
2369 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002370 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002371 if (pInBuffer != &inBuffer) {
2372 delete pInBuffer;
2373 }
Andy Hung9d84af52018-09-12 18:03:44 -07002374 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2375 __func__, mId,
2376 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002377 } else {
2378 break;
2379 }
2380 }
2381 }
2382
2383 // If we could not write all frames, allocate a buffer and queue it for next time.
2384 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002385 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002386 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002387 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002388 }
2389 }
2390
Andy Hungc25b84a2015-01-14 19:04:10 -08002391 // Calling write() with a 0 length buffer means that no more data will be written:
2392 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2393 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2394 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002395 }
2396
Andy Hung1c86ebe2018-05-29 20:29:08 -07002397 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002398}
2399
Andy Hung8d31fd22023-06-26 19:20:57 -07002400void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002401
2402 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2403 Buffer *pInBuffer = new Buffer;
2404 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2405 pInBuffer->mBuffer = malloc(bufferSize);
2406 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2407 "%s: Unable to malloc size %zu", __func__, bufferSize);
2408 pInBuffer->frameCount = inBuffer.frameCount;
2409 pInBuffer->raw = pInBuffer->mBuffer;
2410 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2411 mBufferQueue.add(pInBuffer);
2412 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2413 (int)mThreadIoHandle, mBufferQueue.size());
2414 // audio data is consumed (stored locally); set frameCount to 0.
2415 inBuffer.frameCount = 0;
2416 } else {
2417 ALOGW("%s(%d): thread %d no more overflow buffers",
2418 __func__, mId, (int)mThreadIoHandle);
2419 // TODO: return error for this.
2420 }
2421}
2422
Andy Hung8d31fd22023-06-26 19:20:57 -07002423void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002424{
Andy Hungc5007f82023-08-29 14:26:09 -07002425 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002426 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2427}
2428
Andy Hung8d31fd22023-06-26 19:20:57 -07002429void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002430 {
Andy Hungc5007f82023-08-29 14:26:09 -07002431 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002432 mTrackMetadatas = metadatas;
2433 }
2434 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2435 setMetadataHasChanged();
2436}
2437
Andy Hung8d31fd22023-06-26 19:20:57 -07002438status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002439 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2440{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002441 ClientProxy::Buffer buf;
2442 buf.mFrameCount = buffer->frameCount;
2443 struct timespec timeout;
2444 timeout.tv_sec = waitTimeMs / 1000;
2445 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2446 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2447 buffer->frameCount = buf.mFrameCount;
2448 buffer->raw = buf.mRaw;
2449 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002450}
2451
Andy Hung8d31fd22023-06-26 19:20:57 -07002452void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002453{
2454 size_t size = mBufferQueue.size();
2455
2456 for (size_t i = 0; i < size; i++) {
2457 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002458 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002459 delete pBuffer;
2460 }
2461 mBufferQueue.clear();
2462}
2463
Andy Hung8d31fd22023-06-26 19:20:57 -07002464void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002465{
2466 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2467 if (mActive && (flags & CBLK_DISABLED)) {
2468 start();
2469 }
2470}
Eric Laurent81784c32012-11-19 14:55:58 -08002471
Andy Hung9d84af52018-09-12 18:03:44 -07002472// ----------------------------------------------------------------------------
2473#undef LOG_TAG
2474#define LOG_TAG "AF::PatchTrack"
2475
Andy Hung8d31fd22023-06-26 19:20:57 -07002476/* static */
2477sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002478 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002479 audio_stream_type_t streamType,
2480 uint32_t sampleRate,
2481 audio_channel_mask_t channelMask,
2482 audio_format_t format,
2483 size_t frameCount,
2484 void* buffer,
2485 size_t bufferSize,
2486 audio_output_flags_t flags,
2487 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002488 size_t frameCountToBeReady, /** Default behaviour is to start
Andy Hung8d31fd22023-06-26 19:20:57 -07002489 * as soon as possible to have
2490 * the lowest possible latency
guonaichao3acc9b12024-06-07 09:27:21 +08002491 * even if it might glitch. */
Andy Hung6b137d12024-08-27 22:35:17 +00002492 float speed,
2493 float volume)
Andy Hung8d31fd22023-06-26 19:20:57 -07002494{
2495 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002496 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002497 streamType,
2498 sampleRate,
2499 channelMask,
2500 format,
2501 frameCount,
2502 buffer,
2503 bufferSize,
2504 flags,
2505 timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002506 frameCountToBeReady,
Andy Hung6b137d12024-08-27 22:35:17 +00002507 speed,
2508 volume);
Andy Hung8d31fd22023-06-26 19:20:57 -07002509}
2510
Andy Hung87c693c2023-07-06 20:56:16 -07002511PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002512 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002513 uint32_t sampleRate,
2514 audio_channel_mask_t channelMask,
2515 audio_format_t format,
2516 size_t frameCount,
2517 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002518 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002519 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002520 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002521 size_t frameCountToBeReady,
Andy Hung6b137d12024-08-27 22:35:17 +00002522 float speed,
2523 float volume)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002524 : Track(playbackThread, NULL, streamType,
Andy Hung6b137d12024-08-27 22:35:17 +00002525 AUDIO_ATTRIBUTES_INITIALIZER,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002526 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002527 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002528 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Andy Hung6b137d12024-08-27 22:35:17 +00002529 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed,
2530 false /*isSpatialized*/, false /*isBitPerfect*/, volume),
guonaichao3acc9b12024-06-07 09:27:21 +08002531 PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
2532 true /*clientInServer*/) : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002533 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002534{
guonaichao3acc9b12024-06-07 09:27:21 +08002535 if (mProxy != nullptr) {
2536 sp<AudioTrackClientProxy>::cast(mProxy)->setPlaybackRate({
2537 /* .mSpeed = */ speed,
2538 /* .mPitch = */ AUDIO_TIMESTRETCH_PITCH_NORMAL,
2539 /* .mStretchMode = */ AUDIO_TIMESTRETCH_STRETCH_DEFAULT,
2540 /* .mFallbackMode = */ AUDIO_TIMESTRETCH_FALLBACK_FAIL
2541 });
2542 }
Andy Hung9d84af52018-09-12 18:03:44 -07002543 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2544 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002545 (int)mPeerTimeout.tv_sec,
2546 (int)(mPeerTimeout.tv_nsec / 1000000));
2547}
2548
Andy Hung8d31fd22023-06-26 19:20:57 -07002549PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002550{
Andy Hungabfab202019-03-07 19:45:54 -08002551 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002552}
2553
Andy Hung8d31fd22023-06-26 19:20:57 -07002554size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002555{
2556 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2557 return std::numeric_limits<size_t>::max();
2558 } else {
2559 return Track::framesReady();
2560 }
2561}
2562
Andy Hung8d31fd22023-06-26 19:20:57 -07002563status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002564 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002565{
2566 status_t status = Track::start(event, triggerSession);
2567 if (status != NO_ERROR) {
2568 return status;
2569 }
2570 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2571 return status;
2572}
2573
Eric Laurent83b88082014-06-20 18:31:16 -07002574// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002575status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002576 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002577{
Andy Hung9d84af52018-09-12 18:03:44 -07002578 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002579 Proxy::Buffer buf;
2580 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002581 if (ATRACE_ENABLED()) {
2582 std::string traceName("PTnReq");
2583 traceName += std::to_string(id());
2584 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2585 }
Eric Laurent83b88082014-06-20 18:31:16 -07002586 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002587 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002588 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002589 if (ATRACE_ENABLED()) {
2590 std::string traceName("PTnObt");
2591 traceName += std::to_string(id());
2592 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2593 }
Eric Laurent83b88082014-06-20 18:31:16 -07002594 if (buf.mFrameCount == 0) {
2595 return WOULD_BLOCK;
2596 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002597 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002598 return status;
2599}
2600
Andy Hung8d31fd22023-06-26 19:20:57 -07002601void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002602{
Andy Hung9d84af52018-09-12 18:03:44 -07002603 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002604 Proxy::Buffer buf;
2605 buf.mFrameCount = buffer->frameCount;
2606 buf.mRaw = buffer->raw;
2607 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002608 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002609}
2610
Andy Hung8d31fd22023-06-26 19:20:57 -07002611status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002612 const struct timespec *timeOut)
2613{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002614 status_t status = NO_ERROR;
2615 static const int32_t kMaxTries = 5;
2616 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002617 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002618 do {
2619 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002620 deferRestartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002621 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002622 }
2623 status = mProxy->obtainBuffer(buffer, timeOut);
2624 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2625 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002626}
2627
Andy Hung8d31fd22023-06-26 19:20:57 -07002628void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002629{
2630 mProxy->releaseBuffer(buffer);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002631 deferRestartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002632
2633 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2634 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2635 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2636 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002637 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002638 && audio_is_linear_pcm(mFormat)
2639 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002640 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002641 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002642 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002643 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2644 / playbackThread->sampleRate();
2645 if (framesReady() < frameCount) {
2646 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002647 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002648 }
2649 }
2650 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002651}
2652
Andy Hung8d31fd22023-06-26 19:20:57 -07002653void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002654{
Eric Laurent83b88082014-06-20 18:31:16 -07002655 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002656 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002657 start();
2658 }
Eric Laurent83b88082014-06-20 18:31:16 -07002659}
2660
Eric Laurent81784c32012-11-19 14:55:58 -08002661// ----------------------------------------------------------------------------
2662// Record
2663// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002664
2665
Andy Hung9d84af52018-09-12 18:03:44 -07002666#undef LOG_TAG
2667#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002668
Andy Hunga5a7fc92023-06-23 19:27:19 -07002669class RecordHandle : public android::media::BnAudioRecord {
2670public:
Andy Hungd29af632023-06-23 19:27:19 -07002671 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002672 ~RecordHandle() override;
2673 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2674 int /*audio_session_t*/ triggerSession) final;
2675 binder::Status stop() final;
2676 binder::Status getActiveMicrophones(
2677 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2678 binder::Status setPreferredMicrophoneDirection(
2679 int /*audio_microphone_direction_t*/ direction) final;
2680 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2681 binder::Status shareAudioHistory(
2682 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2683
2684private:
Andy Hungd29af632023-06-23 19:27:19 -07002685 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002686
2687 // for use from destructor
2688 void stop_nonvirtual();
2689};
2690
2691/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002692sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2693 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002694 return sp<RecordHandle>::make(recordTrack);
2695}
2696
2697RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002698 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002699 : BnAudioRecord(),
2700 mRecordTrack(recordTrack)
2701{
Andy Hung225aef62022-12-06 16:33:20 -08002702 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -07002703 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -08002704}
2705
Andy Hunga5a7fc92023-06-23 19:27:19 -07002706RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002707 stop_nonvirtual();
2708 mRecordTrack->destroy();
2709}
2710
Andy Hunga5a7fc92023-06-23 19:27:19 -07002711binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002712 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002713 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002714 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002715 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002716}
2717
Andy Hunga5a7fc92023-06-23 19:27:19 -07002718binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002719 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002720 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002721}
2722
Andy Hunga5a7fc92023-06-23 19:27:19 -07002723void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002724 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002725 mRecordTrack->stop();
2726}
2727
Andy Hunga5a7fc92023-06-23 19:27:19 -07002728binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002729 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002730 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002731 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002732}
2733
Andy Hunga5a7fc92023-06-23 19:27:19 -07002734binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002735 int /*audio_microphone_direction_t*/ direction) {
2736 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002737 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002738 static_cast<audio_microphone_direction_t>(direction)));
2739}
2740
Andy Hunga5a7fc92023-06-23 19:27:19 -07002741binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002742 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002743 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002744}
2745
Andy Hunga5a7fc92023-06-23 19:27:19 -07002746binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002747 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2748 return binderStatusFromStatusT(
2749 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2750}
2751
Eric Laurent81784c32012-11-19 14:55:58 -08002752// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002753#undef LOG_TAG
2754#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002755
Andy Hung8d31fd22023-06-26 19:20:57 -07002756
Andy Hung99b1ba62023-07-14 11:00:08 -07002757/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002758sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002759 const sp<Client>& client,
2760 const audio_attributes_t& attr,
2761 uint32_t sampleRate,
2762 audio_format_t format,
2763 audio_channel_mask_t channelMask,
2764 size_t frameCount,
2765 void* buffer,
2766 size_t bufferSize,
2767 audio_session_t sessionId,
2768 pid_t creatorPid,
2769 const AttributionSourceState& attributionSource,
2770 audio_input_flags_t flags,
2771 track_type type,
2772 audio_port_handle_t portId,
2773 int32_t startFrames)
2774{
2775 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002776 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002777 client,
2778 attr,
2779 sampleRate,
2780 format,
2781 channelMask,
2782 frameCount,
2783 buffer,
2784 bufferSize,
2785 sessionId,
2786 creatorPid,
2787 attributionSource,
2788 flags,
2789 type,
2790 portId,
2791 startFrames);
2792}
2793
Glenn Kasten05997e22014-03-13 15:08:33 -07002794// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002795RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002796 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002797 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002798 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002799 uint32_t sampleRate,
2800 audio_format_t format,
2801 audio_channel_mask_t channelMask,
2802 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002803 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002804 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002805 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002806 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002807 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002808 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002809 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002810 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002811 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002812 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002813 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002814 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002815 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002816 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002817 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002818 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002819 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002820 type, portId,
2821 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002822 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002823 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002824 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002825 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002826 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002827 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002828{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002829 if (mCblk == NULL) {
2830 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002831 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002832
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002833 if (!isDirect()) {
2834 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002835 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002836 channelMask, format, sampleRate);
2837 // Check if the RecordBufferConverter construction was successful.
2838 // If not, don't continue with construction.
2839 //
2840 // NOTE: It would be extremely rare that the record track cannot be created
2841 // for the current device, but a pending or future device change would make
2842 // the record track configuration valid.
2843 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002844 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002845 return;
2846 }
Andy Hung97a893e2015-03-29 01:03:07 -07002847 }
2848
Andy Hung6ae58432016-02-16 18:32:24 -08002849 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002850 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002851
Andy Hung97a893e2015-03-29 01:03:07 -07002852 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002853
Eric Laurent05067782016-06-01 18:27:28 -07002854 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002855 ALOG_ASSERT(thread->fastTrackAvailable());
2856 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002857 } else {
2858 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002859 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002860 }
Andy Hung8946a282018-04-19 20:04:56 -07002861#ifdef TEE_SINK
2862 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2863 + "_" + std::to_string(mId)
2864 + "_R");
2865#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002866
2867 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002868 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002869}
2870
Andy Hung8d31fd22023-06-26 19:20:57 -07002871RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002872{
Andy Hung9d84af52018-09-12 18:03:44 -07002873 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002874 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002875 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002876}
2877
Andy Hung8d31fd22023-06-26 19:20:57 -07002878status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002879{
2880 status_t status = TrackBase::initCheck();
2881 if (status == NO_ERROR && mServerProxy == 0) {
2882 status = BAD_VALUE;
2883 }
2884 return status;
2885}
2886
Eric Laurent81784c32012-11-19 14:55:58 -08002887// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002888status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002889{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002890 ServerProxy::Buffer buf;
2891 buf.mFrameCount = buffer->frameCount;
2892 status_t status = mServerProxy->obtainBuffer(&buf);
2893 buffer->frameCount = buf.mFrameCount;
2894 buffer->raw = buf.mRaw;
2895 if (buf.mFrameCount == 0) {
2896 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002897 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002898 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002899 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002900}
2901
Andy Hung8d31fd22023-06-26 19:20:57 -07002902status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002903 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002904{
Andy Hung87c693c2023-07-06 20:56:16 -07002905 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002906 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002907 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002908 return recordThread->start(this, event, triggerSession);
2909 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002910 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2911 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002912 }
2913}
2914
Andy Hung8d31fd22023-06-26 19:20:57 -07002915void RecordTrack::stop()
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 Laurent83b88082014-06-20 18:31:16 -07002920 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002921 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002922 }
2923 }
2924}
2925
Andy Hung8d31fd22023-06-26 19:20:57 -07002926void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002927{
Andy Hung8d31fd22023-06-26 19:20:57 -07002928 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002929 sp<RecordTrack> keep(this);
2930 {
Andy Hungce685402018-10-05 17:23:27 -07002931 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002932 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002933 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07002934 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002935 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002936 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002937 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002938 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002939 }
Andy Hungce685402018-10-05 17:23:27 -07002940 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2941 }
2942 // APM portid/client management done outside of lock.
2943 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2944 if (isExternalTrack()) {
2945 switch (priorState) {
2946 case ACTIVE: // invalidated while still active
2947 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2948 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2949 AudioSystem::stopInput(mPortId);
2950 break;
2951
2952 case STARTING_1: // invalidated/start-aborted and startInput not successful
2953 case PAUSED: // OK, not active
2954 case IDLE: // OK, not active
2955 break;
2956
2957 case STOPPED: // unexpected (destroyed)
2958 default:
2959 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2960 }
2961 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002962 }
2963 }
2964}
2965
Andy Hung8d31fd22023-06-26 19:20:57 -07002966void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002967{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002968 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002969 // FIXME should use proxy, and needs work
2970 audio_track_cblk_t* cblk = mCblk;
2971 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2972 android_atomic_release_store(0x40000000, &cblk->mFutex);
2973 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002974 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002975}
2976
Eric Laurent81784c32012-11-19 14:55:58 -08002977
Andy Hung8d31fd22023-06-26 19:20:57 -07002978void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002979{
Eric Laurent973db022018-11-20 14:54:31 -08002980 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002981 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002982 " Server FrmCnt FrmRdy Sil%s\n",
2983 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002984}
2985
Andy Hung8d31fd22023-06-26 19:20:57 -07002986void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002987{
Eric Laurent973db022018-11-20 14:54:31 -08002988 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002989 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002990 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002991 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002992 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002993 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002994 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002995 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002996 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002997 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002998 mCblk->mFlags,
2999
Eric Laurent81784c32012-11-19 14:55:58 -08003000 mFormat,
3001 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003002 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003003 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08003004
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003005 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07003006 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07003007 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07003008 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003009 );
Andy Hung000adb52018-06-01 15:43:26 -07003010 if (isServerLatencySupported()) {
3011 double latencyMs;
3012 bool fromTrack;
3013 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
3014 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
3015 // or 'k' if estimated from kernel (usually for debugging).
3016 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
3017 } else {
3018 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
3019 }
3020 }
3021 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08003022}
3023
Andy Hung93bb5732023-05-04 21:16:34 -07003024// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07003025void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07003026 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003027{
Andy Hung93bb5732023-05-04 21:16:34 -07003028 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07003029 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07003030 if (threadBase != 0) {
3031 // TODO: use actual buffer filling status instead of 2 buffers when info is available
3032 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07003033 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003034 }
Andy Hung93bb5732023-05-04 21:16:34 -07003035
3036 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003037}
3038
Andy Hung8d31fd22023-06-26 19:20:57 -07003039void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003040{
Andy Hung93bb5732023-05-04 21:16:34 -07003041 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003042}
3043
Andy Hung8d31fd22023-06-26 19:20:57 -07003044void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08003045 int64_t trackFramesReleased, int64_t sourceFramesRead,
3046 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
3047{
Andy Hung30282562018-08-08 18:27:03 -07003048 // Make the kernel frametime available.
3049 const FrameTime ft{
3050 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
3051 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
3052 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
3053 mKernelFrameTime.store(ft);
3054 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05003055 // Stream is direct, return provided timestamp with no conversion
3056 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07003057 return;
3058 }
3059
Andy Hung3f0c9022016-01-15 17:49:46 -08003060 ExtendedTimestamp local = timestamp;
3061
3062 // Convert HAL frames to server-side track frames at track sample rate.
3063 // We use trackFramesReleased and sourceFramesRead as an anchor point.
3064 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
3065 if (local.mTimeNs[i] != 0) {
3066 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
3067 const int64_t relativeTrackFrames = relativeServerFrames
3068 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3069 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3070 }
3071 }
Andy Hung6ae58432016-02-16 18:32:24 -08003072 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003073
3074 // Compute latency info.
3075 const bool useTrackTimestamp = true; // use track unless debugging.
3076 const double latencyMs = - (useTrackTimestamp
3077 ? local.getOutputServerLatencyMs(sampleRate())
3078 : timestamp.getOutputServerLatencyMs(halSampleRate));
3079
3080 mServerLatencyFromTrack.store(useTrackTimestamp);
3081 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003082}
Eric Laurent83b88082014-06-20 18:31:16 -07003083
Andy Hung8d31fd22023-06-26 19:20:57 -07003084status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07003085 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003086{
Andy Hung87c693c2023-07-06 20:56:16 -07003087 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003088 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003089 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003090 return recordThread->getActiveMicrophones(activeMicrophones);
3091 } else {
3092 return BAD_VALUE;
3093 }
3094}
3095
Andy Hung8d31fd22023-06-26 19:20:57 -07003096status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003097 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003098 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003099 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003100 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003101 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003102 } else {
3103 return BAD_VALUE;
3104 }
3105}
3106
Andy Hung8d31fd22023-06-26 19:20:57 -07003107status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003108 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003109 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003110 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003111 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003112 } else {
3113 return BAD_VALUE;
3114 }
3115}
3116
Andy Hung8d31fd22023-06-26 19:20:57 -07003117status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003118 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3119
3120 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3121 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3122 if (callingUid != mUid || callingPid != mCreatorPid) {
3123 return PERMISSION_DENIED;
3124 }
3125
Svet Ganov33761132021-05-13 22:51:08 +00003126 AttributionSourceState attributionSource{};
3127 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3128 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3129 attributionSource.token = sp<BBinder>::make();
3130 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003131 return PERMISSION_DENIED;
3132 }
3133
Andy Hung87c693c2023-07-06 20:56:16 -07003134 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003135 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003136 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003137 status_t status = recordThread->shareAudioHistory(
3138 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3139 if (status == NO_ERROR) {
3140 mSharedAudioPackageName = sharedAudioPackageName;
3141 }
3142 return status;
3143 } else {
3144 return BAD_VALUE;
3145 }
3146}
3147
Andy Hung8d31fd22023-06-26 19:20:57 -07003148void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003149{
3150
3151 // Do not forward PatchRecord metadata with unspecified audio source
3152 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3153 return;
3154 }
3155
3156 // No track is invalid as this is called after prepareTrack_l in the same critical section
3157 record_track_metadata_v7_t metadata;
3158 metadata.base = {
3159 .source = mAttr.source,
3160 .gain = 1, // capture tracks do not have volumes
3161 };
3162 metadata.channel_mask = mChannelMask;
3163 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3164
3165 *backInserter++ = metadata;
3166}
Eric Laurentec376dc2021-04-08 20:41:22 +02003167
Andy Hung9d84af52018-09-12 18:03:44 -07003168// ----------------------------------------------------------------------------
3169#undef LOG_TAG
3170#define LOG_TAG "AF::PatchRecord"
3171
Andy Hung8d31fd22023-06-26 19:20:57 -07003172/* static */
3173sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003174 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003175 uint32_t sampleRate,
3176 audio_channel_mask_t channelMask,
3177 audio_format_t format,
3178 size_t frameCount,
3179 void *buffer,
3180 size_t bufferSize,
3181 audio_input_flags_t flags,
3182 const Timeout& timeout,
3183 audio_source_t source)
3184{
3185 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003186 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003187 sampleRate,
3188 channelMask,
3189 format,
3190 frameCount,
3191 buffer,
3192 bufferSize,
3193 flags,
3194 timeout,
3195 source);
3196}
3197
Andy Hung87c693c2023-07-06 20:56:16 -07003198PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003199 uint32_t sampleRate,
3200 audio_channel_mask_t channelMask,
3201 audio_format_t format,
3202 size_t frameCount,
3203 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003204 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003205 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003206 const Timeout& timeout,
3207 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003208 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003209 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003210 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003211 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003212 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003213 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3214 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003215 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003216{
Andy Hung9d84af52018-09-12 18:03:44 -07003217 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3218 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003219 (int)mPeerTimeout.tv_sec,
3220 (int)(mPeerTimeout.tv_nsec / 1000000));
3221}
3222
Andy Hung8d31fd22023-06-26 19:20:57 -07003223PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003224{
Andy Hungabfab202019-03-07 19:45:54 -08003225 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003226}
3227
Mikhail Naganov8296c252019-09-25 14:59:54 -07003228static size_t writeFramesHelper(
3229 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3230{
3231 AudioBufferProvider::Buffer patchBuffer;
3232 patchBuffer.frameCount = frameCount;
3233 auto status = dest->getNextBuffer(&patchBuffer);
3234 if (status != NO_ERROR) {
3235 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3236 __func__, status, strerror(-status));
3237 return 0;
3238 }
3239 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3240 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3241 size_t framesWritten = patchBuffer.frameCount;
3242 dest->releaseBuffer(&patchBuffer);
3243 return framesWritten;
3244}
3245
3246// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003247size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003248 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3249{
3250 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3251 // On buffer wrap, the buffer frame count will be less than requested,
3252 // when this happens a second buffer needs to be used to write the leftover audio
3253 const size_t framesLeft = frameCount - framesWritten;
3254 if (framesWritten != 0 && framesLeft != 0) {
3255 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3256 framesLeft, frameSize);
3257 }
3258 return framesWritten;
3259}
3260
Eric Laurent83b88082014-06-20 18:31:16 -07003261// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003262status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003263 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003264{
Andy Hung9d84af52018-09-12 18:03:44 -07003265 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003266 Proxy::Buffer buf;
3267 buf.mFrameCount = buffer->frameCount;
3268 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3269 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003270 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003271 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003272 if (ATRACE_ENABLED()) {
3273 std::string traceName("PRnObt");
3274 traceName += std::to_string(id());
3275 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3276 }
Eric Laurent83b88082014-06-20 18:31:16 -07003277 if (buf.mFrameCount == 0) {
3278 return WOULD_BLOCK;
3279 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003280 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003281 return status;
3282}
3283
Andy Hung8d31fd22023-06-26 19:20:57 -07003284void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003285{
Andy Hung9d84af52018-09-12 18:03:44 -07003286 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003287 Proxy::Buffer buf;
3288 buf.mFrameCount = buffer->frameCount;
3289 buf.mRaw = buffer->raw;
3290 mPeerProxy->releaseBuffer(&buf);
3291 TrackBase::releaseBuffer(buffer);
3292}
3293
Andy Hung8d31fd22023-06-26 19:20:57 -07003294status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003295 const struct timespec *timeOut)
3296{
3297 return mProxy->obtainBuffer(buffer, timeOut);
3298}
3299
Andy Hung8d31fd22023-06-26 19:20:57 -07003300void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003301{
3302 mProxy->releaseBuffer(buffer);
3303}
3304
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003305#undef LOG_TAG
3306#define LOG_TAG "AF::PthrPatchRecord"
3307
3308static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3309{
3310 void *ptr = nullptr;
3311 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003312 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003313}
3314
Andy Hung8d31fd22023-06-26 19:20:57 -07003315/* static */
3316sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003317 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003318 uint32_t sampleRate,
3319 audio_channel_mask_t channelMask,
3320 audio_format_t format,
3321 size_t frameCount,
3322 audio_input_flags_t flags,
3323 audio_source_t source)
3324{
3325 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003326 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003327 sampleRate,
3328 channelMask,
3329 format,
3330 frameCount,
3331 flags,
3332 source);
3333}
3334
3335PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003336 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003337 uint32_t sampleRate,
3338 audio_channel_mask_t channelMask,
3339 audio_format_t format,
3340 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003341 audio_input_flags_t flags,
3342 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003343 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003344 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003345 mPatchRecordAudioBufferProvider(*this),
3346 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3347 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3348{
3349 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3350}
3351
Andy Hung8d31fd22023-06-26 19:20:57 -07003352sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003353 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003354{
3355 *thread = mThread.promote();
3356 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003357 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07003358 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07003359 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003360}
3361
3362// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003363status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003364 Proxy::Buffer* buffer, const struct timespec* timeOut)
3365{
3366 if (mUnconsumedFrames) {
3367 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3368 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3369 return PatchRecord::obtainBuffer(buffer, timeOut);
3370 }
3371
3372 // Otherwise, execute a read from HAL and write into the buffer.
3373 nsecs_t startTimeNs = 0;
3374 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3375 // Will need to correct timeOut by elapsed time.
3376 startTimeNs = systemTime();
3377 }
3378 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3379 buffer->mFrameCount = 0;
3380 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003381 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003382 sp<StreamInHalInterface> stream = obtainStream(&thread);
3383 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3384
3385 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003386 size_t bytesRead = 0;
3387 {
3388 ATRACE_NAME("read");
3389 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3390 if (result != NO_ERROR) goto stream_error;
3391 if (bytesRead == 0) return NO_ERROR;
3392 }
3393
3394 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003395 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003396 mReadBytes += bytesRead;
3397 mReadError = NO_ERROR;
3398 }
3399 mReadCV.notify_one();
3400 // writeFrames handles wraparound and should write all the provided frames.
3401 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3402 buffer->mFrameCount = writeFrames(
3403 &mPatchRecordAudioBufferProvider,
3404 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3405 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3406 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3407 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003408 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003409 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003410 // Correct the timeout by elapsed time.
3411 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003412 if (newTimeOutNs < 0) newTimeOutNs = 0;
3413 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3414 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003415 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003416 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003417 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003418
3419stream_error:
3420 stream->standby();
3421 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003422 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003423 mReadError = result;
3424 }
3425 mReadCV.notify_one();
3426 return result;
3427}
3428
Andy Hung8d31fd22023-06-26 19:20:57 -07003429void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003430{
3431 if (buffer->mFrameCount <= mUnconsumedFrames) {
3432 mUnconsumedFrames -= buffer->mFrameCount;
3433 } else {
3434 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3435 buffer->mFrameCount, mUnconsumedFrames);
3436 mUnconsumedFrames = 0;
3437 }
3438 PatchRecord::releaseBuffer(buffer);
3439}
3440
3441// AudioBufferProvider and Source methods are called on RecordThread
3442// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3443// and 'releaseBuffer' are stubbed out and ignore their input.
3444// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3445// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003446status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003447 void* buffer, size_t bytes, size_t* read)
3448{
3449 bytes = std::min(bytes, mFrameCount * mFrameSize);
3450 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003451 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003452 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3453 if (mReadError != NO_ERROR) {
3454 mLastReadFrames = 0;
3455 return mReadError;
3456 }
3457 *read = std::min(bytes, mReadBytes);
3458 mReadBytes -= *read;
3459 }
3460 mLastReadFrames = *read / mFrameSize;
3461 memset(buffer, 0, *read);
3462 return 0;
3463}
3464
Andy Hung8d31fd22023-06-26 19:20:57 -07003465status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003466 int64_t* frames, int64_t* time)
3467{
Andy Hung87c693c2023-07-06 20:56:16 -07003468 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003469 sp<StreamInHalInterface> stream = obtainStream(&thread);
3470 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3471}
3472
Andy Hung8d31fd22023-06-26 19:20:57 -07003473status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003474{
3475 // RecordThread issues 'standby' command in two major cases:
3476 // 1. Error on read--this case is handled in 'obtainBuffer'.
3477 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3478 // output, this can only happen when the software patch
3479 // is being torn down. In this case, the RecordThread
3480 // will terminate and close the HAL stream.
3481 return 0;
3482}
3483
3484// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003485status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003486 AudioBufferProvider::Buffer* buffer)
3487{
3488 buffer->frameCount = mLastReadFrames;
3489 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3490 return NO_ERROR;
3491}
3492
Andy Hung8d31fd22023-06-26 19:20:57 -07003493void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003494 AudioBufferProvider::Buffer* buffer)
3495{
3496 buffer->frameCount = 0;
3497 buffer->raw = nullptr;
3498}
3499
Andy Hung9d84af52018-09-12 18:03:44 -07003500// ----------------------------------------------------------------------------
3501#undef LOG_TAG
3502#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003503
Andy Hung8d31fd22023-06-26 19:20:57 -07003504/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003505sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003506 const audio_attributes_t& attr,
3507 uint32_t sampleRate,
3508 audio_format_t format,
3509 audio_channel_mask_t channelMask,
3510 audio_session_t sessionId,
3511 bool isOut,
3512 const android::content::AttributionSourceState& attributionSource,
3513 pid_t creatorPid,
Andy Hung6b137d12024-08-27 22:35:17 +00003514 audio_port_handle_t portId,
3515 float volume)
Andy Hung8d31fd22023-06-26 19:20:57 -07003516{
3517 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003518 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003519 attr,
3520 sampleRate,
3521 format,
3522 channelMask,
3523 sessionId,
3524 isOut,
3525 attributionSource,
3526 creatorPid,
Andy Hung6b137d12024-08-27 22:35:17 +00003527 portId,
3528 volume);
Andy Hung8d31fd22023-06-26 19:20:57 -07003529}
3530
Andy Hung87c693c2023-07-06 20:56:16 -07003531MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003532 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003533 uint32_t sampleRate,
3534 audio_format_t format,
3535 audio_channel_mask_t channelMask,
3536 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003537 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003538 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003539 pid_t creatorPid,
Andy Hung6b137d12024-08-27 22:35:17 +00003540 audio_port_handle_t portId,
3541 float volume)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003542 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003543 channelMask, (size_t)0 /* frameCount */,
3544 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003545 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003546 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003547 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003548 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003549 TYPE_DEFAULT, portId,
3550 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003551 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Andy Hung6b137d12024-08-27 22:35:17 +00003552 mSilenced(false), mSilencedNotified(false), mVolume(volume)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003553{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003554 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003555 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Andy Hung6b137d12024-08-27 22:35:17 +00003556 if (isOut && (attr.usage == AUDIO_USAGE_CALL_ASSISTANT
3557 || attr.usage == AUDIO_USAGE_VIRTUAL_SOURCE)) {
3558 // Audio patch and call assistant volume are always max
3559 mVolume = 1.0f;
3560 }
Eric Laurent6acd1d42017-01-04 14:23:29 -08003561}
3562
Andy Hung8d31fd22023-06-26 19:20:57 -07003563MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003564{
3565}
3566
Andy Hung8d31fd22023-06-26 19:20:57 -07003567status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003568{
3569 return NO_ERROR;
3570}
3571
Andy Hung8d31fd22023-06-26 19:20:57 -07003572status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003573 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003574{
3575 return NO_ERROR;
3576}
3577
Andy Hung8d31fd22023-06-26 19:20:57 -07003578void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003579{
3580}
3581
3582// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003583status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003584{
3585 buffer->frameCount = 0;
3586 buffer->raw = nullptr;
3587 return INVALID_OPERATION;
3588}
3589
3590// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003591size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003592 return 0;
3593}
3594
Andy Hung8d31fd22023-06-26 19:20:57 -07003595int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003596{
3597 return 0;
3598}
3599
Andy Hung8d31fd22023-06-26 19:20:57 -07003600void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003601{
3602}
3603
Andy Hung8d31fd22023-06-26 19:20:57 -07003604void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003605{
3606 if (mMuteState == muteState) {
3607 // mute state did not change, do nothing
3608 return;
3609 }
3610
3611 status_t result = UNKNOWN_ERROR;
3612 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3613 if (mMuteEventExtras == nullptr) {
3614 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3615 }
3616 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3617 static_cast<int>(muteState));
3618
3619 result = audioManager->portEvent(mPortId,
3620 PLAYER_UPDATE_MUTED,
3621 mMuteEventExtras);
3622 }
3623
3624 if (result == OK) {
Andy Hung0e26ec62024-02-20 16:32:57 -08003625 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
3626 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popaec1788e2022-08-04 11:23:30 +02003627 mMuteState = muteState;
3628 } else {
3629 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3630 __func__,
3631 id(),
3632 mPortId,
3633 result);
3634 }
3635}
3636
Andy Hung8d31fd22023-06-26 19:20:57 -07003637void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003638{
Andy Hung6b137d12024-08-27 22:35:17 +00003639 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s %s\n",
3640 isOut() ? "Usg CT": "Source", isOut() ? "PortVol dB" : "");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003641}
3642
Andy Hung8d31fd22023-06-26 19:20:57 -07003643void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003644{
Eric Laurent973db022018-11-20 14:54:31 -08003645 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003646 mPid,
3647 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003648 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003649 mFormat,
3650 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003651 mSampleRate,
3652 mAttr.flags);
3653 if (isOut()) {
3654 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
Andy Hung6b137d12024-08-27 22:35:17 +00003655 result.appendFormat("%11.2g", 20.0 * log10(mVolume));
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003656 } else {
3657 result.appendFormat("%6x", mAttr.source);
3658 }
3659 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003660}
3661
Glenn Kasten63238ef2015-03-02 15:50:29 -08003662} // namespace android