blob: f8cfc1257a4ded95a1d5bb4e6aa82f5942315e1c [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 Hung8d31fd22023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700318 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700325 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
326 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung8d31fd22023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hunga5a7fc92023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hungd29af632023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hungd29af632023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hungd29af632023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hung225aef62022-12-06 16:33:20 -0800391 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -0700392 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -0800393}
394
Andy Hunga5a7fc92023-06-23 19:27:19 -0700395TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800396 // just stop the track on deletion, associated resources
397 // will be freed from the main thread once all pending buffers have
398 // been played. Unless it's not in the active track list, in which
399 // case we free everything now...
400 mTrack->destroy();
401}
402
Andy Hunga5a7fc92023-06-23 19:27:19 -0700403Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800404 std::optional<media::SharedFileRegion>* _aidl_return) {
405 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
406 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800407}
408
Andy Hunga5a7fc92023-06-23 19:27:19 -0700409Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800410 *_aidl_return = mTrack->start();
411 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800412}
413
Andy Hunga5a7fc92023-06-23 19:27:19 -0700414Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800415 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800416 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800417}
418
Andy Hunga5a7fc92023-06-23 19:27:19 -0700419Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800420 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800422}
423
Andy Hunga5a7fc92023-06-23 19:27:19 -0700424Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800425 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800426 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800427}
428
Andy Hunga5a7fc92023-06-23 19:27:19 -0700429Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800430 int32_t* _aidl_return) {
431 *_aidl_return = mTrack->attachAuxEffect(effectId);
432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hunga5a7fc92023-06-23 19:27:19 -0700435Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800436 int32_t* _aidl_return) {
437 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
438 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700439}
440
Andy Hunga5a7fc92023-06-23 19:27:19 -0700441Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800442 int32_t* _aidl_return) {
443 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
444 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800445}
446
Andy Hunga5a7fc92023-06-23 19:27:19 -0700447Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800448 int32_t* _aidl_return) {
449 AudioTimestamp legacy;
450 *_aidl_return = mTrack->getTimestamp(legacy);
451 if (*_aidl_return != OK) {
452 return Status::ok();
453 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000454
455 // restrict position modulo INT_MAX to avoid integer sanitization abort
456 legacy.mPosition &= INT_MAX;
457
Andy Hung973638a2020-12-08 20:47:45 -0800458 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800460}
461
Andy Hunga5a7fc92023-06-23 19:27:19 -0700462Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800463 mTrack->signal();
464 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800465}
466
Andy Hunga5a7fc92023-06-23 19:27:19 -0700467Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800468 const media::VolumeShaperConfiguration& configuration,
469 const media::VolumeShaperOperation& operation,
470 int32_t* _aidl_return) {
471 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
472 *_aidl_return = conf->readFromParcelable(configuration);
473 if (*_aidl_return != OK) {
474 return Status::ok();
475 }
476
477 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
478 *_aidl_return = op->readFromParcelable(operation);
479 if (*_aidl_return != OK) {
480 return Status::ok();
481 }
482
483 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
484 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700485}
486
Andy Hunga5a7fc92023-06-23 19:27:19 -0700487Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800488 int32_t id,
489 std::optional<media::VolumeShaperState>* _aidl_return) {
490 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
491 if (legacy == nullptr) {
492 _aidl_return->reset();
493 return Status::ok();
494 }
495 media::VolumeShaperState aidl;
496 legacy->writeToParcelable(&aidl);
497 *_aidl_return = aidl;
498 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800499}
500
Andy Hunga5a7fc92023-06-23 19:27:19 -0700501Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000502 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800503{
504 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
505 const status_t status = mTrack->getDualMonoMode(&mode)
506 ?: AudioValidator::validateDualMonoMode(mode);
507 if (status == OK) {
508 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
509 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
510 }
511 return binderStatusFromStatusT(status);
512}
513
Andy Hunga5a7fc92023-06-23 19:27:19 -0700514Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000515 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800516{
517 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
518 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
519 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
520 ?: mTrack->setDualMonoMode(localMonoMode));
521}
522
Andy Hunga5a7fc92023-06-23 19:27:19 -0700523Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800524{
525 float leveldB = -std::numeric_limits<float>::infinity();
526 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
527 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
528 if (status == OK) *_aidl_return = leveldB;
529 return binderStatusFromStatusT(status);
530}
531
Andy Hunga5a7fc92023-06-23 19:27:19 -0700532Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800533{
534 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
535 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
536}
537
Andy Hunga5a7fc92023-06-23 19:27:19 -0700538Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000539 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800540{
541 audio_playback_rate_t localPlaybackRate{};
542 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
543 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
544 if (status == NO_ERROR) {
545 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
546 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
547 }
548 return binderStatusFromStatusT(status);
549}
550
Andy Hunga5a7fc92023-06-23 19:27:19 -0700551Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000552 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800553{
554 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
555 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
556 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
557 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
558}
559
Eric Laurent81784c32012-11-19 14:55:58 -0800560// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800561// AppOp for audio playback
562// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700563
564// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700565sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700566 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000567 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700568 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800569{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700570 Vector<String16> packages;
571 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000572 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700573 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700574 if (packages.isEmpty()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000575 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700576 uid);
577 return nullptr;
578 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800579 }
580 // stream type has been filtered by audio policy to indicate whether it can be muted
581 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700582 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700583 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800584 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700585 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
586 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
587 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
588 id, attr.flags);
589 return nullptr;
590 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700591 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700592}
593
Andy Hung87c693c2023-07-06 20:56:16 -0700594OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700595 const AttributionSourceState& attributionSource,
596 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700597 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700598 mHasOpPlayAudio(true),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700599 mUsage((int32_t)usage),
600 mId(id),
601 mUid(uid),
602 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
603 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800604
Andy Hung8d31fd22023-06-26 19:20:57 -0700605OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800606{
607 if (mOpCallback != 0) {
608 mAppOpsManager.stopWatchingMode(mOpCallback);
609 }
610 mOpCallback.clear();
611}
612
Andy Hung8d31fd22023-06-26 19:20:57 -0700613void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700614{
Vlad Popad5859592023-08-02 18:36:04 -0700615 // make sure not to broadcast the initial state since it is not needed and could
616 // cause a deadlock since this method can be called with the mThread->mLock held
617 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000618 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700619 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000620 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
621 } else {
622 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700623 }
624}
625
Andy Hung8d31fd22023-06-26 19:20:57 -0700626bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800627 return mHasOpPlayAudio.load();
628}
629
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700630// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800631// - not called from constructor due to check on UID,
632// - not called from PlayAudioOpCallback because the callback is not installed in this case
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000633void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
634 const bool hasAppOps =
635 mPackageName.size() &&
636 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
637 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700638
639 bool shouldChange = !hasAppOps; // check if we need to update.
640 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000641 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000642 String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
Vlad Popad5859592023-08-02 18:36:04 -0700643 if (doBroadcast) {
644 auto thread = mThread.promote();
645 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
646 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hungc5007f82023-08-29 14:26:09 -0700647 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad5859592023-08-02 18:36:04 -0700648 thread->broadcast_l();
649 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700650 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800651 }
652}
653
Andy Hung8d31fd22023-06-26 19:20:57 -0700654OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800655 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
656{ }
657
Andy Hung8d31fd22023-06-26 19:20:57 -0700658void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800659 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800660 if (op != AppOpsManager::OP_PLAY_AUDIO) {
661 return;
662 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000663
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000664 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800665 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
666 if (monitor != NULL) {
Vlad Popad5859592023-08-02 18:36:04 -0700667 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800668 }
669}
670
Eric Laurent9066ad32019-05-20 14:40:10 -0700671// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700672void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700673 uid_t uid, Vector<String16>& packages)
674{
675 PermissionController permissionController;
676 permissionController.getPackagesForUid(uid, packages);
677}
678
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800679// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700680#undef LOG_TAG
681#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800682
Andy Hung8d31fd22023-06-26 19:20:57 -0700683/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700684sp<IAfTrack> IAfTrack::create(
685 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700686 const sp<Client>& client,
687 audio_stream_type_t streamType,
688 const audio_attributes_t& attr,
689 uint32_t sampleRate,
690 audio_format_t format,
691 audio_channel_mask_t channelMask,
692 size_t frameCount,
693 void *buffer,
694 size_t bufferSize,
695 const sp<IMemory>& sharedBuffer,
696 audio_session_t sessionId,
697 pid_t creatorPid,
698 const AttributionSourceState& attributionSource,
699 audio_output_flags_t flags,
700 track_type type,
701 audio_port_handle_t portId,
702 /** default behaviour is to start when there are as many frames
703 * ready as possible (aka. Buffer is full). */
704 size_t frameCountToBeReady,
705 float speed,
706 bool isSpatialized,
707 bool isBitPerfect) {
Andy Hung87c693c2023-07-06 20:56:16 -0700708 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700709 client,
710 streamType,
711 attr,
712 sampleRate,
713 format,
714 channelMask,
715 frameCount,
716 buffer,
717 bufferSize,
718 sharedBuffer,
719 sessionId,
720 creatorPid,
721 attributionSource,
722 flags,
723 type,
724 portId,
725 frameCountToBeReady,
726 speed,
727 isSpatialized,
728 isBitPerfect);
729}
730
Eric Laurent81784c32012-11-19 14:55:58 -0800731// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700732Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700733 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800734 const sp<Client>& client,
735 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700736 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800737 uint32_t sampleRate,
738 audio_format_t format,
739 audio_channel_mask_t channelMask,
740 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700741 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700742 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800743 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800744 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700745 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000746 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700747 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800748 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100749 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000750 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200751 float speed,
jiabinc658e452022-10-21 20:52:21 +0000752 bool isSpatialized,
753 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700754 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700755 // TODO: Using unsecurePointer() has some associated security pitfalls
756 // (see declaration for details).
757 // Either document why it is safe in this case or address the
758 // issue (e.g. by copying).
759 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700760 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700761 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000762 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700763 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800764 type,
765 portId,
766 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700767 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800768 // mRetryCount initialized later when needed
769 mSharedBuffer(sharedBuffer),
770 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700771 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800772 mAuxBuffer(NULL),
773 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700774 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700775 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700776 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700777 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700778 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800779 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800780 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700781 /* The track might not play immediately after being active, similarly as if its volume was 0.
782 * When the track starts playing, its volume will be computed. */
783 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800784 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700785 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000786 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200787 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000788 mIsSpatialized(isSpatialized),
789 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800790{
Eric Laurent83b88082014-06-20 18:31:16 -0700791 // client == 0 implies sharedBuffer == 0
792 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
793
Andy Hung9d84af52018-09-12 18:03:44 -0700794 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700795 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700796
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700797 if (mCblk == NULL) {
798 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800799 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700800
Svet Ganov33761132021-05-13 22:51:08 +0000801 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700802 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
803 ALOGE("%s(%d): no more tracks available", __func__, mId);
804 releaseCblk(); // this makes the track invalid.
805 return;
806 }
807
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700808 if (sharedBuffer == 0) {
809 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700810 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700811 } else {
812 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100813 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700814 }
815 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700816 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700817
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700818 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700819 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700820 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
821 // race with setSyncEvent(). However, if we call it, we cannot properly start
822 // static fast tracks (SoundPool) immediately after stopping.
823 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700824 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
825 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700826 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700827 // FIXME This is too eager. We allocate a fast track index before the
828 // fast track becomes active. Since fast tracks are a scarce resource,
829 // this means we are potentially denying other more important fast tracks from
830 // being created. It would be better to allocate the index dynamically.
831 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700832 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700833 }
Andy Hung8946a282018-04-19 20:04:56 -0700834
Dean Wheatley7b036912020-06-18 16:22:11 +1000835 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700836#ifdef TEE_SINK
837 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800838 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700839#endif
jiabin57303cc2018-12-18 15:45:57 -0800840
jiabineb3bda02020-06-30 14:07:03 -0700841 if (thread->supportsHapticPlayback()) {
842 // If the track is attached to haptic playback thread, it is potentially to have
843 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
844 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800845 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000846 std::string packageName = attributionSource.packageName.has_value() ?
847 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800848 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700849 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800850 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800851
852 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700853 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800854 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800855}
856
Andy Hung8d31fd22023-06-26 19:20:57 -0700857Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800858{
Andy Hung9d84af52018-09-12 18:03:44 -0700859 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700860
861 // The destructor would clear mSharedBuffer,
862 // but it will not push the decremented reference count,
863 // leaving the client's IMemory dangling indefinitely.
864 // This prevents that leak.
865 if (mSharedBuffer != 0) {
866 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700867 }
Eric Laurent81784c32012-11-19 14:55:58 -0800868}
869
Andy Hung8d31fd22023-06-26 19:20:57 -0700870status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700871{
872 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700873 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700874 status = NO_MEMORY;
875 }
876 return status;
877}
878
Andy Hung8d31fd22023-06-26 19:20:57 -0700879void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800880{
881 // NOTE: destroyTrack_l() can remove a strong reference to this Track
882 // by removing it from mTracks vector, so there is a risk that this Tracks's
883 // destructor is called. As the destructor needs to lock mLock,
884 // we must acquire a strong reference on this Track before locking mLock
885 // here so that the destructor is called only when exiting this function.
886 // On the other hand, as long as Track::destroy() is only called by
887 // TrackHandle destructor, the TrackHandle still holds a strong ref on
888 // this Track with its member mTrack.
889 sp<Track> keep(this);
890 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700891 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700892 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800893 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -0800894 audio_utils::unique_lock ul(thread->mutex());
895 thread->waitWhileThreadBusy_l(ul);
896
Andy Hung87c693c2023-07-06 20:56:16 -0700897 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700898 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000899 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700900 }
901 if (isExternalTrack() && !wasActive) {
Andy Hung6c498e92023-12-05 17:28:17 -0800902 // If the track is not active, the TrackHandle is responsible for
903 // releasing the port id, not the ThreadBase::threadLoop().
904 // At this point, there is no concurrency issue as the track is going away.
Eric Laurentd7fe0862018-07-14 16:48:01 -0700905 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800906 }
907 }
908}
909
Andy Hung8d31fd22023-06-26 19:20:57 -0700910void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800911{
Eric Laurent973db022018-11-20 14:54:31 -0800912 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700913 " Format Chn mask SRate "
914 "ST Usg CT "
915 " G db L dB R dB VS dB "
jiabin220eea12024-05-17 17:55:20 +0000916 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700917 "%s\n",
918 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800919}
920
Andy Hung8d31fd22023-06-26 19:20:57 -0700921void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800922{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700923 char trackType;
924 switch (mType) {
925 case TYPE_DEFAULT:
926 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700927 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700928 trackType = 'S'; // static
929 } else {
930 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800931 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700932 break;
933 case TYPE_PATCH:
934 trackType = 'P';
935 break;
936 default:
937 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800938 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700939
940 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700941 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700942 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700943 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700944 }
945
Eric Laurent81784c32012-11-19 14:55:58 -0800946 char nowInUnderrun;
947 switch (mObservedUnderruns.mBitFields.mMostRecent) {
948 case UNDERRUN_FULL:
949 nowInUnderrun = ' ';
950 break;
951 case UNDERRUN_PARTIAL:
952 nowInUnderrun = '<';
953 break;
954 case UNDERRUN_EMPTY:
955 nowInUnderrun = '*';
956 break;
957 default:
958 nowInUnderrun = '?';
959 break;
960 }
Andy Hungda540db2017-04-20 14:06:17 -0700961
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700962 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700963 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700964 case FS_INVALID:
965 fillingStatus = 'I';
966 break;
967 case FS_FILLING:
968 fillingStatus = 'f';
969 break;
970 case FS_FILLED:
971 fillingStatus = 'F';
972 break;
973 case FS_ACTIVE:
974 fillingStatus = 'A';
975 break;
976 default:
977 fillingStatus = '?';
978 break;
979 }
980
981 // clip framesReadySafe to max representation in dump
982 const size_t framesReadySafe =
983 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
984
985 // obtain volumes
986 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
987 const std::pair<float /* volume */, bool /* active */> vsVolume =
988 mVolumeHandler->getLastVolume();
989
990 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
991 // as it may be reduced by the application.
992 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
993 // Check whether the buffer size has been modified by the app.
994 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
995 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
996 ? 'e' /* error */ : ' ' /* identical */;
997
Eric Laurent973db022018-11-20 14:54:31 -0800998 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700999 "%08X %08X %6u "
1000 "%2u %3x %2x "
1001 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin220eea12024-05-17 17:55:20 +00001002 "%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
Marco Nelissenb2208842014-02-07 14:00:50 -08001003 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001004 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001005 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001006 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001007 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001008 mCblk->mFlags,
1009
Eric Laurent81784c32012-11-19 14:55:58 -08001010 mFormat,
1011 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001012 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001013
1014 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001015 mAttr.usage,
1016 mAttr.content_type,
1017
1018 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001019 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1020 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001021 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1022 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001023
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001024 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001025 bufferSizeInFrames,
1026 modifiedBufferChar,
1027 framesReadySafe,
1028 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001029 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001030 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001031 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
jiabin220eea12024-05-17 17:55:20 +00001032 isBitPerfect() ? "true" : "false",
1033 getInternalMute() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001034 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001035
1036 if (isServerLatencySupported()) {
1037 double latencyMs;
1038 bool fromTrack;
1039 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1040 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1041 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1042 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001043 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001044 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001045 }
1046 }
1047 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001048}
1049
Andy Hung8d31fd22023-06-26 19:20:57 -07001050uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001051 return mAudioTrackServerProxy->getSampleRate();
1052}
1053
Eric Laurent81784c32012-11-19 14:55:58 -08001054// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001055status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001056{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001057 ServerProxy::Buffer buf;
1058 size_t desiredFrames = buffer->frameCount;
1059 buf.mFrameCount = desiredFrames;
1060 status_t status = mServerProxy->obtainBuffer(&buf);
1061 buffer->frameCount = buf.mFrameCount;
1062 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001063 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001064 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001065 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001066 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001067 } else {
1068 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001069 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001070 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001071}
1072
Andy Hung8d31fd22023-06-26 19:20:57 -07001073void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001074{
1075 interceptBuffer(*buffer);
1076 TrackBase::releaseBuffer(buffer);
1077}
1078
1079// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001080void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001081 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001082 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001083 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001084 if (frameCount == 0) {
1085 return; // No audio to intercept.
1086 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1087 // does not allow 0 frame size request contrary to getNextBuffer
1088 }
Jiabin Huang73f97052023-12-12 20:08:03 +00001089 TeePatches teePatches;
1090 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1091 // Cache a copy of tee patches in case it is updated while using.
1092 teePatches = mTeePatches;
1093 mTeePatchesRWLock.unlock();
1094 }
1095 for (auto& teePatch : teePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001096 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001097 const size_t framesWritten = patchRecord->writeFrames(
1098 sourceBuffer.i8, frameCount, mFrameSize);
1099 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001100 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001101 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001102 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001103 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001104 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1105 using namespace std::chrono_literals;
1106 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001107 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang73f97052023-12-12 20:08:03 +00001108 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001109}
1110
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001111// ExtendedAudioBufferProvider interface
1112
Andy Hung27876c02014-09-09 18:07:55 -07001113// framesReady() may return an approximation of the number of frames if called
1114// from a different thread than the one calling Proxy->obtainBuffer() and
1115// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1116// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001117size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001118 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1119 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1120 // The remainder of the buffer is not drained.
1121 return 0;
1122 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001123 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001124}
1125
Andy Hung8d31fd22023-06-26 19:20:57 -07001126int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001127{
1128 return mAudioTrackServerProxy->framesReleased();
1129}
1130
Andy Hung8d31fd22023-06-26 19:20:57 -07001131void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001132{
1133 // This call comes from a FastTrack and should be kept lockless.
1134 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001135 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001136
Andy Hung818e7a32016-02-16 18:08:07 -08001137 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001138
1139 // Compute latency.
1140 // TODO: Consider whether the server latency may be passed in by FastMixer
1141 // as a constant for all active FastTracks.
1142 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1143 mServerLatencyFromTrack.store(true);
1144 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001145}
1146
Eric Laurent81784c32012-11-19 14:55:58 -08001147// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001148bool Track::isReady() const {
1149 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001150 return true;
1151 }
1152
Eric Laurent16498512014-03-17 17:22:08 -07001153 if (isStopping()) {
1154 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001155 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001156 }
Eric Laurent81784c32012-11-19 14:55:58 -08001157 return true;
1158 }
1159
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001160 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001161 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1162 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1163 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1164 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001165
1166 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1167 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1168 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001169 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001170 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001171 return true;
1172 }
1173 return false;
1174}
1175
Andy Hung8d31fd22023-06-26 19:20:57 -07001176status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001177 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001178{
1179 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001180 ALOGV("%s(%d): calling pid %d session %d",
1181 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001182
Andy Hung87c693c2023-07-06 20:56:16 -07001183 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001184 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001185 if (isOffloaded()) {
Andy Hung954b9712023-08-28 18:36:53 -07001186 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hungab65b182023-09-06 19:41:47 -07001187 const bool nonOffloadableGlobalEffectEnabled =
1188 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hungc5007f82023-08-29 14:26:09 -07001189 audio_utils::lock_guard _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001190 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hungab65b182023-09-06 19:41:47 -07001191 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001192 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001193 invalidate();
1194 return PERMISSION_DENIED;
1195 }
1196 }
Andy Hung6c498e92023-12-05 17:28:17 -08001197 audio_utils::unique_lock ul(thread->mutex());
1198 thread->waitWhileThreadBusy_l(ul);
1199
Eric Laurent81784c32012-11-19 14:55:58 -08001200 track_state state = mState;
1201 // here the track could be either new, or restarted
1202 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001203
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001204 // initial state-stopping. next state-pausing.
1205 // What if resume is called ?
1206
Zhou Song1ed46a22020-08-17 15:36:56 +08001207 if (state == FLUSHED) {
1208 // avoid underrun glitches when starting after flush
1209 reset();
1210 }
1211
kuowei.li576f1362021-05-11 18:02:32 +08001212 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1213 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001214 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001215 if (mResumeToStopping) {
1216 // happened we need to resume to STOPPING_1
1217 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001218 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1219 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001220 } else {
1221 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001222 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1223 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001224 }
Eric Laurent81784c32012-11-19 14:55:58 -08001225 } else {
1226 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001227 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1228 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001229 }
1230
Andy Hung87c693c2023-07-06 20:56:16 -07001231 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001232
1233 // states to reset position info for pcm tracks
1234 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001235 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1236 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001237
Dorin Drimusb882d482024-01-17 18:30:02 +01001238 if (!isFastTrack()) {
yucliu6cfb5932022-07-20 17:40:39 -07001239 // Start point of track -> sink frame map. If the HAL returns a
1240 // frame position smaller than the first written frame in
1241 // updateTrackFrameInfo, the timestamp can be interpolated
1242 // instead of using a larger value.
1243 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1244 playbackThread->framesWritten());
1245 }
Andy Hunge10393e2015-06-12 13:59:33 -07001246 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001247 if (isFastTrack()) {
1248 // refresh fast track underruns on start because that field is never cleared
1249 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1250 // after stop.
1251 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1252 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001253 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001254 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001255 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001256 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001257 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001258 mState = state;
1259 }
1260 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001261
Andy Hungb68f5eb2019-12-03 16:49:17 -08001262 // Audio timing metrics are computed a few mix cycles after starting.
1263 {
1264 mLogStartCountdown = LOG_START_COUNTDOWN;
1265 mLogStartTimeNs = systemTime();
1266 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001267 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1268 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001269 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001270 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001271
Andy Hung1d3556d2018-03-29 16:30:14 -07001272 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1273 // for streaming tracks, remove the buffer read stop limit.
1274 mAudioTrackServerProxy->start();
1275 }
1276
Eric Laurentbfb1b832013-01-07 09:53:42 -08001277 // track was already in the active list, not a problem
1278 if (status == ALREADY_EXISTS) {
1279 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001280 } else {
1281 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1282 // It is usually unsafe to access the server proxy from a binder thread.
1283 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1284 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1285 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001286 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001287 ServerProxy::Buffer buffer;
1288 buffer.mFrameCount = 1;
1289 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001290 }
jiabin7434e812023-06-27 18:22:35 +00001291 if (status == NO_ERROR) {
1292 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1293 }
Eric Laurent81784c32012-11-19 14:55:58 -08001294 } else {
1295 status = BAD_VALUE;
1296 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001297 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001298 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001299 const sp<IAudioManager> audioManager =
1300 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001301 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1302 std::unique_ptr<os::PersistableBundle> bundle =
1303 std::make_unique<os::PersistableBundle>();
1304 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1305 isSpatialized());
1306 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1307 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1308 status_t result = audioManager->portEvent(mPortId,
1309 PLAYER_UPDATE_FORMAT, bundle);
1310 if (result != OK) {
1311 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1312 __func__, mPortId, result);
1313 }
1314 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001315 }
Eric Laurent81784c32012-11-19 14:55:58 -08001316 return status;
1317}
1318
Andy Hung8d31fd22023-06-26 19:20:57 -07001319void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001320{
Andy Hungc0691382018-09-12 18:01:57 -07001321 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001322 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001323 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001324 audio_utils::unique_lock ul(thread->mutex());
1325 thread->waitWhileThreadBusy_l(ul);
1326
Eric Laurent81784c32012-11-19 14:55:58 -08001327 track_state state = mState;
1328 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1329 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001330 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1331 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001332 reset();
1333 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001334 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1335 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1336 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001337 mState = STOPPED;
1338 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001339 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1340 // presentation is complete
1341 // For an offloaded track this starts a drain and state will
1342 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001343 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001344 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001345 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001346 }
Eric Laurent81784c32012-11-19 14:55:58 -08001347 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001348 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001349 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1350 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001351 }
jiabin7434e812023-06-27 18:22:35 +00001352 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001353 }
1354}
1355
Andy Hung8d31fd22023-06-26 19:20:57 -07001356void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001357{
Andy Hungc0691382018-09-12 18:01:57 -07001358 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001359 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001360 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001361 audio_utils::unique_lock ul(thread->mutex());
1362 thread->waitWhileThreadBusy_l(ul);
1363
Andy Hung87c693c2023-07-06 20:56:16 -07001364 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001365 switch (mState) {
1366 case STOPPING_1:
1367 case STOPPING_2:
1368 if (!isOffloaded()) {
1369 /* nothing to do if track is not offloaded */
1370 break;
1371 }
1372
1373 // Offloaded track was draining, we need to carry on draining when resumed
1374 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001375 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001376 case ACTIVE:
1377 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001378 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001379 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1380 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001381 if (isOffloadedOrDirect()) {
1382 mPauseHwPending = true;
1383 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001384 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001385 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001386
Eric Laurentbfb1b832013-01-07 09:53:42 -08001387 default:
1388 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001389 }
jiabin7434e812023-06-27 18:22:35 +00001390 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1391 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001392 }
1393}
1394
Andy Hung8d31fd22023-06-26 19:20:57 -07001395void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001396{
Andy Hungc0691382018-09-12 18:01:57 -07001397 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001398 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001399 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001400 audio_utils::unique_lock ul(thread->mutex());
1401 thread->waitWhileThreadBusy_l(ul);
1402
Andy Hung87c693c2023-07-06 20:56:16 -07001403 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001404
Phil Burk4bb650b2016-09-09 12:11:17 -07001405 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1406 // Otherwise the flush would not be done until the track is resumed.
1407 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001408 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001409 (void)mServerProxy->flushBufferIfNeeded();
1410 }
1411
Eric Laurentbfb1b832013-01-07 09:53:42 -08001412 if (isOffloaded()) {
1413 // If offloaded we allow flush during any state except terminated
1414 // and keep the track active to avoid problems if user is seeking
1415 // rapidly and underlying hardware has a significant delay handling
1416 // a pause
1417 if (isTerminated()) {
1418 return;
1419 }
1420
Andy Hung9d84af52018-09-12 18:03:44 -07001421 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001422 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001423
1424 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001425 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1426 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001427 mState = ACTIVE;
1428 }
1429
Haynes Mathew George7844f672014-01-15 12:32:55 -08001430 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001431 mResumeToStopping = false;
1432 } else {
1433 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1434 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1435 return;
1436 }
1437 // No point remaining in PAUSED state after a flush => go to
1438 // FLUSHED state
1439 mState = FLUSHED;
1440 // do not reset the track if it is still in the process of being stopped or paused.
1441 // this will be done by prepareTracks_l() when the track is stopped.
1442 // prepareTracks_l() will see mState == FLUSHED, then
1443 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001444 if (isDirect()) {
1445 mFlushHwPending = true;
1446 }
Andy Hung87c693c2023-07-06 20:56:16 -07001447 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001448 reset();
1449 }
Eric Laurent81784c32012-11-19 14:55:58 -08001450 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001451 // Prevent flush being lost if the track is flushed and then resumed
1452 // before mixer thread can run. This is important when offloading
1453 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001454 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001455 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1456 // new data
1457 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001458 }
1459}
1460
Haynes Mathew George7844f672014-01-15 12:32:55 -08001461// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001462void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001463{
Andy Hung920f6572022-10-06 12:09:49 -07001464 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001465 return;
Andy Hung920f6572022-10-06 12:09:49 -07001466 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001467
Phil Burk4bb650b2016-09-09 12:11:17 -07001468 // Clear the client ring buffer so that the app can prime the buffer while paused.
1469 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1470 mServerProxy->flushBufferIfNeeded();
1471
Haynes Mathew George7844f672014-01-15 12:32:55 -08001472 mFlushHwPending = false;
1473}
1474
Andy Hung8d31fd22023-06-26 19:20:57 -07001475void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001476{
1477 mPauseHwPending = false;
1478}
1479
Andy Hung8d31fd22023-06-26 19:20:57 -07001480void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001481{
1482 // Do not reset twice to avoid discarding data written just after a flush and before
1483 // the audioflinger thread detects the track is stopped.
1484 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001485 // Force underrun condition to avoid false underrun callback until first data is
1486 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001487 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001488 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001489 mResetDone = true;
1490 if (mState == FLUSHED) {
1491 mState = IDLE;
1492 }
1493 }
1494}
1495
Andy Hung8d31fd22023-06-26 19:20:57 -07001496status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001497{
Andy Hung87c693c2023-07-06 20:56:16 -07001498 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001499 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001500 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001501 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001502 } else if (thread->type() == IAfThreadBase::DIRECT
1503 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001504 return thread->setParameters(keyValuePairs);
1505 } else {
1506 return PERMISSION_DENIED;
1507 }
1508}
1509
Andy Hung8d31fd22023-06-26 19:20:57 -07001510status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001511 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001512 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001513 if (thread == 0) {
1514 ALOGE("thread is dead");
1515 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001516 } else if (thread->type() == IAfThreadBase::DIRECT
1517 || thread->type() == IAfThreadBase::OFFLOAD) {
1518 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001519 return directOutputThread->selectPresentation(presentationId, programId);
1520 }
1521 return INVALID_OPERATION;
1522}
1523
Andy Hung8d31fd22023-06-26 19:20:57 -07001524VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001525 const sp<VolumeShaper::Configuration>& configuration,
1526 const sp<VolumeShaper::Operation>& operation)
1527{
Andy Hung398ffa22022-12-13 19:19:53 -08001528 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001529
1530 if (isOffloadedOrDirect()) {
1531 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001532 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001533 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001534 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001535 thread->broadcast_l();
1536 }
1537 }
1538 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001539}
1540
Andy Hung8d31fd22023-06-26 19:20:57 -07001541sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001542{
1543 // Note: We don't check if Thread exists.
1544
1545 // mVolumeHandler is thread safe.
1546 return mVolumeHandler->getVolumeShaperState(id);
1547}
1548
Andy Hung8d31fd22023-06-26 19:20:57 -07001549void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001550{
jiabin76d94692022-12-15 21:51:21 +00001551 mFinalVolumeLeft = volumeLeft;
1552 mFinalVolumeRight = volumeRight;
1553 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001554 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1555 mFinalVolume = volume;
1556 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001557 mLogForceVolumeUpdate = true;
1558 }
1559 if (mLogForceVolumeUpdate) {
1560 mLogForceVolumeUpdate = false;
1561 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001562 }
1563}
1564
Andy Hung8d31fd22023-06-26 19:20:57 -07001565void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001566{
Eric Laurent49e39282022-06-24 18:42:45 +02001567 // Do not forward metadata for PatchTrack with unspecified stream type
1568 if (mStreamType == AUDIO_STREAM_PATCH) {
1569 return;
1570 }
1571
Eric Laurent94579172020-11-20 18:41:04 +01001572 playback_track_metadata_v7_t metadata;
1573 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001574 .usage = mAttr.usage,
1575 .content_type = mAttr.content_type,
1576 .gain = mFinalVolume,
1577 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001578
1579 // When attributes are undefined, derive default values from stream type.
1580 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1581 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1582 switch (mStreamType) {
1583 case AUDIO_STREAM_VOICE_CALL:
1584 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1585 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1586 break;
1587 case AUDIO_STREAM_SYSTEM:
1588 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1589 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1590 break;
1591 case AUDIO_STREAM_RING:
1592 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1593 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1594 break;
1595 case AUDIO_STREAM_MUSIC:
1596 metadata.base.usage = AUDIO_USAGE_MEDIA;
1597 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1598 break;
1599 case AUDIO_STREAM_ALARM:
1600 metadata.base.usage = AUDIO_USAGE_ALARM;
1601 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1602 break;
1603 case AUDIO_STREAM_NOTIFICATION:
1604 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1605 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1606 break;
1607 case AUDIO_STREAM_DTMF:
1608 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1609 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1610 break;
1611 case AUDIO_STREAM_ACCESSIBILITY:
1612 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1613 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1614 break;
1615 case AUDIO_STREAM_ASSISTANT:
1616 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1617 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1618 break;
1619 case AUDIO_STREAM_REROUTING:
1620 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1621 // unknown content type
1622 break;
1623 case AUDIO_STREAM_CALL_ASSISTANT:
1624 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1625 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1626 break;
1627 default:
1628 break;
1629 }
1630 }
1631
Eric Laurent78b07302022-10-07 16:20:34 +02001632 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001633 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1634 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001635}
1636
Andy Hung8d31fd22023-06-26 19:20:57 -07001637void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001638 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001639 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang73f97052023-12-12 20:08:03 +00001640 {
1641 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1642 mTeePatches = std::move(mTeePatchesToUpdate.value());
1643 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001644 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1645 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001646 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001647 }
1648 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001649 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001650}
1651
Andy Hung16ed0da2023-07-14 11:45:38 -07001652void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001653 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1654 "%s, existing tee patches to update will be ignored", __func__);
1655 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1656}
1657
Vlad Popae8d99472022-06-30 16:02:48 +02001658// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001659void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001660 IAudioManager>& audioManager, mute_state_t muteState)
1661{
1662 if (mMuteState == muteState) {
1663 // mute state did not change, do nothing
1664 return;
1665 }
1666
1667 status_t result = UNKNOWN_ERROR;
1668 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1669 if (mMuteEventExtras == nullptr) {
1670 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1671 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001672 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001673
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001674 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001675 }
1676
1677 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001678 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
Andy Hung0e26ec62024-02-20 16:32:57 -08001679 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001680 mMuteState = muteState;
1681 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001682 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1683 mPortId, result);
Vlad Popae8d99472022-06-30 16:02:48 +02001684 }
1685}
1686
Andy Hung8d31fd22023-06-26 19:20:57 -07001687status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001688{
Andy Hung818e7a32016-02-16 18:08:07 -08001689 if (!isOffloaded() && !isDirect()) {
1690 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001691 }
Andy Hung87c693c2023-07-06 20:56:16 -07001692 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001693 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001694 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001695 }
Phil Burk6140c792015-03-19 14:30:21 -07001696
Andy Hungc5007f82023-08-29 14:26:09 -07001697 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001698 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001699 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001700}
1701
Andy Hung8d31fd22023-06-26 19:20:57 -07001702status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001703{
Andy Hung87c693c2023-07-06 20:56:16 -07001704 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001705 if (thread == nullptr) {
1706 return DEAD_OBJECT;
1707 }
Eric Laurent81784c32012-11-19 14:55:58 -08001708
Andy Hung87c693c2023-07-06 20:56:16 -07001709 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001710 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001711 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001712 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001713 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001714
Eric Laurent6c796322019-04-09 14:13:17 -07001715 if (EffectId != 0 && status == NO_ERROR) {
1716 status = dstThread->attachAuxEffect(this, EffectId);
1717 if (status == NO_ERROR) {
1718 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001719 }
Eric Laurent6c796322019-04-09 14:13:17 -07001720 }
1721
1722 if (status != NO_ERROR && srcThread != nullptr) {
1723 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001724 }
1725 return status;
1726}
1727
Andy Hung8d31fd22023-06-26 19:20:57 -07001728void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001729{
1730 mAuxEffectId = EffectId;
1731 mAuxBuffer = buffer;
1732}
1733
Andy Hung59de4262021-06-14 10:53:54 -07001734// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001735bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001736 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001737{
Andy Hung818e7a32016-02-16 18:08:07 -08001738 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1739 // This assists in proper timestamp computation as well as wakelock management.
1740
Eric Laurent81784c32012-11-19 14:55:58 -08001741 // a track is considered presented when the total number of frames written to audio HAL
1742 // corresponds to the number of frames written when presentationComplete() is called for the
1743 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001744 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1745 // to detect when all frames have been played. In this case framesWritten isn't
1746 // useful because it doesn't always reflect whether there is data in the h/w
1747 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001748 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1749 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001750 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001751 if (mPresentationCompleteFrames == 0) {
1752 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001753 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001754 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1755 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001756 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001757 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001758
Andy Hungc54b1ff2016-02-23 14:07:07 -08001759 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001760 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001761 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001762 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1763 __func__, mId, (complete ? "complete" : "waiting"),
1764 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001765 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001766 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001767 && mAudioTrackServerProxy->isDrained();
1768 }
1769
1770 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001771 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001772 return true;
1773 }
1774 return false;
1775}
1776
Andy Hung59de4262021-06-14 10:53:54 -07001777// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001778bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001779{
1780 // For Offloaded or Direct tracks.
1781
1782 // For a direct track, we incorporated time based testing for presentationComplete.
1783
1784 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1785 // to detect when all frames have been played. In this case latencyMs isn't
1786 // useful because it doesn't always reflect whether there is data in the h/w
1787 // buffers, particularly if a track has been paused and resumed during draining
1788
1789 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1790 if (mPresentationCompleteTimeNs == 0) {
1791 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1792 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1793 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1794 }
1795
1796 bool complete;
1797 if (isOffloaded()) {
1798 complete = true;
1799 } else { // Direct
1800 complete = systemTime() >= mPresentationCompleteTimeNs;
1801 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1802 }
1803 if (complete) {
1804 notifyPresentationComplete();
1805 return true;
1806 }
1807 return false;
1808}
1809
Andy Hung8d31fd22023-06-26 19:20:57 -07001810void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001811{
1812 // This only triggers once. TODO: should we enforce this?
1813 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1814 mAudioTrackServerProxy->setStreamEndDone();
1815}
1816
Andy Hung8d31fd22023-06-26 19:20:57 -07001817void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001818{
Andy Hung068e08e2023-05-15 19:02:55 -07001819 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1820 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001821 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001822 (*it)->trigger();
1823 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001824 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001825 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001826 }
1827 }
1828}
1829
1830// implement VolumeBufferProvider interface
1831
Andy Hung8d31fd22023-06-26 19:20:57 -07001832gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001833{
1834 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1835 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001836 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1837 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1838 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001839 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001840 if (vl > GAIN_FLOAT_UNITY) {
1841 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001842 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001843 if (vr > GAIN_FLOAT_UNITY) {
1844 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001845 }
1846 // now apply the cached master volume and stream type volume;
1847 // this is trusted but lacks any synchronization or barrier so may be stale
1848 float v = mCachedVolume;
1849 vl *= v;
1850 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001851 // re-combine into packed minifloat
1852 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001853 // FIXME look at mute, pause, and stop flags
1854 return vlr;
1855}
1856
Andy Hung8d31fd22023-06-26 19:20:57 -07001857status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001858 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001859{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001860 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001861 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1862 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001863 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1864 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001865 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001866 event->cancel();
1867 return INVALID_OPERATION;
1868 }
1869 (void) TrackBase::setSyncEvent(event);
1870 return NO_ERROR;
1871}
1872
Andy Hung8d31fd22023-06-26 19:20:57 -07001873void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001874{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001875 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001876 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001877}
1878
Andy Hung8d31fd22023-06-26 19:20:57 -07001879void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001880{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001881 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001882 signalClientFlag(CBLK_DISABLED);
1883}
1884
Eric Laurent022a5132024-04-12 17:02:51 +00001885bool Track::isDisabled() const {
1886 audio_track_cblk_t* cblk = mCblk;
1887 return (cblk != nullptr)
1888 && ((android_atomic_release_load(&cblk->mFlags) & CBLK_DISABLED) != 0);
1889}
1890
Andy Hung8d31fd22023-06-26 19:20:57 -07001891void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001892{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001893 // FIXME should use proxy, and needs work
1894 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001895 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001896 android_atomic_release_store(0x40000000, &cblk->mFutex);
1897 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001898 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001899}
1900
Andy Hung8d31fd22023-06-26 19:20:57 -07001901void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001902{
Andy Hung87c693c2023-07-06 20:56:16 -07001903 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001904 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001905 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001906 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001907 t->broadcast_l();
1908 }
1909}
1910
Andy Hung8d31fd22023-06-26 19:20:57 -07001911status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001912{
1913 status_t status = INVALID_OPERATION;
1914 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001915 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001916 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001917 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001918 audio_utils::lock_guard _l(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001919 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001920 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1921 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1922 }
1923 }
1924 return status;
1925}
1926
Andy Hung8d31fd22023-06-26 19:20:57 -07001927status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001928{
1929 status_t status = INVALID_OPERATION;
1930 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001931 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001933 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001934 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001935 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001936 if (status == NO_ERROR) {
1937 mDualMonoMode = mode;
1938 }
1939 }
1940 }
1941 return status;
1942}
1943
Andy Hung8d31fd22023-06-26 19:20:57 -07001944status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001945{
1946 status_t status = INVALID_OPERATION;
1947 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001948 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001949 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001950 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001951 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001952 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001953 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1954 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1955 }
1956 }
1957 return status;
1958}
1959
Andy Hung8d31fd22023-06-26 19:20:57 -07001960status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001961{
1962 status_t status = INVALID_OPERATION;
1963 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001964 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001965 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001966 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001967 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001968 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001969 if (status == NO_ERROR) {
1970 mAudioDescriptionMixLevel = leveldB;
1971 }
1972 }
1973 }
1974 return status;
1975}
1976
Andy Hung8d31fd22023-06-26 19:20:57 -07001977status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001978 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001979{
1980 status_t status = INVALID_OPERATION;
1981 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001982 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001983 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001984 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001985 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001986 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001987 ALOGD_IF((status == NO_ERROR) &&
1988 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1989 "%s: playbackRate inconsistent", __func__);
1990 }
1991 }
1992 return status;
1993}
1994
Andy Hung8d31fd22023-06-26 19:20:57 -07001995status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001996 const audio_playback_rate_t& playbackRate)
1997{
1998 status_t status = INVALID_OPERATION;
1999 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002000 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002001 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002002 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002003 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002004 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002005 if (status == NO_ERROR) {
2006 mPlaybackRateParameters = playbackRate;
2007 }
2008 }
2009 }
2010 return status;
2011}
2012
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002013//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002014bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07002015 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002016 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002017 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002018 /* Resume is pending if track was stopping before pause was called */
2019 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07002020 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002021 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002022 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002023
2024 return false;
2025}
2026
2027//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002028void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07002029 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002030 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07002031 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002032
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002033 // Other possibility of pending resume is stopping_1 state
2034 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002035 // drain being called.
2036 if (mState == STOPPING_1) {
2037 mResumeToStopping = false;
2038 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002039}
Andy Hunge10393e2015-06-12 13:59:33 -07002040
2041//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002042void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002043 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002044 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002045 // Make the kernel frametime available.
2046 const FrameTime ft{
2047 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2048 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2049 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2050 mKernelFrameTime.store(ft);
2051 if (!audio_is_linear_pcm(mFormat)) {
2052 return;
2053 }
2054
Andy Hung818e7a32016-02-16 18:08:07 -08002055 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002056 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002057
2058 // adjust server times and set drained state.
2059 //
2060 // Our timestamps are only updated when the track is on the Thread active list.
2061 // We need to ensure that tracks are not removed before full drain.
2062 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002063 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002064 bool checked = false;
2065 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2066 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2067 // Lookup the track frame corresponding to the sink frame position.
2068 if (local.mTimeNs[i] > 0) {
2069 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2070 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002071 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002072 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002073 checked = true;
2074 }
2075 }
Andy Hunge10393e2015-06-12 13:59:33 -07002076 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002077
Andy Hung93bb5732023-05-04 21:16:34 -07002078 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2079 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002080 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002081 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002082 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002083 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002084
2085 // Compute latency info.
2086 const bool useTrackTimestamp = !drained;
2087 const double latencyMs = useTrackTimestamp
2088 ? local.getOutputServerLatencyMs(sampleRate())
2089 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2090
2091 mServerLatencyFromTrack.store(useTrackTimestamp);
2092 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002093
Andy Hung62921122020-05-18 10:47:31 -07002094 if (mLogStartCountdown > 0
2095 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2096 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2097 {
2098 if (mLogStartCountdown > 1) {
2099 --mLogStartCountdown;
2100 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2101 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002102 // startup is the difference in times for the current timestamp and our start
2103 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002104 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002105 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002106 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2107 * 1e3 / mSampleRate;
2108 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2109 " localTime:%lld startTime:%lld"
2110 " localPosition:%lld startPosition:%lld",
2111 __func__, latencyMs, startUpMs,
2112 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002113 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002114 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002115 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002116 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002117 }
Andy Hung62921122020-05-18 10:47:31 -07002118 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002119 }
Andy Hunge10393e2015-06-12 13:59:33 -07002120}
2121
Andy Hung8d31fd22023-06-26 19:20:57 -07002122bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002123 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002124 if (thread != 0) {
2125 // Lock for updating mHapticPlaybackEnabled.
Andy Hungc5007f82023-08-29 14:26:09 -07002126 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002127 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002128 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002129 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002130 ALOGD("%s, haptic playback was %s for track %d",
2131 __func__, muted ? "muted" : "unmuted", mTrack->id());
2132 mTrack->setHapticPlaybackEnabled(!muted);
2133 return true;
jiabin57303cc2018-12-18 15:45:57 -08002134 }
2135 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002136 return false;
2137}
2138
Andy Hung8d31fd22023-06-26 19:20:57 -07002139binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002140 /*out*/ bool *ret) {
2141 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002142 return binder::Status::ok();
2143}
2144
Andy Hung8d31fd22023-06-26 19:20:57 -07002145binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002146 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002147 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002148 return binder::Status::ok();
2149}
2150
Eric Laurent81784c32012-11-19 14:55:58 -08002151// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002152#undef LOG_TAG
2153#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002154
Andy Hung8d31fd22023-06-26 19:20:57 -07002155/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002156sp<IAfOutputTrack> IAfOutputTrack::create(
2157 IAfPlaybackThread* playbackThread,
2158 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002159 uint32_t sampleRate,
2160 audio_format_t format,
2161 audio_channel_mask_t channelMask,
2162 size_t frameCount,
2163 const AttributionSourceState& attributionSource) {
2164 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002165 playbackThread,
2166 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002167 sampleRate,
2168 format,
2169 channelMask,
2170 frameCount,
2171 attributionSource);
2172}
2173
2174OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002175 IAfPlaybackThread* playbackThread,
2176 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002177 uint32_t sampleRate,
2178 audio_format_t format,
2179 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002180 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002181 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002182 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002183 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002184 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002185 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002186 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002187 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002188 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002189{
2190
2191 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002192 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002193 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002194 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002195 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002196 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002197 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002198 // since client and server are in the same process,
2199 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002200 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2201 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002202 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002203 mClientProxy->setSendLevel(0.0);
2204 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002205 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002206 ALOGW("%s(%d): Error creating output track on thread %d",
2207 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002208 }
2209}
2210
Andy Hung8d31fd22023-06-26 19:20:57 -07002211OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002212{
2213 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002214 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002215}
2216
Andy Hung8d31fd22023-06-26 19:20:57 -07002217status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002218 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002219{
2220 status_t status = Track::start(event, triggerSession);
2221 if (status != NO_ERROR) {
2222 return status;
2223 }
2224
2225 mActive = true;
2226 mRetryCount = 127;
2227 return status;
2228}
2229
Andy Hung8d31fd22023-06-26 19:20:57 -07002230void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002231{
2232 Track::stop();
2233 clearBufferQueue();
2234 mOutBuffer.frameCount = 0;
2235 mActive = false;
2236}
2237
Andy Hung8d31fd22023-06-26 19:20:57 -07002238ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002239{
Eric Laurent19952e12023-04-20 10:08:29 +02002240 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002241 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002242 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002243 // preload one silent buffer to trigger mixer on start()
2244 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2245 status_t status = mClientProxy->obtainBuffer(&buf);
2246 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2247 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2248 return 0;
2249 }
2250 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2251 mClientProxy->releaseBuffer(&buf);
2252
2253 (void) start();
2254
2255 // wait for HAL stream to start before sending actual audio. Doing this on each
2256 // OutputTrack makes that playback start on all output streams is synchronized.
2257 // If another OutputTrack has already started it can underrun but this is OK
2258 // as only silence has been played so far and the retry count is very high on
2259 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002260 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002261 if (!pt->waitForHalStart()) {
2262 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2263 stop();
2264 return 0;
2265 }
2266
2267 // enqueue the first buffer and exit so that other OutputTracks will also start before
2268 // write() is called again and this buffer actually consumed.
2269 Buffer firstBuffer;
2270 firstBuffer.frameCount = frames;
2271 firstBuffer.raw = data;
2272 queueBuffer(firstBuffer);
2273 return frames;
2274 } else {
2275 (void) start();
2276 }
2277 }
2278
Eric Laurent81784c32012-11-19 14:55:58 -08002279 Buffer *pInBuffer;
2280 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002281 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002282 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002283 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002284 while (waitTimeLeftMs) {
2285 // First write pending buffers, then new data
2286 if (mBufferQueue.size()) {
2287 pInBuffer = mBufferQueue.itemAt(0);
2288 } else {
2289 pInBuffer = &inBuffer;
2290 }
2291
2292 if (pInBuffer->frameCount == 0) {
2293 break;
2294 }
2295
2296 if (mOutBuffer.frameCount == 0) {
2297 mOutBuffer.frameCount = pInBuffer->frameCount;
2298 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002299 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002300 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002301 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2302 __func__, mId,
2303 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002304 break;
2305 }
2306 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2307 if (waitTimeLeftMs >= waitTimeMs) {
2308 waitTimeLeftMs -= waitTimeMs;
2309 } else {
2310 waitTimeLeftMs = 0;
2311 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002312 if (status == NOT_ENOUGH_DATA) {
2313 restartIfDisabled();
2314 continue;
2315 }
Eric Laurent81784c32012-11-19 14:55:58 -08002316 }
2317
2318 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2319 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002320 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002321 Proxy::Buffer buf;
2322 buf.mFrameCount = outFrames;
2323 buf.mRaw = NULL;
2324 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002325 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002326 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002327 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002328 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002329 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002330
2331 if (pInBuffer->frameCount == 0) {
2332 if (mBufferQueue.size()) {
2333 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002334 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002335 if (pInBuffer != &inBuffer) {
2336 delete pInBuffer;
2337 }
Andy Hung9d84af52018-09-12 18:03:44 -07002338 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2339 __func__, mId,
2340 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002341 } else {
2342 break;
2343 }
2344 }
2345 }
2346
2347 // If we could not write all frames, allocate a buffer and queue it for next time.
2348 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002349 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002350 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002351 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002352 }
2353 }
2354
Andy Hungc25b84a2015-01-14 19:04:10 -08002355 // Calling write() with a 0 length buffer means that no more data will be written:
2356 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2357 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2358 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002359 }
2360
Andy Hung1c86ebe2018-05-29 20:29:08 -07002361 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002362}
2363
Andy Hung8d31fd22023-06-26 19:20:57 -07002364void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002365
2366 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2367 Buffer *pInBuffer = new Buffer;
2368 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2369 pInBuffer->mBuffer = malloc(bufferSize);
2370 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2371 "%s: Unable to malloc size %zu", __func__, bufferSize);
2372 pInBuffer->frameCount = inBuffer.frameCount;
2373 pInBuffer->raw = pInBuffer->mBuffer;
2374 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2375 mBufferQueue.add(pInBuffer);
2376 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2377 (int)mThreadIoHandle, mBufferQueue.size());
2378 // audio data is consumed (stored locally); set frameCount to 0.
2379 inBuffer.frameCount = 0;
2380 } else {
2381 ALOGW("%s(%d): thread %d no more overflow buffers",
2382 __func__, mId, (int)mThreadIoHandle);
2383 // TODO: return error for this.
2384 }
2385}
2386
Andy Hung8d31fd22023-06-26 19:20:57 -07002387void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002388{
Andy Hungc5007f82023-08-29 14:26:09 -07002389 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002390 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2391}
2392
Andy Hung8d31fd22023-06-26 19:20:57 -07002393void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002394 {
Andy Hungc5007f82023-08-29 14:26:09 -07002395 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002396 mTrackMetadatas = metadatas;
2397 }
2398 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2399 setMetadataHasChanged();
2400}
2401
Andy Hung8d31fd22023-06-26 19:20:57 -07002402status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002403 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2404{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002405 ClientProxy::Buffer buf;
2406 buf.mFrameCount = buffer->frameCount;
2407 struct timespec timeout;
2408 timeout.tv_sec = waitTimeMs / 1000;
2409 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2410 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2411 buffer->frameCount = buf.mFrameCount;
2412 buffer->raw = buf.mRaw;
2413 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002414}
2415
Andy Hung8d31fd22023-06-26 19:20:57 -07002416void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002417{
2418 size_t size = mBufferQueue.size();
2419
2420 for (size_t i = 0; i < size; i++) {
2421 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002422 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002423 delete pBuffer;
2424 }
2425 mBufferQueue.clear();
2426}
2427
Andy Hung8d31fd22023-06-26 19:20:57 -07002428void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002429{
2430 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2431 if (mActive && (flags & CBLK_DISABLED)) {
2432 start();
2433 }
2434}
Eric Laurent81784c32012-11-19 14:55:58 -08002435
Andy Hung9d84af52018-09-12 18:03:44 -07002436// ----------------------------------------------------------------------------
2437#undef LOG_TAG
2438#define LOG_TAG "AF::PatchTrack"
2439
Andy Hung8d31fd22023-06-26 19:20:57 -07002440/* static */
2441sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002442 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002443 audio_stream_type_t streamType,
2444 uint32_t sampleRate,
2445 audio_channel_mask_t channelMask,
2446 audio_format_t format,
2447 size_t frameCount,
2448 void* buffer,
2449 size_t bufferSize,
2450 audio_output_flags_t flags,
2451 const Timeout& timeout,
2452 size_t frameCountToBeReady /** Default behaviour is to start
2453 * as soon as possible to have
2454 * the lowest possible latency
2455 * even if it might glitch. */)
2456{
2457 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002458 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002459 streamType,
2460 sampleRate,
2461 channelMask,
2462 format,
2463 frameCount,
2464 buffer,
2465 bufferSize,
2466 flags,
2467 timeout,
2468 frameCountToBeReady);
2469}
2470
Andy Hung87c693c2023-07-06 20:56:16 -07002471PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002472 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002473 uint32_t sampleRate,
2474 audio_channel_mask_t channelMask,
2475 audio_format_t format,
2476 size_t frameCount,
2477 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002478 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002479 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002480 const Timeout& timeout,
2481 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002482 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002483 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002484 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002485 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002486 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002487 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002488 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2489 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002490 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002491{
Andy Hung9d84af52018-09-12 18:03:44 -07002492 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2493 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002494 (int)mPeerTimeout.tv_sec,
2495 (int)(mPeerTimeout.tv_nsec / 1000000));
2496}
2497
Andy Hung8d31fd22023-06-26 19:20:57 -07002498PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002499{
Andy Hungabfab202019-03-07 19:45:54 -08002500 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002501}
2502
Andy Hung8d31fd22023-06-26 19:20:57 -07002503size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002504{
2505 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2506 return std::numeric_limits<size_t>::max();
2507 } else {
2508 return Track::framesReady();
2509 }
2510}
2511
Andy Hung8d31fd22023-06-26 19:20:57 -07002512status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002513 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002514{
2515 status_t status = Track::start(event, triggerSession);
2516 if (status != NO_ERROR) {
2517 return status;
2518 }
2519 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2520 return status;
2521}
2522
Eric Laurent83b88082014-06-20 18:31:16 -07002523// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002524status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002525 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002526{
Andy Hung9d84af52018-09-12 18:03:44 -07002527 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002528 Proxy::Buffer buf;
2529 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002530 if (ATRACE_ENABLED()) {
2531 std::string traceName("PTnReq");
2532 traceName += std::to_string(id());
2533 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2534 }
Eric Laurent83b88082014-06-20 18:31:16 -07002535 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002536 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002537 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002538 if (ATRACE_ENABLED()) {
2539 std::string traceName("PTnObt");
2540 traceName += std::to_string(id());
2541 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2542 }
Eric Laurent83b88082014-06-20 18:31:16 -07002543 if (buf.mFrameCount == 0) {
2544 return WOULD_BLOCK;
2545 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002546 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002547 return status;
2548}
2549
Andy Hung8d31fd22023-06-26 19:20:57 -07002550void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002551{
Andy Hung9d84af52018-09-12 18:03:44 -07002552 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002553 Proxy::Buffer buf;
2554 buf.mFrameCount = buffer->frameCount;
2555 buf.mRaw = buffer->raw;
2556 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002557 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002558}
2559
Andy Hung8d31fd22023-06-26 19:20:57 -07002560status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002561 const struct timespec *timeOut)
2562{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002563 status_t status = NO_ERROR;
2564 static const int32_t kMaxTries = 5;
2565 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002566 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002567 do {
2568 if (status == NOT_ENOUGH_DATA) {
2569 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002570 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002571 }
2572 status = mProxy->obtainBuffer(buffer, timeOut);
2573 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2574 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002575}
2576
Andy Hung8d31fd22023-06-26 19:20:57 -07002577void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002578{
2579 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002580 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002581
2582 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2583 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2584 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2585 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002586 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002587 && audio_is_linear_pcm(mFormat)
2588 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002589 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002590 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002591 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002592 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2593 / playbackThread->sampleRate();
2594 if (framesReady() < frameCount) {
2595 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002596 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002597 }
2598 }
2599 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002600}
2601
Andy Hung8d31fd22023-06-26 19:20:57 -07002602void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002603{
Eric Laurent83b88082014-06-20 18:31:16 -07002604 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002605 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002606 start();
2607 }
Eric Laurent83b88082014-06-20 18:31:16 -07002608}
2609
Eric Laurent81784c32012-11-19 14:55:58 -08002610// ----------------------------------------------------------------------------
2611// Record
2612// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002613
2614
Andy Hung9d84af52018-09-12 18:03:44 -07002615#undef LOG_TAG
2616#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002617
Andy Hunga5a7fc92023-06-23 19:27:19 -07002618class RecordHandle : public android::media::BnAudioRecord {
2619public:
Andy Hungd29af632023-06-23 19:27:19 -07002620 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002621 ~RecordHandle() override;
2622 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2623 int /*audio_session_t*/ triggerSession) final;
2624 binder::Status stop() final;
2625 binder::Status getActiveMicrophones(
2626 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2627 binder::Status setPreferredMicrophoneDirection(
2628 int /*audio_microphone_direction_t*/ direction) final;
2629 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2630 binder::Status shareAudioHistory(
2631 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2632
2633private:
Andy Hungd29af632023-06-23 19:27:19 -07002634 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002635
2636 // for use from destructor
2637 void stop_nonvirtual();
2638};
2639
2640/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002641sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2642 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002643 return sp<RecordHandle>::make(recordTrack);
2644}
2645
2646RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002647 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002648 : BnAudioRecord(),
2649 mRecordTrack(recordTrack)
2650{
Andy Hung225aef62022-12-06 16:33:20 -08002651 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -07002652 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -08002653}
2654
Andy Hunga5a7fc92023-06-23 19:27:19 -07002655RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002656 stop_nonvirtual();
2657 mRecordTrack->destroy();
2658}
2659
Andy Hunga5a7fc92023-06-23 19:27:19 -07002660binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002661 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002662 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002663 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002664 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002665}
2666
Andy Hunga5a7fc92023-06-23 19:27:19 -07002667binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002668 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002669 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002670}
2671
Andy Hunga5a7fc92023-06-23 19:27:19 -07002672void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002673 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002674 mRecordTrack->stop();
2675}
2676
Andy Hunga5a7fc92023-06-23 19:27:19 -07002677binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002678 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002679 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002680 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002681}
2682
Andy Hunga5a7fc92023-06-23 19:27:19 -07002683binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002684 int /*audio_microphone_direction_t*/ direction) {
2685 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002686 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002687 static_cast<audio_microphone_direction_t>(direction)));
2688}
2689
Andy Hunga5a7fc92023-06-23 19:27:19 -07002690binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002691 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002692 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002693}
2694
Andy Hunga5a7fc92023-06-23 19:27:19 -07002695binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002696 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2697 return binderStatusFromStatusT(
2698 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2699}
2700
Eric Laurent81784c32012-11-19 14:55:58 -08002701// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002702#undef LOG_TAG
2703#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002704
Andy Hung8d31fd22023-06-26 19:20:57 -07002705
Andy Hung99b1ba62023-07-14 11:00:08 -07002706/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002707sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002708 const sp<Client>& client,
2709 const audio_attributes_t& attr,
2710 uint32_t sampleRate,
2711 audio_format_t format,
2712 audio_channel_mask_t channelMask,
2713 size_t frameCount,
2714 void* buffer,
2715 size_t bufferSize,
2716 audio_session_t sessionId,
2717 pid_t creatorPid,
2718 const AttributionSourceState& attributionSource,
2719 audio_input_flags_t flags,
2720 track_type type,
2721 audio_port_handle_t portId,
2722 int32_t startFrames)
2723{
2724 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002725 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002726 client,
2727 attr,
2728 sampleRate,
2729 format,
2730 channelMask,
2731 frameCount,
2732 buffer,
2733 bufferSize,
2734 sessionId,
2735 creatorPid,
2736 attributionSource,
2737 flags,
2738 type,
2739 portId,
2740 startFrames);
2741}
2742
Glenn Kasten05997e22014-03-13 15:08:33 -07002743// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002744RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002745 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002746 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002747 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002748 uint32_t sampleRate,
2749 audio_format_t format,
2750 audio_channel_mask_t channelMask,
2751 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002752 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002753 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002754 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002755 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002756 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002757 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002758 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002759 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002760 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002761 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002762 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002763 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002764 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002765 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002766 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002767 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002768 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002769 type, portId,
2770 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002771 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002772 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002773 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002774 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002775 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002776 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002777{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002778 if (mCblk == NULL) {
2779 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002780 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002781
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002782 if (!isDirect()) {
2783 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002784 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002785 channelMask, format, sampleRate);
2786 // Check if the RecordBufferConverter construction was successful.
2787 // If not, don't continue with construction.
2788 //
2789 // NOTE: It would be extremely rare that the record track cannot be created
2790 // for the current device, but a pending or future device change would make
2791 // the record track configuration valid.
2792 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002793 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002794 return;
2795 }
Andy Hung97a893e2015-03-29 01:03:07 -07002796 }
2797
Andy Hung6ae58432016-02-16 18:32:24 -08002798 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002799 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002800
Andy Hung97a893e2015-03-29 01:03:07 -07002801 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002802
Eric Laurent05067782016-06-01 18:27:28 -07002803 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002804 ALOG_ASSERT(thread->fastTrackAvailable());
2805 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002806 } else {
2807 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002808 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002809 }
Andy Hung8946a282018-04-19 20:04:56 -07002810#ifdef TEE_SINK
2811 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2812 + "_" + std::to_string(mId)
2813 + "_R");
2814#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002815
2816 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002817 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002818}
2819
Andy Hung8d31fd22023-06-26 19:20:57 -07002820RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002821{
Andy Hung9d84af52018-09-12 18:03:44 -07002822 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002823 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002824 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002825}
2826
Andy Hung8d31fd22023-06-26 19:20:57 -07002827status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002828{
2829 status_t status = TrackBase::initCheck();
2830 if (status == NO_ERROR && mServerProxy == 0) {
2831 status = BAD_VALUE;
2832 }
2833 return status;
2834}
2835
Eric Laurent81784c32012-11-19 14:55:58 -08002836// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002837status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002838{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002839 ServerProxy::Buffer buf;
2840 buf.mFrameCount = buffer->frameCount;
2841 status_t status = mServerProxy->obtainBuffer(&buf);
2842 buffer->frameCount = buf.mFrameCount;
2843 buffer->raw = buf.mRaw;
2844 if (buf.mFrameCount == 0) {
2845 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002846 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002847 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002848 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002849}
2850
Andy Hung8d31fd22023-06-26 19:20:57 -07002851status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002852 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002853{
Andy Hung87c693c2023-07-06 20:56:16 -07002854 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002855 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002856 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002857 return recordThread->start(this, event, triggerSession);
2858 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002859 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2860 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002861 }
2862}
2863
Andy Hung8d31fd22023-06-26 19:20:57 -07002864void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002865{
Andy Hung87c693c2023-07-06 20:56:16 -07002866 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002867 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002868 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002869 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002870 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002871 }
2872 }
2873}
2874
Andy Hung8d31fd22023-06-26 19:20:57 -07002875void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002876{
Andy Hung8d31fd22023-06-26 19:20:57 -07002877 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002878 sp<RecordTrack> keep(this);
2879 {
Andy Hungce685402018-10-05 17:23:27 -07002880 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002881 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002882 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07002883 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002884 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002885 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002886 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002887 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002888 }
Andy Hungce685402018-10-05 17:23:27 -07002889 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2890 }
2891 // APM portid/client management done outside of lock.
2892 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2893 if (isExternalTrack()) {
2894 switch (priorState) {
2895 case ACTIVE: // invalidated while still active
2896 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2897 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2898 AudioSystem::stopInput(mPortId);
2899 break;
2900
2901 case STARTING_1: // invalidated/start-aborted and startInput not successful
2902 case PAUSED: // OK, not active
2903 case IDLE: // OK, not active
2904 break;
2905
2906 case STOPPED: // unexpected (destroyed)
2907 default:
2908 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2909 }
2910 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002911 }
2912 }
2913}
2914
Andy Hung8d31fd22023-06-26 19:20:57 -07002915void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002916{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002917 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002918 // FIXME should use proxy, and needs work
2919 audio_track_cblk_t* cblk = mCblk;
2920 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2921 android_atomic_release_store(0x40000000, &cblk->mFutex);
2922 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002923 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002924}
2925
Eric Laurent81784c32012-11-19 14:55:58 -08002926
Andy Hung8d31fd22023-06-26 19:20:57 -07002927void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002928{
Eric Laurent973db022018-11-20 14:54:31 -08002929 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002930 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002931 " Server FrmCnt FrmRdy Sil%s\n",
2932 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002933}
2934
Andy Hung8d31fd22023-06-26 19:20:57 -07002935void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002936{
Eric Laurent973db022018-11-20 14:54:31 -08002937 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002938 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002939 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002940 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002941 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002942 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002943 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002944 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002945 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002946 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002947 mCblk->mFlags,
2948
Eric Laurent81784c32012-11-19 14:55:58 -08002949 mFormat,
2950 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002951 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002952 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002953
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002954 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002955 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002956 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002957 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002958 );
Andy Hung000adb52018-06-01 15:43:26 -07002959 if (isServerLatencySupported()) {
2960 double latencyMs;
2961 bool fromTrack;
2962 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2963 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2964 // or 'k' if estimated from kernel (usually for debugging).
2965 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2966 } else {
2967 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2968 }
2969 }
2970 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002971}
2972
Andy Hung93bb5732023-05-04 21:16:34 -07002973// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002974void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002975 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002976{
Andy Hung93bb5732023-05-04 21:16:34 -07002977 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002978 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002979 if (threadBase != 0) {
2980 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2981 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07002982 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002983 }
Andy Hung93bb5732023-05-04 21:16:34 -07002984
2985 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002986}
2987
Andy Hung8d31fd22023-06-26 19:20:57 -07002988void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002989{
Andy Hung93bb5732023-05-04 21:16:34 -07002990 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002991}
2992
Andy Hung8d31fd22023-06-26 19:20:57 -07002993void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002994 int64_t trackFramesReleased, int64_t sourceFramesRead,
2995 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2996{
Andy Hung30282562018-08-08 18:27:03 -07002997 // Make the kernel frametime available.
2998 const FrameTime ft{
2999 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
3000 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
3001 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
3002 mKernelFrameTime.store(ft);
3003 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05003004 // Stream is direct, return provided timestamp with no conversion
3005 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07003006 return;
3007 }
3008
Andy Hung3f0c9022016-01-15 17:49:46 -08003009 ExtendedTimestamp local = timestamp;
3010
3011 // Convert HAL frames to server-side track frames at track sample rate.
3012 // We use trackFramesReleased and sourceFramesRead as an anchor point.
3013 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
3014 if (local.mTimeNs[i] != 0) {
3015 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
3016 const int64_t relativeTrackFrames = relativeServerFrames
3017 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3018 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3019 }
3020 }
Andy Hung6ae58432016-02-16 18:32:24 -08003021 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003022
3023 // Compute latency info.
3024 const bool useTrackTimestamp = true; // use track unless debugging.
3025 const double latencyMs = - (useTrackTimestamp
3026 ? local.getOutputServerLatencyMs(sampleRate())
3027 : timestamp.getOutputServerLatencyMs(halSampleRate));
3028
3029 mServerLatencyFromTrack.store(useTrackTimestamp);
3030 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003031}
Eric Laurent83b88082014-06-20 18:31:16 -07003032
Andy Hung8d31fd22023-06-26 19:20:57 -07003033status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07003034 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003035{
Andy Hung87c693c2023-07-06 20:56:16 -07003036 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003037 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003038 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003039 return recordThread->getActiveMicrophones(activeMicrophones);
3040 } else {
3041 return BAD_VALUE;
3042 }
3043}
3044
Andy Hung8d31fd22023-06-26 19:20:57 -07003045status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003046 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003047 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003048 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003049 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003050 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003051 } else {
3052 return BAD_VALUE;
3053 }
3054}
3055
Andy Hung8d31fd22023-06-26 19:20:57 -07003056status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003057 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003058 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003059 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003060 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003061 } else {
3062 return BAD_VALUE;
3063 }
3064}
3065
Andy Hung8d31fd22023-06-26 19:20:57 -07003066status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003067 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3068
3069 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3070 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3071 if (callingUid != mUid || callingPid != mCreatorPid) {
3072 return PERMISSION_DENIED;
3073 }
3074
Svet Ganov33761132021-05-13 22:51:08 +00003075 AttributionSourceState attributionSource{};
3076 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3077 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3078 attributionSource.token = sp<BBinder>::make();
3079 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003080 return PERMISSION_DENIED;
3081 }
3082
Andy Hung87c693c2023-07-06 20:56:16 -07003083 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003084 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003085 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003086 status_t status = recordThread->shareAudioHistory(
3087 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3088 if (status == NO_ERROR) {
3089 mSharedAudioPackageName = sharedAudioPackageName;
3090 }
3091 return status;
3092 } else {
3093 return BAD_VALUE;
3094 }
3095}
3096
Andy Hung8d31fd22023-06-26 19:20:57 -07003097void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003098{
3099
3100 // Do not forward PatchRecord metadata with unspecified audio source
3101 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3102 return;
3103 }
3104
3105 // No track is invalid as this is called after prepareTrack_l in the same critical section
3106 record_track_metadata_v7_t metadata;
3107 metadata.base = {
3108 .source = mAttr.source,
3109 .gain = 1, // capture tracks do not have volumes
3110 };
3111 metadata.channel_mask = mChannelMask;
3112 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3113
3114 *backInserter++ = metadata;
3115}
Eric Laurentec376dc2021-04-08 20:41:22 +02003116
Andy Hung9d84af52018-09-12 18:03:44 -07003117// ----------------------------------------------------------------------------
3118#undef LOG_TAG
3119#define LOG_TAG "AF::PatchRecord"
3120
Andy Hung8d31fd22023-06-26 19:20:57 -07003121/* static */
3122sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003123 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003124 uint32_t sampleRate,
3125 audio_channel_mask_t channelMask,
3126 audio_format_t format,
3127 size_t frameCount,
3128 void *buffer,
3129 size_t bufferSize,
3130 audio_input_flags_t flags,
3131 const Timeout& timeout,
3132 audio_source_t source)
3133{
3134 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003135 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003136 sampleRate,
3137 channelMask,
3138 format,
3139 frameCount,
3140 buffer,
3141 bufferSize,
3142 flags,
3143 timeout,
3144 source);
3145}
3146
Andy Hung87c693c2023-07-06 20:56:16 -07003147PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003148 uint32_t sampleRate,
3149 audio_channel_mask_t channelMask,
3150 audio_format_t format,
3151 size_t frameCount,
3152 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003153 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003154 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003155 const Timeout& timeout,
3156 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003157 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003158 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003159 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003160 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003161 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003162 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3163 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003164 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003165{
Andy Hung9d84af52018-09-12 18:03:44 -07003166 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3167 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003168 (int)mPeerTimeout.tv_sec,
3169 (int)(mPeerTimeout.tv_nsec / 1000000));
3170}
3171
Andy Hung8d31fd22023-06-26 19:20:57 -07003172PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003173{
Andy Hungabfab202019-03-07 19:45:54 -08003174 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003175}
3176
Mikhail Naganov8296c252019-09-25 14:59:54 -07003177static size_t writeFramesHelper(
3178 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3179{
3180 AudioBufferProvider::Buffer patchBuffer;
3181 patchBuffer.frameCount = frameCount;
3182 auto status = dest->getNextBuffer(&patchBuffer);
3183 if (status != NO_ERROR) {
3184 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3185 __func__, status, strerror(-status));
3186 return 0;
3187 }
3188 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3189 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3190 size_t framesWritten = patchBuffer.frameCount;
3191 dest->releaseBuffer(&patchBuffer);
3192 return framesWritten;
3193}
3194
3195// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003196size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003197 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3198{
3199 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3200 // On buffer wrap, the buffer frame count will be less than requested,
3201 // when this happens a second buffer needs to be used to write the leftover audio
3202 const size_t framesLeft = frameCount - framesWritten;
3203 if (framesWritten != 0 && framesLeft != 0) {
3204 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3205 framesLeft, frameSize);
3206 }
3207 return framesWritten;
3208}
3209
Eric Laurent83b88082014-06-20 18:31:16 -07003210// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003211status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003212 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003213{
Andy Hung9d84af52018-09-12 18:03:44 -07003214 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003215 Proxy::Buffer buf;
3216 buf.mFrameCount = buffer->frameCount;
3217 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3218 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003219 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003220 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003221 if (ATRACE_ENABLED()) {
3222 std::string traceName("PRnObt");
3223 traceName += std::to_string(id());
3224 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3225 }
Eric Laurent83b88082014-06-20 18:31:16 -07003226 if (buf.mFrameCount == 0) {
3227 return WOULD_BLOCK;
3228 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003229 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003230 return status;
3231}
3232
Andy Hung8d31fd22023-06-26 19:20:57 -07003233void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003234{
Andy Hung9d84af52018-09-12 18:03:44 -07003235 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003236 Proxy::Buffer buf;
3237 buf.mFrameCount = buffer->frameCount;
3238 buf.mRaw = buffer->raw;
3239 mPeerProxy->releaseBuffer(&buf);
3240 TrackBase::releaseBuffer(buffer);
3241}
3242
Andy Hung8d31fd22023-06-26 19:20:57 -07003243status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003244 const struct timespec *timeOut)
3245{
3246 return mProxy->obtainBuffer(buffer, timeOut);
3247}
3248
Andy Hung8d31fd22023-06-26 19:20:57 -07003249void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003250{
3251 mProxy->releaseBuffer(buffer);
3252}
3253
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003254#undef LOG_TAG
3255#define LOG_TAG "AF::PthrPatchRecord"
3256
3257static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3258{
3259 void *ptr = nullptr;
3260 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003261 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003262}
3263
Andy Hung8d31fd22023-06-26 19:20:57 -07003264/* static */
3265sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003266 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003267 uint32_t sampleRate,
3268 audio_channel_mask_t channelMask,
3269 audio_format_t format,
3270 size_t frameCount,
3271 audio_input_flags_t flags,
3272 audio_source_t source)
3273{
3274 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003275 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003276 sampleRate,
3277 channelMask,
3278 format,
3279 frameCount,
3280 flags,
3281 source);
3282}
3283
3284PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003285 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003286 uint32_t sampleRate,
3287 audio_channel_mask_t channelMask,
3288 audio_format_t format,
3289 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003290 audio_input_flags_t flags,
3291 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003292 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003293 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003294 mPatchRecordAudioBufferProvider(*this),
3295 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3296 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3297{
3298 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3299}
3300
Andy Hung8d31fd22023-06-26 19:20:57 -07003301sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003302 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003303{
3304 *thread = mThread.promote();
3305 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003306 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07003307 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07003308 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003309}
3310
3311// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003312status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003313 Proxy::Buffer* buffer, const struct timespec* timeOut)
3314{
3315 if (mUnconsumedFrames) {
3316 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3317 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3318 return PatchRecord::obtainBuffer(buffer, timeOut);
3319 }
3320
3321 // Otherwise, execute a read from HAL and write into the buffer.
3322 nsecs_t startTimeNs = 0;
3323 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3324 // Will need to correct timeOut by elapsed time.
3325 startTimeNs = systemTime();
3326 }
3327 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3328 buffer->mFrameCount = 0;
3329 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003330 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003331 sp<StreamInHalInterface> stream = obtainStream(&thread);
3332 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3333
3334 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003335 size_t bytesRead = 0;
3336 {
3337 ATRACE_NAME("read");
3338 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3339 if (result != NO_ERROR) goto stream_error;
3340 if (bytesRead == 0) return NO_ERROR;
3341 }
3342
3343 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003344 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003345 mReadBytes += bytesRead;
3346 mReadError = NO_ERROR;
3347 }
3348 mReadCV.notify_one();
3349 // writeFrames handles wraparound and should write all the provided frames.
3350 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3351 buffer->mFrameCount = writeFrames(
3352 &mPatchRecordAudioBufferProvider,
3353 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3354 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3355 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3356 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003357 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003358 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003359 // Correct the timeout by elapsed time.
3360 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003361 if (newTimeOutNs < 0) newTimeOutNs = 0;
3362 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3363 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003364 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003365 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003366 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003367
3368stream_error:
3369 stream->standby();
3370 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003371 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003372 mReadError = result;
3373 }
3374 mReadCV.notify_one();
3375 return result;
3376}
3377
Andy Hung8d31fd22023-06-26 19:20:57 -07003378void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003379{
3380 if (buffer->mFrameCount <= mUnconsumedFrames) {
3381 mUnconsumedFrames -= buffer->mFrameCount;
3382 } else {
3383 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3384 buffer->mFrameCount, mUnconsumedFrames);
3385 mUnconsumedFrames = 0;
3386 }
3387 PatchRecord::releaseBuffer(buffer);
3388}
3389
3390// AudioBufferProvider and Source methods are called on RecordThread
3391// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3392// and 'releaseBuffer' are stubbed out and ignore their input.
3393// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3394// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003395status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003396 void* buffer, size_t bytes, size_t* read)
3397{
3398 bytes = std::min(bytes, mFrameCount * mFrameSize);
3399 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003400 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003401 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3402 if (mReadError != NO_ERROR) {
3403 mLastReadFrames = 0;
3404 return mReadError;
3405 }
3406 *read = std::min(bytes, mReadBytes);
3407 mReadBytes -= *read;
3408 }
3409 mLastReadFrames = *read / mFrameSize;
3410 memset(buffer, 0, *read);
3411 return 0;
3412}
3413
Andy Hung8d31fd22023-06-26 19:20:57 -07003414status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003415 int64_t* frames, int64_t* time)
3416{
Andy Hung87c693c2023-07-06 20:56:16 -07003417 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003418 sp<StreamInHalInterface> stream = obtainStream(&thread);
3419 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3420}
3421
Andy Hung8d31fd22023-06-26 19:20:57 -07003422status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003423{
3424 // RecordThread issues 'standby' command in two major cases:
3425 // 1. Error on read--this case is handled in 'obtainBuffer'.
3426 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3427 // output, this can only happen when the software patch
3428 // is being torn down. In this case, the RecordThread
3429 // will terminate and close the HAL stream.
3430 return 0;
3431}
3432
3433// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003434status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003435 AudioBufferProvider::Buffer* buffer)
3436{
3437 buffer->frameCount = mLastReadFrames;
3438 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3439 return NO_ERROR;
3440}
3441
Andy Hung8d31fd22023-06-26 19:20:57 -07003442void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003443 AudioBufferProvider::Buffer* buffer)
3444{
3445 buffer->frameCount = 0;
3446 buffer->raw = nullptr;
3447}
3448
Andy Hung9d84af52018-09-12 18:03:44 -07003449// ----------------------------------------------------------------------------
3450#undef LOG_TAG
3451#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003452
Andy Hung8d31fd22023-06-26 19:20:57 -07003453/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003454sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003455 const audio_attributes_t& attr,
3456 uint32_t sampleRate,
3457 audio_format_t format,
3458 audio_channel_mask_t channelMask,
3459 audio_session_t sessionId,
3460 bool isOut,
3461 const android::content::AttributionSourceState& attributionSource,
3462 pid_t creatorPid,
3463 audio_port_handle_t portId)
3464{
3465 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003466 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003467 attr,
3468 sampleRate,
3469 format,
3470 channelMask,
3471 sessionId,
3472 isOut,
3473 attributionSource,
3474 creatorPid,
3475 portId);
3476}
3477
Andy Hung87c693c2023-07-06 20:56:16 -07003478MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003479 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003480 uint32_t sampleRate,
3481 audio_format_t format,
3482 audio_channel_mask_t channelMask,
3483 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003484 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003485 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003486 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003487 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003488 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003489 channelMask, (size_t)0 /* frameCount */,
3490 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003491 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003492 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003493 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003494 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003495 TYPE_DEFAULT, portId,
3496 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003497 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003498 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003499{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003500 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003501 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003502}
3503
Andy Hung8d31fd22023-06-26 19:20:57 -07003504MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003505{
3506}
3507
Andy Hung8d31fd22023-06-26 19:20:57 -07003508status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003509{
3510 return NO_ERROR;
3511}
3512
Andy Hung8d31fd22023-06-26 19:20:57 -07003513status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003514 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003515{
3516 return NO_ERROR;
3517}
3518
Andy Hung8d31fd22023-06-26 19:20:57 -07003519void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003520{
3521}
3522
3523// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003524status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003525{
3526 buffer->frameCount = 0;
3527 buffer->raw = nullptr;
3528 return INVALID_OPERATION;
3529}
3530
3531// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003532size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003533 return 0;
3534}
3535
Andy Hung8d31fd22023-06-26 19:20:57 -07003536int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003537{
3538 return 0;
3539}
3540
Andy Hung8d31fd22023-06-26 19:20:57 -07003541void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003542{
3543}
3544
Andy Hung8d31fd22023-06-26 19:20:57 -07003545void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003546{
3547 if (mMuteState == muteState) {
3548 // mute state did not change, do nothing
3549 return;
3550 }
3551
3552 status_t result = UNKNOWN_ERROR;
3553 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3554 if (mMuteEventExtras == nullptr) {
3555 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3556 }
3557 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3558 static_cast<int>(muteState));
3559
3560 result = audioManager->portEvent(mPortId,
3561 PLAYER_UPDATE_MUTED,
3562 mMuteEventExtras);
3563 }
3564
3565 if (result == OK) {
Andy Hung0e26ec62024-02-20 16:32:57 -08003566 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
3567 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popaec1788e2022-08-04 11:23:30 +02003568 mMuteState = muteState;
3569 } else {
3570 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3571 __func__,
3572 id(),
3573 mPortId,
3574 result);
3575 }
3576}
3577
Andy Hung8d31fd22023-06-26 19:20:57 -07003578void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003579{
Eric Laurent973db022018-11-20 14:54:31 -08003580 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003581 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003582}
3583
Andy Hung8d31fd22023-06-26 19:20:57 -07003584void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003585{
Eric Laurent973db022018-11-20 14:54:31 -08003586 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003587 mPid,
3588 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003589 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003590 mFormat,
3591 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003592 mSampleRate,
3593 mAttr.flags);
3594 if (isOut()) {
3595 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3596 } else {
3597 result.appendFormat("%6x", mAttr.source);
3598 }
3599 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003600}
3601
Glenn Kasten63238ef2015-03-02 15:50:29 -08003602} // namespace android