blob: f5f11ccd1717554947a3ec60b3c7413d93342151 [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Eric Laurent81784c32012-11-19 14:55:58 -080018#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070020#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080021
Andy Hung0f725b42023-07-19 11:40:07 -070022#include "MmapTracks.h"
23#include "PlaybackTracks.h"
24#include "RecordTracks.h"
25
26#include "Client.h"
27#include "IAfEffect.h"
28#include "IAfThread.h"
29#include "ResamplerBufferProvider.h"
30
31#include <audio_utils/minifloat.h>
32#include <media/AudioValidator.h>
33#include <media/RecordBufferConverter.h>
34#include <media/nbaio/Pipe.h>
35#include <media/nbaio/PipeReader.h>
36#include <mediautils/ServiceUtilities.h>
37#include <mediautils/SharedMemoryAllocator.h>
38#include <private/media/AudioTrackShared.h>
Eric Laurent81784c32012-11-19 14:55:58 -080039#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070040#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080041
Andy Hung0f725b42023-07-19 11:40:07 -070042#include <linux/futex.h>
43#include <math.h>
44#include <sys/syscall.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080045
Eric Laurent81784c32012-11-19 14:55:58 -080046// ----------------------------------------------------------------------------
47
48// Note: the following macro is used for extremely verbose logging message. In
49// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
50// 0; but one side effect of this is to turn all LOGV's as well. Some messages
51// are so verbose that we want to suppress them even when we have ALOG_ASSERT
52// turned on. Do not uncomment the #def below unless you really know what you
53// are doing and want to see all of the extremely verbose messages.
54//#define VERY_VERY_VERBOSE_LOGGING
55#ifdef VERY_VERY_VERBOSE_LOGGING
56#define ALOGVV ALOGV
57#else
58#define ALOGVV(a...) do { } while(0)
59#endif
60
Kuowei Lid4adbdb2020-08-13 14:44:25 +080061// TODO: Remove when this is put into AidlConversionUtil.h
62#define VALUE_OR_RETURN_BINDER_STATUS(x) \
63 ({ \
64 auto _tmp = (x); \
65 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
66 std::move(_tmp.value()); \
67 })
68
Eric Laurent81784c32012-11-19 14:55:58 -080069namespace android {
70
Kuowei Lid4adbdb2020-08-13 14:44:25 +080071using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080072using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000073using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070074using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080075// ----------------------------------------------------------------------------
76// TrackBase
77// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070078#undef LOG_TAG
79#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080080
Glenn Kastenda6ef132013-01-10 12:31:01 -080081static volatile int32_t nextTrackId = 55;
82
Eric Laurent81784c32012-11-19 14:55:58 -080083// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung87c693c2023-07-06 20:56:16 -070085 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080086 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070087 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080088 uint32_t sampleRate,
89 audio_format_t format,
90 audio_channel_mask_t channelMask,
91 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070092 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070093 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080094 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070095 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080096 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070097 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070098 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080099 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800100 audio_port_handle_t portId,
101 std::string metricsId)
Andy Hungd29af632023-06-23 19:27:19 -0700102 :
Eric Laurent81784c32012-11-19 14:55:58 -0800103 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700104 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800105 mClient(client),
106 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700107 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800108 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700109 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800110 mSampleRate(sampleRate),
111 mFormat(format),
112 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700113 mChannelCount(isOut ?
114 audio_channel_count_from_out_mask(channelMask) :
115 audio_channel_count_from_in_mask(channelMask)),
Dean Wheatleyd883e302023-10-20 06:11:43 +1100116 mFrameSize(audio_bytes_per_frame(mChannelCount, format)),
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung8d31fd22023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung8d31fd22023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung954b9712023-08-28 18:36:53 -0700279 audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung8d31fd22023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung8d31fd22023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung56ce2ed2024-06-12 16:03:16 -0700317void TrackBase::deferRestartIfDisabled()
318{
319 const auto thread = mThread.promote();
320 if (thread == nullptr) return;
321 thread->getThreadloopExecutor().defer(
322 [track = wp<TrackBase>::fromExisting(this)] {
323 const auto actual = track.promote();
324 if (actual) actual->restartIfDisabled();
325 });
326}
327
Andy Hung8d31fd22023-06-26 19:20:57 -0700328PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700329 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800330 : mProxy(proxy)
331{
332 if (timeout) {
333 setPeerTimeout(*timeout);
334 } else {
335 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700336 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
337 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800338 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
339 }
340}
341
Andy Hung8d31fd22023-06-26 19:20:57 -0700342void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800343 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
344 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
345}
346
347
Eric Laurent81784c32012-11-19 14:55:58 -0800348// ----------------------------------------------------------------------------
349// Playback
350// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700351#undef LOG_TAG
352#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800353
Andy Hunga5a7fc92023-06-23 19:27:19 -0700354class TrackHandle : public android::media::BnAudioTrack {
355public:
Andy Hungd29af632023-06-23 19:27:19 -0700356 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700357 ~TrackHandle() override;
358
359 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
360 binder::Status start(int32_t* _aidl_return) final;
361 binder::Status stop() final;
362 binder::Status flush() final;
363 binder::Status pause() final;
364 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
365 binder::Status setParameters(const std::string& keyValuePairs,
366 int32_t* _aidl_return) final;
367 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
368 int32_t* _aidl_return) final;
369 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
370 int32_t* _aidl_return) final;
371 binder::Status signal() final;
372 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
373 const media::VolumeShaperOperation& operation,
374 int32_t* _aidl_return) final;
375 binder::Status getVolumeShaperState(
376 int32_t id,
377 std::optional<media::VolumeShaperState>* _aidl_return) final;
378 binder::Status getDualMonoMode(
379 media::audio::common::AudioDualMonoMode* _aidl_return) final;
380 binder::Status setDualMonoMode(
381 media::audio::common::AudioDualMonoMode mode) final;
382 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
383 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
384 binder::Status getPlaybackRateParameters(
385 media::audio::common::AudioPlaybackRate* _aidl_return) final;
386 binder::Status setPlaybackRateParameters(
387 const media::audio::common::AudioPlaybackRate& playbackRate) final;
388
389private:
Andy Hungd29af632023-06-23 19:27:19 -0700390 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700391};
392
393/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700394sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700395 return sp<TrackHandle>::make(track);
396}
397
Andy Hungd29af632023-06-23 19:27:19 -0700398TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800399 : BnAudioTrack(),
400 mTrack(track)
401{
Andy Hung225aef62022-12-06 16:33:20 -0800402 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -0700403 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -0800404}
405
Andy Hunga5a7fc92023-06-23 19:27:19 -0700406TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800407 // just stop the track on deletion, associated resources
408 // will be freed from the main thread once all pending buffers have
409 // been played. Unless it's not in the active track list, in which
410 // case we free everything now...
411 mTrack->destroy();
412}
413
Andy Hunga5a7fc92023-06-23 19:27:19 -0700414Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800415 std::optional<media::SharedFileRegion>* _aidl_return) {
416 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
417 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800418}
419
Andy Hunga5a7fc92023-06-23 19:27:19 -0700420Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 *_aidl_return = mTrack->start();
422 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800423}
424
Andy Hunga5a7fc92023-06-23 19:27:19 -0700425Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800426 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800427 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800428}
429
Andy Hunga5a7fc92023-06-23 19:27:19 -0700430Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800431 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hunga5a7fc92023-06-23 19:27:19 -0700435Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800436 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800437 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800438}
439
Andy Hunga5a7fc92023-06-23 19:27:19 -0700440Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800441 int32_t* _aidl_return) {
442 *_aidl_return = mTrack->attachAuxEffect(effectId);
443 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800444}
445
Andy Hunga5a7fc92023-06-23 19:27:19 -0700446Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800447 int32_t* _aidl_return) {
448 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
449 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700450}
451
Andy Hunga5a7fc92023-06-23 19:27:19 -0700452Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800453 int32_t* _aidl_return) {
454 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
455 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800456}
457
Andy Hunga5a7fc92023-06-23 19:27:19 -0700458Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 int32_t* _aidl_return) {
460 AudioTimestamp legacy;
461 *_aidl_return = mTrack->getTimestamp(legacy);
462 if (*_aidl_return != OK) {
463 return Status::ok();
464 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000465
466 // restrict position modulo INT_MAX to avoid integer sanitization abort
467 legacy.mPosition &= INT_MAX;
468
Andy Hung973638a2020-12-08 20:47:45 -0800469 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800470 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800471}
472
Andy Hunga5a7fc92023-06-23 19:27:19 -0700473Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800474 mTrack->signal();
475 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800476}
477
Andy Hunga5a7fc92023-06-23 19:27:19 -0700478Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800479 const media::VolumeShaperConfiguration& configuration,
480 const media::VolumeShaperOperation& operation,
481 int32_t* _aidl_return) {
482 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
483 *_aidl_return = conf->readFromParcelable(configuration);
484 if (*_aidl_return != OK) {
485 return Status::ok();
486 }
487
488 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
489 *_aidl_return = op->readFromParcelable(operation);
490 if (*_aidl_return != OK) {
491 return Status::ok();
492 }
493
494 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
495 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700496}
497
Andy Hunga5a7fc92023-06-23 19:27:19 -0700498Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800499 int32_t id,
500 std::optional<media::VolumeShaperState>* _aidl_return) {
501 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
502 if (legacy == nullptr) {
503 _aidl_return->reset();
504 return Status::ok();
505 }
506 media::VolumeShaperState aidl;
507 legacy->writeToParcelable(&aidl);
508 *_aidl_return = aidl;
509 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800510}
511
Andy Hunga5a7fc92023-06-23 19:27:19 -0700512Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000513 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800514{
515 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
516 const status_t status = mTrack->getDualMonoMode(&mode)
517 ?: AudioValidator::validateDualMonoMode(mode);
518 if (status == OK) {
519 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
520 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
521 }
522 return binderStatusFromStatusT(status);
523}
524
Andy Hunga5a7fc92023-06-23 19:27:19 -0700525Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000526 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800527{
528 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
529 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
530 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
531 ?: mTrack->setDualMonoMode(localMonoMode));
532}
533
Andy Hunga5a7fc92023-06-23 19:27:19 -0700534Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800535{
536 float leveldB = -std::numeric_limits<float>::infinity();
537 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
538 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
539 if (status == OK) *_aidl_return = leveldB;
540 return binderStatusFromStatusT(status);
541}
542
Andy Hunga5a7fc92023-06-23 19:27:19 -0700543Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800544{
545 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
546 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
547}
548
Andy Hunga5a7fc92023-06-23 19:27:19 -0700549Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000550 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800551{
552 audio_playback_rate_t localPlaybackRate{};
553 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
554 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
555 if (status == NO_ERROR) {
556 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
557 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
558 }
559 return binderStatusFromStatusT(status);
560}
561
Andy Hunga5a7fc92023-06-23 19:27:19 -0700562Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000563 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800564{
565 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
566 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
567 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
568 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
569}
570
Eric Laurent81784c32012-11-19 14:55:58 -0800571// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800572// AppOp for audio playback
573// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700574
575// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700576sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700577 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000578 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700579 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800580{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700581 Vector<String16> packages;
582 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000583 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700584 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700585 if (packages.isEmpty()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000586 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700587 uid);
588 return nullptr;
589 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800590 }
591 // stream type has been filtered by audio policy to indicate whether it can be muted
592 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700593 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700594 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800595 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700596 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
597 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
598 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
599 id, attr.flags);
600 return nullptr;
601 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700602 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700603}
604
Andy Hung87c693c2023-07-06 20:56:16 -0700605OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700606 const AttributionSourceState& attributionSource,
607 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700608 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700609 mHasOpPlayAudio(true),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700610 mUsage((int32_t)usage),
611 mId(id),
612 mUid(uid),
613 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
614 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800615
Andy Hung8d31fd22023-06-26 19:20:57 -0700616OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800617{
618 if (mOpCallback != 0) {
619 mAppOpsManager.stopWatchingMode(mOpCallback);
620 }
621 mOpCallback.clear();
622}
623
Andy Hung8d31fd22023-06-26 19:20:57 -0700624void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700625{
Vlad Popad5859592023-08-02 18:36:04 -0700626 // make sure not to broadcast the initial state since it is not needed and could
627 // cause a deadlock since this method can be called with the mThread->mLock held
628 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000629 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700630 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000631 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
632 } else {
633 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700634 }
635}
636
Andy Hung8d31fd22023-06-26 19:20:57 -0700637bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800638 return mHasOpPlayAudio.load();
639}
640
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700641// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800642// - not called from constructor due to check on UID,
643// - not called from PlayAudioOpCallback because the callback is not installed in this case
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000644void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
645 const bool hasAppOps =
646 mPackageName.size() &&
647 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
648 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700649
650 bool shouldChange = !hasAppOps; // check if we need to update.
651 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000652 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000653 String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
Vlad Popad5859592023-08-02 18:36:04 -0700654 if (doBroadcast) {
655 auto thread = mThread.promote();
656 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
657 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hungc5007f82023-08-29 14:26:09 -0700658 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad5859592023-08-02 18:36:04 -0700659 thread->broadcast_l();
660 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700661 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800662 }
663}
664
Andy Hung8d31fd22023-06-26 19:20:57 -0700665OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800666 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
667{ }
668
Andy Hung8d31fd22023-06-26 19:20:57 -0700669void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800670 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800671 if (op != AppOpsManager::OP_PLAY_AUDIO) {
672 return;
673 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000674
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000675 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800676 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
677 if (monitor != NULL) {
Vlad Popad5859592023-08-02 18:36:04 -0700678 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800679 }
680}
681
Eric Laurent9066ad32019-05-20 14:40:10 -0700682// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700683void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700684 uid_t uid, Vector<String16>& packages)
685{
686 PermissionController permissionController;
687 permissionController.getPackagesForUid(uid, packages);
688}
689
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800690// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700691#undef LOG_TAG
692#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800693
Andy Hung8d31fd22023-06-26 19:20:57 -0700694/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700695sp<IAfTrack> IAfTrack::create(
696 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700697 const sp<Client>& client,
698 audio_stream_type_t streamType,
699 const audio_attributes_t& attr,
700 uint32_t sampleRate,
701 audio_format_t format,
702 audio_channel_mask_t channelMask,
703 size_t frameCount,
704 void *buffer,
705 size_t bufferSize,
706 const sp<IMemory>& sharedBuffer,
707 audio_session_t sessionId,
708 pid_t creatorPid,
709 const AttributionSourceState& attributionSource,
710 audio_output_flags_t flags,
711 track_type type,
712 audio_port_handle_t portId,
713 /** default behaviour is to start when there are as many frames
714 * ready as possible (aka. Buffer is full). */
715 size_t frameCountToBeReady,
716 float speed,
717 bool isSpatialized,
718 bool isBitPerfect) {
Andy Hung87c693c2023-07-06 20:56:16 -0700719 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700720 client,
721 streamType,
722 attr,
723 sampleRate,
724 format,
725 channelMask,
726 frameCount,
727 buffer,
728 bufferSize,
729 sharedBuffer,
730 sessionId,
731 creatorPid,
732 attributionSource,
733 flags,
734 type,
735 portId,
736 frameCountToBeReady,
737 speed,
738 isSpatialized,
739 isBitPerfect);
740}
741
Eric Laurent81784c32012-11-19 14:55:58 -0800742// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700743Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700744 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800745 const sp<Client>& client,
746 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700747 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800748 uint32_t sampleRate,
749 audio_format_t format,
750 audio_channel_mask_t channelMask,
751 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700752 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700753 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800754 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800755 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700756 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000757 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700758 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800759 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100760 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000761 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200762 float speed,
jiabinc658e452022-10-21 20:52:21 +0000763 bool isSpatialized,
764 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700765 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700766 // TODO: Using unsecurePointer() has some associated security pitfalls
767 // (see declaration for details).
768 // Either document why it is safe in this case or address the
769 // issue (e.g. by copying).
770 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700771 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700772 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000773 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700774 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800775 type,
776 portId,
777 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700778 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800779 // mRetryCount initialized later when needed
780 mSharedBuffer(sharedBuffer),
781 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700782 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800783 mAuxBuffer(NULL),
784 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700785 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700786 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700787 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700788 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700789 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800790 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800791 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700792 /* The track might not play immediately after being active, similarly as if its volume was 0.
793 * When the track starts playing, its volume will be computed. */
794 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800795 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700796 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000797 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200798 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000799 mIsSpatialized(isSpatialized),
800 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800801{
Eric Laurent83b88082014-06-20 18:31:16 -0700802 // client == 0 implies sharedBuffer == 0
803 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
804
Andy Hung9d84af52018-09-12 18:03:44 -0700805 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700806 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700807
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700808 if (mCblk == NULL) {
809 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800810 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700811
Svet Ganov33761132021-05-13 22:51:08 +0000812 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700813 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
814 ALOGE("%s(%d): no more tracks available", __func__, mId);
815 releaseCblk(); // this makes the track invalid.
816 return;
817 }
818
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700819 if (sharedBuffer == 0) {
820 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700821 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700822 } else {
823 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100824 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700825 }
826 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700827 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700828
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700829 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700830 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700831 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
832 // race with setSyncEvent(). However, if we call it, we cannot properly start
833 // static fast tracks (SoundPool) immediately after stopping.
834 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700835 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
836 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700837 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700838 // FIXME This is too eager. We allocate a fast track index before the
839 // fast track becomes active. Since fast tracks are a scarce resource,
840 // this means we are potentially denying other more important fast tracks from
841 // being created. It would be better to allocate the index dynamically.
842 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700843 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700844 }
Andy Hung8946a282018-04-19 20:04:56 -0700845
Dean Wheatley7b036912020-06-18 16:22:11 +1000846 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700847#ifdef TEE_SINK
848 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800849 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700850#endif
jiabin57303cc2018-12-18 15:45:57 -0800851
jiabineb3bda02020-06-30 14:07:03 -0700852 if (thread->supportsHapticPlayback()) {
853 // If the track is attached to haptic playback thread, it is potentially to have
854 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
855 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800856 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000857 std::string packageName = attributionSource.packageName.has_value() ?
858 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800859 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700860 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800861 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800862
863 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700864 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800865 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800866}
867
Andy Hung8d31fd22023-06-26 19:20:57 -0700868Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800869{
Andy Hung9d84af52018-09-12 18:03:44 -0700870 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700871
872 // The destructor would clear mSharedBuffer,
873 // but it will not push the decremented reference count,
874 // leaving the client's IMemory dangling indefinitely.
875 // This prevents that leak.
876 if (mSharedBuffer != 0) {
877 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700878 }
Eric Laurent81784c32012-11-19 14:55:58 -0800879}
880
Andy Hung8d31fd22023-06-26 19:20:57 -0700881status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700882{
883 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700884 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700885 status = NO_MEMORY;
886 }
887 return status;
888}
889
Andy Hung8d31fd22023-06-26 19:20:57 -0700890void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800891{
892 // NOTE: destroyTrack_l() can remove a strong reference to this Track
893 // by removing it from mTracks vector, so there is a risk that this Tracks's
894 // destructor is called. As the destructor needs to lock mLock,
895 // we must acquire a strong reference on this Track before locking mLock
896 // here so that the destructor is called only when exiting this function.
897 // On the other hand, as long as Track::destroy() is only called by
898 // TrackHandle destructor, the TrackHandle still holds a strong ref on
899 // this Track with its member mTrack.
900 sp<Track> keep(this);
901 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700902 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700903 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800904 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -0800905 audio_utils::unique_lock ul(thread->mutex());
906 thread->waitWhileThreadBusy_l(ul);
907
Andy Hung87c693c2023-07-06 20:56:16 -0700908 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700909 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000910 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700911 }
912 if (isExternalTrack() && !wasActive) {
Andy Hung6c498e92023-12-05 17:28:17 -0800913 // If the track is not active, the TrackHandle is responsible for
914 // releasing the port id, not the ThreadBase::threadLoop().
915 // At this point, there is no concurrency issue as the track is going away.
Eric Laurentd7fe0862018-07-14 16:48:01 -0700916 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800917 }
918 }
919}
920
Andy Hung8d31fd22023-06-26 19:20:57 -0700921void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800922{
Eric Laurent973db022018-11-20 14:54:31 -0800923 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700924 " Format Chn mask SRate "
925 "ST Usg CT "
926 " G db L dB R dB VS dB "
jiabin220eea12024-05-17 17:55:20 +0000927 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700928 "%s\n",
929 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800930}
931
Andy Hung8d31fd22023-06-26 19:20:57 -0700932void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800933{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700934 char trackType;
935 switch (mType) {
936 case TYPE_DEFAULT:
937 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700938 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700939 trackType = 'S'; // static
940 } else {
941 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800942 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700943 break;
944 case TYPE_PATCH:
945 trackType = 'P';
946 break;
947 default:
948 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800949 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700950
951 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700952 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700953 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700954 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700955 }
956
Eric Laurent81784c32012-11-19 14:55:58 -0800957 char nowInUnderrun;
958 switch (mObservedUnderruns.mBitFields.mMostRecent) {
959 case UNDERRUN_FULL:
960 nowInUnderrun = ' ';
961 break;
962 case UNDERRUN_PARTIAL:
963 nowInUnderrun = '<';
964 break;
965 case UNDERRUN_EMPTY:
966 nowInUnderrun = '*';
967 break;
968 default:
969 nowInUnderrun = '?';
970 break;
971 }
Andy Hungda540db2017-04-20 14:06:17 -0700972
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700973 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700974 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700975 case FS_INVALID:
976 fillingStatus = 'I';
977 break;
978 case FS_FILLING:
979 fillingStatus = 'f';
980 break;
981 case FS_FILLED:
982 fillingStatus = 'F';
983 break;
984 case FS_ACTIVE:
985 fillingStatus = 'A';
986 break;
987 default:
988 fillingStatus = '?';
989 break;
990 }
991
992 // clip framesReadySafe to max representation in dump
993 const size_t framesReadySafe =
994 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
995
996 // obtain volumes
997 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
998 const std::pair<float /* volume */, bool /* active */> vsVolume =
999 mVolumeHandler->getLastVolume();
1000
1001 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
1002 // as it may be reduced by the application.
1003 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
1004 // Check whether the buffer size has been modified by the app.
1005 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
1006 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
1007 ? 'e' /* error */ : ' ' /* identical */;
1008
Eric Laurent973db022018-11-20 14:54:31 -08001009 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001010 "%08X %08X %6u "
1011 "%2u %3x %2x "
1012 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin220eea12024-05-17 17:55:20 +00001013 "%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
Marco Nelissenb2208842014-02-07 14:00:50 -08001014 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001015 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001016 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001017 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001018 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001019 mCblk->mFlags,
1020
Eric Laurent81784c32012-11-19 14:55:58 -08001021 mFormat,
1022 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001023 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001024
1025 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001026 mAttr.usage,
1027 mAttr.content_type,
1028
1029 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001030 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1031 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001032 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1033 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001034
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001035 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001036 bufferSizeInFrames,
1037 modifiedBufferChar,
1038 framesReadySafe,
1039 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001040 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001041 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001042 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
jiabin220eea12024-05-17 17:55:20 +00001043 isBitPerfect() ? "true" : "false",
1044 getInternalMute() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001045 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001046
1047 if (isServerLatencySupported()) {
1048 double latencyMs;
1049 bool fromTrack;
1050 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1051 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1052 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1053 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001054 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001055 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001056 }
1057 }
1058 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001059}
1060
Andy Hung8d31fd22023-06-26 19:20:57 -07001061uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001062 return mAudioTrackServerProxy->getSampleRate();
1063}
1064
Eric Laurent81784c32012-11-19 14:55:58 -08001065// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001066status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001067{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001068 ServerProxy::Buffer buf;
1069 size_t desiredFrames = buffer->frameCount;
1070 buf.mFrameCount = desiredFrames;
1071 status_t status = mServerProxy->obtainBuffer(&buf);
1072 buffer->frameCount = buf.mFrameCount;
1073 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001074 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001075 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001076 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001077 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001078 } else {
1079 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001080 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001081 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001082}
1083
Andy Hung8d31fd22023-06-26 19:20:57 -07001084void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001085{
1086 interceptBuffer(*buffer);
1087 TrackBase::releaseBuffer(buffer);
1088}
1089
1090// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001091void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001092 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001093 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001094 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001095 if (frameCount == 0) {
1096 return; // No audio to intercept.
1097 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1098 // does not allow 0 frame size request contrary to getNextBuffer
1099 }
Jiabin Huang73f97052023-12-12 20:08:03 +00001100 TeePatches teePatches;
1101 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1102 // Cache a copy of tee patches in case it is updated while using.
1103 teePatches = mTeePatches;
1104 mTeePatchesRWLock.unlock();
1105 }
1106 for (auto& teePatch : teePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001107 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001108 const size_t framesWritten = patchRecord->writeFrames(
1109 sourceBuffer.i8, frameCount, mFrameSize);
1110 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001111 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001112 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001113 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001114 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001115 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1116 using namespace std::chrono_literals;
1117 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001118 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang73f97052023-12-12 20:08:03 +00001119 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001120}
1121
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001122// ExtendedAudioBufferProvider interface
1123
Andy Hung27876c02014-09-09 18:07:55 -07001124// framesReady() may return an approximation of the number of frames if called
1125// from a different thread than the one calling Proxy->obtainBuffer() and
1126// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1127// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001128size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001129 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1130 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1131 // The remainder of the buffer is not drained.
1132 return 0;
1133 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001134 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001135}
1136
Andy Hung8d31fd22023-06-26 19:20:57 -07001137int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001138{
1139 return mAudioTrackServerProxy->framesReleased();
1140}
1141
Andy Hung8d31fd22023-06-26 19:20:57 -07001142void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001143{
1144 // This call comes from a FastTrack and should be kept lockless.
1145 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001146 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001147
Andy Hung818e7a32016-02-16 18:08:07 -08001148 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001149
1150 // Compute latency.
1151 // TODO: Consider whether the server latency may be passed in by FastMixer
1152 // as a constant for all active FastTracks.
1153 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1154 mServerLatencyFromTrack.store(true);
1155 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001156}
1157
Eric Laurent81784c32012-11-19 14:55:58 -08001158// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001159bool Track::isReady() const {
1160 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001161 return true;
1162 }
1163
Eric Laurent16498512014-03-17 17:22:08 -07001164 if (isStopping()) {
1165 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001166 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001167 }
Eric Laurent81784c32012-11-19 14:55:58 -08001168 return true;
1169 }
1170
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001171 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001172 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1173 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1174 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1175 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001176
1177 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1178 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1179 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001180 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001181 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001182 return true;
1183 }
1184 return false;
1185}
1186
Andy Hung8d31fd22023-06-26 19:20:57 -07001187status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001188 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001189{
1190 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001191 ALOGV("%s(%d): calling pid %d session %d",
1192 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001193
Andy Hung87c693c2023-07-06 20:56:16 -07001194 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001195 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001196 if (isOffloaded()) {
Andy Hung954b9712023-08-28 18:36:53 -07001197 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hungab65b182023-09-06 19:41:47 -07001198 const bool nonOffloadableGlobalEffectEnabled =
1199 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hungc5007f82023-08-29 14:26:09 -07001200 audio_utils::lock_guard _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001201 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hungab65b182023-09-06 19:41:47 -07001202 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001203 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001204 invalidate();
1205 return PERMISSION_DENIED;
1206 }
1207 }
Andy Hung6c498e92023-12-05 17:28:17 -08001208 audio_utils::unique_lock ul(thread->mutex());
1209 thread->waitWhileThreadBusy_l(ul);
1210
Eric Laurent81784c32012-11-19 14:55:58 -08001211 track_state state = mState;
1212 // here the track could be either new, or restarted
1213 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001214
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001215 // initial state-stopping. next state-pausing.
1216 // What if resume is called ?
1217
Zhou Song1ed46a22020-08-17 15:36:56 +08001218 if (state == FLUSHED) {
1219 // avoid underrun glitches when starting after flush
1220 reset();
1221 }
1222
kuowei.li576f1362021-05-11 18:02:32 +08001223 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1224 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001225 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001226 if (mResumeToStopping) {
1227 // happened we need to resume to STOPPING_1
1228 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001229 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1230 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001231 } else {
1232 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001233 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1234 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001235 }
Eric Laurent81784c32012-11-19 14:55:58 -08001236 } else {
1237 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001238 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1239 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001240 }
1241
Andy Hung87c693c2023-07-06 20:56:16 -07001242 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001243
1244 // states to reset position info for pcm tracks
1245 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001246 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1247 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001248
Dorin Drimusb882d482024-01-17 18:30:02 +01001249 if (!isFastTrack()) {
yucliu6cfb5932022-07-20 17:40:39 -07001250 // Start point of track -> sink frame map. If the HAL returns a
1251 // frame position smaller than the first written frame in
1252 // updateTrackFrameInfo, the timestamp can be interpolated
1253 // instead of using a larger value.
1254 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1255 playbackThread->framesWritten());
1256 }
Andy Hunge10393e2015-06-12 13:59:33 -07001257 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001258 if (isFastTrack()) {
1259 // refresh fast track underruns on start because that field is never cleared
1260 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1261 // after stop.
1262 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1263 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001264 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001265 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001266 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001267 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001268 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001269 mState = state;
1270 }
1271 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001272
Andy Hungb68f5eb2019-12-03 16:49:17 -08001273 // Audio timing metrics are computed a few mix cycles after starting.
1274 {
1275 mLogStartCountdown = LOG_START_COUNTDOWN;
1276 mLogStartTimeNs = systemTime();
1277 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001278 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1279 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001280 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001281 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001282
Andy Hung1d3556d2018-03-29 16:30:14 -07001283 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1284 // for streaming tracks, remove the buffer read stop limit.
1285 mAudioTrackServerProxy->start();
1286 }
1287
Eric Laurentbfb1b832013-01-07 09:53:42 -08001288 // track was already in the active list, not a problem
1289 if (status == ALREADY_EXISTS) {
1290 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001291 } else {
1292 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1293 // It is usually unsafe to access the server proxy from a binder thread.
1294 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1295 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1296 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001297 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001298 ServerProxy::Buffer buffer;
1299 buffer.mFrameCount = 1;
1300 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001301 }
jiabin7434e812023-06-27 18:22:35 +00001302 if (status == NO_ERROR) {
1303 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1304 }
Eric Laurent81784c32012-11-19 14:55:58 -08001305 } else {
1306 status = BAD_VALUE;
1307 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001308 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001309 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001310 const sp<IAudioManager> audioManager =
1311 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001312 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1313 std::unique_ptr<os::PersistableBundle> bundle =
1314 std::make_unique<os::PersistableBundle>();
1315 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1316 isSpatialized());
1317 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1318 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1319 status_t result = audioManager->portEvent(mPortId,
1320 PLAYER_UPDATE_FORMAT, bundle);
1321 if (result != OK) {
1322 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1323 __func__, mPortId, result);
1324 }
1325 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001326 }
Eric Laurent81784c32012-11-19 14:55:58 -08001327 return status;
1328}
1329
Andy Hung8d31fd22023-06-26 19:20:57 -07001330void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001331{
Andy Hungc0691382018-09-12 18:01:57 -07001332 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001333 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001334 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001335 audio_utils::unique_lock ul(thread->mutex());
1336 thread->waitWhileThreadBusy_l(ul);
1337
Eric Laurent81784c32012-11-19 14:55:58 -08001338 track_state state = mState;
1339 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1340 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001341 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1342 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001343 reset();
1344 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001345 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1346 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1347 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001348 mState = STOPPED;
1349 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001350 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1351 // presentation is complete
1352 // For an offloaded track this starts a drain and state will
1353 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001354 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001355 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001356 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001357 }
Eric Laurent81784c32012-11-19 14:55:58 -08001358 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001359 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001360 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1361 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001362 }
jiabin7434e812023-06-27 18:22:35 +00001363 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001364 }
1365}
1366
Andy Hung8d31fd22023-06-26 19:20:57 -07001367void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001368{
Andy Hungc0691382018-09-12 18:01:57 -07001369 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001370 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001371 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001372 audio_utils::unique_lock ul(thread->mutex());
1373 thread->waitWhileThreadBusy_l(ul);
1374
Andy Hung87c693c2023-07-06 20:56:16 -07001375 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001376 switch (mState) {
1377 case STOPPING_1:
1378 case STOPPING_2:
1379 if (!isOffloaded()) {
1380 /* nothing to do if track is not offloaded */
1381 break;
1382 }
1383
1384 // Offloaded track was draining, we need to carry on draining when resumed
1385 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001386 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001387 case ACTIVE:
1388 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001389 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001390 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1391 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001392 if (isOffloadedOrDirect()) {
1393 mPauseHwPending = true;
1394 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001395 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001396 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001397
Eric Laurentbfb1b832013-01-07 09:53:42 -08001398 default:
1399 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001400 }
jiabin7434e812023-06-27 18:22:35 +00001401 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1402 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001403 }
1404}
1405
Andy Hung8d31fd22023-06-26 19:20:57 -07001406void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001407{
Andy Hungc0691382018-09-12 18:01:57 -07001408 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001409 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001410 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001411 audio_utils::unique_lock ul(thread->mutex());
1412 thread->waitWhileThreadBusy_l(ul);
1413
Andy Hung87c693c2023-07-06 20:56:16 -07001414 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001415
Phil Burk4bb650b2016-09-09 12:11:17 -07001416 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1417 // Otherwise the flush would not be done until the track is resumed.
1418 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001419 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001420 (void)mServerProxy->flushBufferIfNeeded();
1421 }
1422
Eric Laurentbfb1b832013-01-07 09:53:42 -08001423 if (isOffloaded()) {
1424 // If offloaded we allow flush during any state except terminated
1425 // and keep the track active to avoid problems if user is seeking
1426 // rapidly and underlying hardware has a significant delay handling
1427 // a pause
1428 if (isTerminated()) {
1429 return;
1430 }
1431
Andy Hung9d84af52018-09-12 18:03:44 -07001432 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001433 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001434
1435 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001436 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1437 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001438 mState = ACTIVE;
1439 }
1440
Haynes Mathew George7844f672014-01-15 12:32:55 -08001441 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001442 mResumeToStopping = false;
1443 } else {
1444 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1445 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1446 return;
1447 }
1448 // No point remaining in PAUSED state after a flush => go to
1449 // FLUSHED state
1450 mState = FLUSHED;
1451 // do not reset the track if it is still in the process of being stopped or paused.
1452 // this will be done by prepareTracks_l() when the track is stopped.
1453 // prepareTracks_l() will see mState == FLUSHED, then
1454 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001455 if (isDirect()) {
1456 mFlushHwPending = true;
1457 }
Andy Hung87c693c2023-07-06 20:56:16 -07001458 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001459 reset();
1460 }
Eric Laurent81784c32012-11-19 14:55:58 -08001461 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001462 // Prevent flush being lost if the track is flushed and then resumed
1463 // before mixer thread can run. This is important when offloading
1464 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001465 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001466 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1467 // new data
1468 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001469 }
1470}
1471
Haynes Mathew George7844f672014-01-15 12:32:55 -08001472// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001473void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001474{
Andy Hung920f6572022-10-06 12:09:49 -07001475 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001476 return;
Andy Hung920f6572022-10-06 12:09:49 -07001477 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001478
Phil Burk4bb650b2016-09-09 12:11:17 -07001479 // Clear the client ring buffer so that the app can prime the buffer while paused.
1480 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1481 mServerProxy->flushBufferIfNeeded();
1482
Haynes Mathew George7844f672014-01-15 12:32:55 -08001483 mFlushHwPending = false;
1484}
1485
Andy Hung8d31fd22023-06-26 19:20:57 -07001486void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001487{
1488 mPauseHwPending = false;
1489}
1490
Andy Hung8d31fd22023-06-26 19:20:57 -07001491void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001492{
1493 // Do not reset twice to avoid discarding data written just after a flush and before
1494 // the audioflinger thread detects the track is stopped.
1495 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001496 // Force underrun condition to avoid false underrun callback until first data is
1497 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001498 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001499 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001500 mResetDone = true;
1501 if (mState == FLUSHED) {
1502 mState = IDLE;
1503 }
1504 }
1505}
1506
Andy Hung8d31fd22023-06-26 19:20:57 -07001507status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001508{
Andy Hung87c693c2023-07-06 20:56:16 -07001509 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001510 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001511 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001512 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001513 } else if (thread->type() == IAfThreadBase::DIRECT
1514 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001515 return thread->setParameters(keyValuePairs);
1516 } else {
1517 return PERMISSION_DENIED;
1518 }
1519}
1520
Andy Hung8d31fd22023-06-26 19:20:57 -07001521status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001522 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001523 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001524 if (thread == 0) {
1525 ALOGE("thread is dead");
1526 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001527 } else if (thread->type() == IAfThreadBase::DIRECT
1528 || thread->type() == IAfThreadBase::OFFLOAD) {
1529 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001530 return directOutputThread->selectPresentation(presentationId, programId);
1531 }
1532 return INVALID_OPERATION;
1533}
1534
Andy Hung8d31fd22023-06-26 19:20:57 -07001535VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001536 const sp<VolumeShaper::Configuration>& configuration,
1537 const sp<VolumeShaper::Operation>& operation)
1538{
Andy Hung398ffa22022-12-13 19:19:53 -08001539 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001540
1541 if (isOffloadedOrDirect()) {
1542 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001543 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001544 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001545 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001546 thread->broadcast_l();
1547 }
1548 }
1549 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001550}
1551
Andy Hung8d31fd22023-06-26 19:20:57 -07001552sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001553{
1554 // Note: We don't check if Thread exists.
1555
1556 // mVolumeHandler is thread safe.
1557 return mVolumeHandler->getVolumeShaperState(id);
1558}
1559
Andy Hung8d31fd22023-06-26 19:20:57 -07001560void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001561{
jiabin76d94692022-12-15 21:51:21 +00001562 mFinalVolumeLeft = volumeLeft;
1563 mFinalVolumeRight = volumeRight;
1564 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001565 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1566 mFinalVolume = volume;
1567 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001568 mLogForceVolumeUpdate = true;
1569 }
1570 if (mLogForceVolumeUpdate) {
1571 mLogForceVolumeUpdate = false;
1572 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001573 }
1574}
1575
Andy Hung8d31fd22023-06-26 19:20:57 -07001576void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001577{
Eric Laurent49e39282022-06-24 18:42:45 +02001578 // Do not forward metadata for PatchTrack with unspecified stream type
1579 if (mStreamType == AUDIO_STREAM_PATCH) {
1580 return;
1581 }
1582
Eric Laurent94579172020-11-20 18:41:04 +01001583 playback_track_metadata_v7_t metadata;
1584 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001585 .usage = mAttr.usage,
1586 .content_type = mAttr.content_type,
1587 .gain = mFinalVolume,
1588 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001589
1590 // When attributes are undefined, derive default values from stream type.
1591 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1592 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1593 switch (mStreamType) {
1594 case AUDIO_STREAM_VOICE_CALL:
1595 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1596 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1597 break;
1598 case AUDIO_STREAM_SYSTEM:
1599 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1600 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1601 break;
1602 case AUDIO_STREAM_RING:
1603 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1604 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1605 break;
1606 case AUDIO_STREAM_MUSIC:
1607 metadata.base.usage = AUDIO_USAGE_MEDIA;
1608 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1609 break;
1610 case AUDIO_STREAM_ALARM:
1611 metadata.base.usage = AUDIO_USAGE_ALARM;
1612 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1613 break;
1614 case AUDIO_STREAM_NOTIFICATION:
1615 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1616 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1617 break;
1618 case AUDIO_STREAM_DTMF:
1619 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1620 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1621 break;
1622 case AUDIO_STREAM_ACCESSIBILITY:
1623 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1624 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1625 break;
1626 case AUDIO_STREAM_ASSISTANT:
1627 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1628 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1629 break;
1630 case AUDIO_STREAM_REROUTING:
1631 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1632 // unknown content type
1633 break;
1634 case AUDIO_STREAM_CALL_ASSISTANT:
1635 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1636 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1637 break;
1638 default:
1639 break;
1640 }
1641 }
1642
Eric Laurent78b07302022-10-07 16:20:34 +02001643 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001644 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1645 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001646}
1647
Andy Hung8d31fd22023-06-26 19:20:57 -07001648void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001649 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001650 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang73f97052023-12-12 20:08:03 +00001651 {
1652 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1653 mTeePatches = std::move(mTeePatchesToUpdate.value());
1654 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001655 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1656 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001657 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001658 }
1659 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001660 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001661}
1662
Andy Hung16ed0da2023-07-14 11:45:38 -07001663void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001664 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1665 "%s, existing tee patches to update will be ignored", __func__);
1666 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1667}
1668
Vlad Popae8d99472022-06-30 16:02:48 +02001669// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001670void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001671 IAudioManager>& audioManager, mute_state_t muteState)
1672{
1673 if (mMuteState == muteState) {
1674 // mute state did not change, do nothing
1675 return;
1676 }
1677
1678 status_t result = UNKNOWN_ERROR;
1679 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1680 if (mMuteEventExtras == nullptr) {
1681 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1682 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001683 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001684
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001685 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001686 }
1687
1688 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001689 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
Andy Hung0e26ec62024-02-20 16:32:57 -08001690 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001691 mMuteState = muteState;
1692 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001693 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1694 mPortId, result);
Vlad Popae8d99472022-06-30 16:02:48 +02001695 }
1696}
1697
Andy Hung8d31fd22023-06-26 19:20:57 -07001698status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001699{
Andy Hung818e7a32016-02-16 18:08:07 -08001700 if (!isOffloaded() && !isDirect()) {
1701 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001702 }
Andy Hung87c693c2023-07-06 20:56:16 -07001703 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001704 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001705 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001706 }
Phil Burk6140c792015-03-19 14:30:21 -07001707
Andy Hungc5007f82023-08-29 14:26:09 -07001708 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001709 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001710 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001711}
1712
Andy Hung8d31fd22023-06-26 19:20:57 -07001713status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001714{
Andy Hung87c693c2023-07-06 20:56:16 -07001715 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001716 if (thread == nullptr) {
1717 return DEAD_OBJECT;
1718 }
Eric Laurent81784c32012-11-19 14:55:58 -08001719
Andy Hung87c693c2023-07-06 20:56:16 -07001720 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001721 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001722 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001723 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001724 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001725
Eric Laurent6c796322019-04-09 14:13:17 -07001726 if (EffectId != 0 && status == NO_ERROR) {
1727 status = dstThread->attachAuxEffect(this, EffectId);
1728 if (status == NO_ERROR) {
1729 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001730 }
Eric Laurent6c796322019-04-09 14:13:17 -07001731 }
1732
1733 if (status != NO_ERROR && srcThread != nullptr) {
1734 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001735 }
1736 return status;
1737}
1738
Andy Hung8d31fd22023-06-26 19:20:57 -07001739void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001740{
1741 mAuxEffectId = EffectId;
1742 mAuxBuffer = buffer;
1743}
1744
Andy Hung59de4262021-06-14 10:53:54 -07001745// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001746bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001747 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001748{
Andy Hung818e7a32016-02-16 18:08:07 -08001749 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1750 // This assists in proper timestamp computation as well as wakelock management.
1751
Eric Laurent81784c32012-11-19 14:55:58 -08001752 // a track is considered presented when the total number of frames written to audio HAL
1753 // corresponds to the number of frames written when presentationComplete() is called for the
1754 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001755 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1756 // to detect when all frames have been played. In this case framesWritten isn't
1757 // useful because it doesn't always reflect whether there is data in the h/w
1758 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001759 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1760 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001761 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001762 if (mPresentationCompleteFrames == 0) {
1763 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001764 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001765 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1766 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001767 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001768 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001769
Andy Hungc54b1ff2016-02-23 14:07:07 -08001770 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001771 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001772 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001773 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1774 __func__, mId, (complete ? "complete" : "waiting"),
1775 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001776 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001777 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001778 && mAudioTrackServerProxy->isDrained();
1779 }
1780
1781 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001782 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001783 return true;
1784 }
1785 return false;
1786}
1787
Andy Hung59de4262021-06-14 10:53:54 -07001788// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001789bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001790{
1791 // For Offloaded or Direct tracks.
1792
1793 // For a direct track, we incorporated time based testing for presentationComplete.
1794
1795 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1796 // to detect when all frames have been played. In this case latencyMs isn't
1797 // useful because it doesn't always reflect whether there is data in the h/w
1798 // buffers, particularly if a track has been paused and resumed during draining
1799
1800 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1801 if (mPresentationCompleteTimeNs == 0) {
1802 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1803 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1804 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1805 }
1806
1807 bool complete;
1808 if (isOffloaded()) {
1809 complete = true;
1810 } else { // Direct
1811 complete = systemTime() >= mPresentationCompleteTimeNs;
1812 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1813 }
1814 if (complete) {
1815 notifyPresentationComplete();
1816 return true;
1817 }
1818 return false;
1819}
1820
Andy Hung8d31fd22023-06-26 19:20:57 -07001821void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001822{
1823 // This only triggers once. TODO: should we enforce this?
1824 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1825 mAudioTrackServerProxy->setStreamEndDone();
1826}
1827
Andy Hung8d31fd22023-06-26 19:20:57 -07001828void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001829{
Andy Hung068e08e2023-05-15 19:02:55 -07001830 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1831 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001832 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001833 (*it)->trigger();
1834 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001835 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001836 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001837 }
1838 }
1839}
1840
1841// implement VolumeBufferProvider interface
1842
Andy Hung8d31fd22023-06-26 19:20:57 -07001843gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001844{
1845 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1846 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001847 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1848 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1849 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001850 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001851 if (vl > GAIN_FLOAT_UNITY) {
1852 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001853 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001854 if (vr > GAIN_FLOAT_UNITY) {
1855 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001856 }
1857 // now apply the cached master volume and stream type volume;
1858 // this is trusted but lacks any synchronization or barrier so may be stale
1859 float v = mCachedVolume;
1860 vl *= v;
1861 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001862 // re-combine into packed minifloat
1863 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001864 // FIXME look at mute, pause, and stop flags
1865 return vlr;
1866}
1867
Andy Hung8d31fd22023-06-26 19:20:57 -07001868status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001869 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001870{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001871 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001872 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1873 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001874 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1875 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001876 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001877 event->cancel();
1878 return INVALID_OPERATION;
1879 }
1880 (void) TrackBase::setSyncEvent(event);
1881 return NO_ERROR;
1882}
1883
Andy Hung8d31fd22023-06-26 19:20:57 -07001884void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001885{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001886 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001887 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001888}
1889
Andy Hung8d31fd22023-06-26 19:20:57 -07001890void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001891{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001892 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001893 signalClientFlag(CBLK_DISABLED);
1894}
1895
Eric Laurent022a5132024-04-12 17:02:51 +00001896bool Track::isDisabled() const {
1897 audio_track_cblk_t* cblk = mCblk;
1898 return (cblk != nullptr)
1899 && ((android_atomic_release_load(&cblk->mFlags) & CBLK_DISABLED) != 0);
1900}
1901
Andy Hung8d31fd22023-06-26 19:20:57 -07001902void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001903{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001904 // FIXME should use proxy, and needs work
1905 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001906 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001907 android_atomic_release_store(0x40000000, &cblk->mFutex);
1908 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001909 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001910}
1911
Andy Hung8d31fd22023-06-26 19:20:57 -07001912void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001913{
Andy Hung87c693c2023-07-06 20:56:16 -07001914 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001915 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001916 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001917 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001918 t->broadcast_l();
1919 }
1920}
1921
Andy Hung8d31fd22023-06-26 19:20:57 -07001922status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001923{
1924 status_t status = INVALID_OPERATION;
1925 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001926 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001927 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001928 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001929 audio_utils::lock_guard _l(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001930 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001931 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1932 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1933 }
1934 }
1935 return status;
1936}
1937
Andy Hung8d31fd22023-06-26 19:20:57 -07001938status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001939{
1940 status_t status = INVALID_OPERATION;
1941 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001942 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001943 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001944 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001945 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001946 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001947 if (status == NO_ERROR) {
1948 mDualMonoMode = mode;
1949 }
1950 }
1951 }
1952 return status;
1953}
1954
Andy Hung8d31fd22023-06-26 19:20:57 -07001955status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001956{
1957 status_t status = INVALID_OPERATION;
1958 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001959 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001960 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001961 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001962 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001963 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001964 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1965 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1966 }
1967 }
1968 return status;
1969}
1970
Andy Hung8d31fd22023-06-26 19:20:57 -07001971status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001972{
1973 status_t status = INVALID_OPERATION;
1974 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001975 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001976 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001977 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001978 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001979 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001980 if (status == NO_ERROR) {
1981 mAudioDescriptionMixLevel = leveldB;
1982 }
1983 }
1984 }
1985 return status;
1986}
1987
Andy Hung8d31fd22023-06-26 19:20:57 -07001988status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001989 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001990{
1991 status_t status = INVALID_OPERATION;
1992 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001993 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001994 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001995 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001996 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001997 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001998 ALOGD_IF((status == NO_ERROR) &&
1999 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
2000 "%s: playbackRate inconsistent", __func__);
2001 }
2002 }
2003 return status;
2004}
2005
Andy Hung8d31fd22023-06-26 19:20:57 -07002006status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002007 const audio_playback_rate_t& playbackRate)
2008{
2009 status_t status = INVALID_OPERATION;
2010 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002011 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002012 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07002013 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07002014 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002015 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002016 if (status == NO_ERROR) {
2017 mPlaybackRateParameters = playbackRate;
2018 }
2019 }
2020 }
2021 return status;
2022}
2023
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002024//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002025bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07002026 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002027 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002028 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002029 /* Resume is pending if track was stopping before pause was called */
2030 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07002031 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002032 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002033 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002034
2035 return false;
2036}
2037
2038//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002039void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07002040 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002041 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07002042 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002043
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002044 // Other possibility of pending resume is stopping_1 state
2045 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002046 // drain being called.
2047 if (mState == STOPPING_1) {
2048 mResumeToStopping = false;
2049 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002050}
Andy Hunge10393e2015-06-12 13:59:33 -07002051
2052//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002053void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002054 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002055 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002056 // Make the kernel frametime available.
2057 const FrameTime ft{
2058 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2059 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2060 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2061 mKernelFrameTime.store(ft);
2062 if (!audio_is_linear_pcm(mFormat)) {
2063 return;
2064 }
2065
Andy Hung818e7a32016-02-16 18:08:07 -08002066 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002067 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002068
2069 // adjust server times and set drained state.
2070 //
2071 // Our timestamps are only updated when the track is on the Thread active list.
2072 // We need to ensure that tracks are not removed before full drain.
2073 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002074 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002075 bool checked = false;
2076 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2077 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2078 // Lookup the track frame corresponding to the sink frame position.
2079 if (local.mTimeNs[i] > 0) {
2080 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2081 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002082 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002083 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002084 checked = true;
2085 }
2086 }
Andy Hunge10393e2015-06-12 13:59:33 -07002087 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002088
Andy Hung93bb5732023-05-04 21:16:34 -07002089 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2090 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002091 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002092 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002093 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002094 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002095
2096 // Compute latency info.
2097 const bool useTrackTimestamp = !drained;
2098 const double latencyMs = useTrackTimestamp
2099 ? local.getOutputServerLatencyMs(sampleRate())
2100 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2101
2102 mServerLatencyFromTrack.store(useTrackTimestamp);
2103 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002104
Andy Hung62921122020-05-18 10:47:31 -07002105 if (mLogStartCountdown > 0
2106 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2107 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2108 {
2109 if (mLogStartCountdown > 1) {
2110 --mLogStartCountdown;
2111 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2112 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002113 // startup is the difference in times for the current timestamp and our start
2114 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002115 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002116 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002117 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2118 * 1e3 / mSampleRate;
2119 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2120 " localTime:%lld startTime:%lld"
2121 " localPosition:%lld startPosition:%lld",
2122 __func__, latencyMs, startUpMs,
2123 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002124 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002125 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002126 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002127 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002128 }
Andy Hung62921122020-05-18 10:47:31 -07002129 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002130 }
Andy Hunge10393e2015-06-12 13:59:33 -07002131}
2132
Andy Hung8d31fd22023-06-26 19:20:57 -07002133bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002134 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002135 if (thread != 0) {
2136 // Lock for updating mHapticPlaybackEnabled.
Andy Hungc5007f82023-08-29 14:26:09 -07002137 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002138 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002139 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002140 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002141 ALOGD("%s, haptic playback was %s for track %d",
2142 __func__, muted ? "muted" : "unmuted", mTrack->id());
2143 mTrack->setHapticPlaybackEnabled(!muted);
2144 return true;
jiabin57303cc2018-12-18 15:45:57 -08002145 }
2146 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002147 return false;
2148}
2149
Andy Hung8d31fd22023-06-26 19:20:57 -07002150binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002151 /*out*/ bool *ret) {
2152 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002153 return binder::Status::ok();
2154}
2155
Andy Hung8d31fd22023-06-26 19:20:57 -07002156binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002157 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002158 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002159 return binder::Status::ok();
2160}
2161
Eric Laurent81784c32012-11-19 14:55:58 -08002162// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002163#undef LOG_TAG
2164#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002165
Andy Hung8d31fd22023-06-26 19:20:57 -07002166/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002167sp<IAfOutputTrack> IAfOutputTrack::create(
2168 IAfPlaybackThread* playbackThread,
2169 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002170 uint32_t sampleRate,
2171 audio_format_t format,
2172 audio_channel_mask_t channelMask,
2173 size_t frameCount,
2174 const AttributionSourceState& attributionSource) {
2175 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002176 playbackThread,
2177 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002178 sampleRate,
2179 format,
2180 channelMask,
2181 frameCount,
2182 attributionSource);
2183}
2184
2185OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002186 IAfPlaybackThread* playbackThread,
2187 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002188 uint32_t sampleRate,
2189 audio_format_t format,
2190 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002191 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002192 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002193 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002194 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002195 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002196 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002197 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002198 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002199 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002200{
2201
2202 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002203 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002204 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002205 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002206 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002207 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002208 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002209 // since client and server are in the same process,
2210 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002211 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2212 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002213 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002214 mClientProxy->setSendLevel(0.0);
2215 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002216 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002217 ALOGW("%s(%d): Error creating output track on thread %d",
2218 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002219 }
2220}
2221
Andy Hung8d31fd22023-06-26 19:20:57 -07002222OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002223{
2224 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002225 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002226}
2227
Andy Hung8d31fd22023-06-26 19:20:57 -07002228status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002229 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002230{
2231 status_t status = Track::start(event, triggerSession);
2232 if (status != NO_ERROR) {
2233 return status;
2234 }
2235
2236 mActive = true;
2237 mRetryCount = 127;
2238 return status;
2239}
2240
Andy Hung8d31fd22023-06-26 19:20:57 -07002241void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002242{
2243 Track::stop();
2244 clearBufferQueue();
2245 mOutBuffer.frameCount = 0;
2246 mActive = false;
2247}
2248
Andy Hung8d31fd22023-06-26 19:20:57 -07002249ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002250{
Eric Laurent19952e12023-04-20 10:08:29 +02002251 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002252 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002253 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002254 // preload one silent buffer to trigger mixer on start()
2255 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2256 status_t status = mClientProxy->obtainBuffer(&buf);
2257 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2258 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2259 return 0;
2260 }
2261 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2262 mClientProxy->releaseBuffer(&buf);
2263
2264 (void) start();
2265
2266 // wait for HAL stream to start before sending actual audio. Doing this on each
2267 // OutputTrack makes that playback start on all output streams is synchronized.
2268 // If another OutputTrack has already started it can underrun but this is OK
2269 // as only silence has been played so far and the retry count is very high on
2270 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002271 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002272 if (!pt->waitForHalStart()) {
2273 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2274 stop();
2275 return 0;
2276 }
2277
2278 // enqueue the first buffer and exit so that other OutputTracks will also start before
2279 // write() is called again and this buffer actually consumed.
2280 Buffer firstBuffer;
2281 firstBuffer.frameCount = frames;
2282 firstBuffer.raw = data;
2283 queueBuffer(firstBuffer);
2284 return frames;
2285 } else {
2286 (void) start();
2287 }
2288 }
2289
Eric Laurent81784c32012-11-19 14:55:58 -08002290 Buffer *pInBuffer;
2291 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002292 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002293 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002294 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002295 while (waitTimeLeftMs) {
2296 // First write pending buffers, then new data
2297 if (mBufferQueue.size()) {
2298 pInBuffer = mBufferQueue.itemAt(0);
2299 } else {
2300 pInBuffer = &inBuffer;
2301 }
2302
2303 if (pInBuffer->frameCount == 0) {
2304 break;
2305 }
2306
2307 if (mOutBuffer.frameCount == 0) {
2308 mOutBuffer.frameCount = pInBuffer->frameCount;
2309 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002310 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002311 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002312 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2313 __func__, mId,
2314 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002315 break;
2316 }
2317 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2318 if (waitTimeLeftMs >= waitTimeMs) {
2319 waitTimeLeftMs -= waitTimeMs;
2320 } else {
2321 waitTimeLeftMs = 0;
2322 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002323 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002324 deferRestartIfDisabled();
Eric Laurent4d231dc2016-03-11 18:38:23 -08002325 continue;
2326 }
Eric Laurent81784c32012-11-19 14:55:58 -08002327 }
2328
2329 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2330 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002331 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002332 Proxy::Buffer buf;
2333 buf.mFrameCount = outFrames;
2334 buf.mRaw = NULL;
2335 mClientProxy->releaseBuffer(&buf);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002336 deferRestartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002337 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002338 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002339 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002340 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002341
2342 if (pInBuffer->frameCount == 0) {
2343 if (mBufferQueue.size()) {
2344 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002345 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002346 if (pInBuffer != &inBuffer) {
2347 delete pInBuffer;
2348 }
Andy Hung9d84af52018-09-12 18:03:44 -07002349 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2350 __func__, mId,
2351 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002352 } else {
2353 break;
2354 }
2355 }
2356 }
2357
2358 // If we could not write all frames, allocate a buffer and queue it for next time.
2359 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002360 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002361 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002362 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002363 }
2364 }
2365
Andy Hungc25b84a2015-01-14 19:04:10 -08002366 // Calling write() with a 0 length buffer means that no more data will be written:
2367 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2368 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2369 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002370 }
2371
Andy Hung1c86ebe2018-05-29 20:29:08 -07002372 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002373}
2374
Andy Hung8d31fd22023-06-26 19:20:57 -07002375void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002376
2377 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2378 Buffer *pInBuffer = new Buffer;
2379 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2380 pInBuffer->mBuffer = malloc(bufferSize);
2381 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2382 "%s: Unable to malloc size %zu", __func__, bufferSize);
2383 pInBuffer->frameCount = inBuffer.frameCount;
2384 pInBuffer->raw = pInBuffer->mBuffer;
2385 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2386 mBufferQueue.add(pInBuffer);
2387 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2388 (int)mThreadIoHandle, mBufferQueue.size());
2389 // audio data is consumed (stored locally); set frameCount to 0.
2390 inBuffer.frameCount = 0;
2391 } else {
2392 ALOGW("%s(%d): thread %d no more overflow buffers",
2393 __func__, mId, (int)mThreadIoHandle);
2394 // TODO: return error for this.
2395 }
2396}
2397
Andy Hung8d31fd22023-06-26 19:20:57 -07002398void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002399{
Andy Hungc5007f82023-08-29 14:26:09 -07002400 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002401 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2402}
2403
Andy Hung8d31fd22023-06-26 19:20:57 -07002404void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002405 {
Andy Hungc5007f82023-08-29 14:26:09 -07002406 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002407 mTrackMetadatas = metadatas;
2408 }
2409 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2410 setMetadataHasChanged();
2411}
2412
Andy Hung8d31fd22023-06-26 19:20:57 -07002413status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002414 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2415{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002416 ClientProxy::Buffer buf;
2417 buf.mFrameCount = buffer->frameCount;
2418 struct timespec timeout;
2419 timeout.tv_sec = waitTimeMs / 1000;
2420 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2421 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2422 buffer->frameCount = buf.mFrameCount;
2423 buffer->raw = buf.mRaw;
2424 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002425}
2426
Andy Hung8d31fd22023-06-26 19:20:57 -07002427void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002428{
2429 size_t size = mBufferQueue.size();
2430
2431 for (size_t i = 0; i < size; i++) {
2432 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002433 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002434 delete pBuffer;
2435 }
2436 mBufferQueue.clear();
2437}
2438
Andy Hung8d31fd22023-06-26 19:20:57 -07002439void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002440{
2441 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2442 if (mActive && (flags & CBLK_DISABLED)) {
2443 start();
2444 }
2445}
Eric Laurent81784c32012-11-19 14:55:58 -08002446
Andy Hung9d84af52018-09-12 18:03:44 -07002447// ----------------------------------------------------------------------------
2448#undef LOG_TAG
2449#define LOG_TAG "AF::PatchTrack"
2450
Andy Hung8d31fd22023-06-26 19:20:57 -07002451/* static */
2452sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002453 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002454 audio_stream_type_t streamType,
2455 uint32_t sampleRate,
2456 audio_channel_mask_t channelMask,
2457 audio_format_t format,
2458 size_t frameCount,
2459 void* buffer,
2460 size_t bufferSize,
2461 audio_output_flags_t flags,
2462 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002463 size_t frameCountToBeReady, /** Default behaviour is to start
Andy Hung8d31fd22023-06-26 19:20:57 -07002464 * as soon as possible to have
2465 * the lowest possible latency
guonaichao3acc9b12024-06-07 09:27:21 +08002466 * even if it might glitch. */
2467 float speed)
Andy Hung8d31fd22023-06-26 19:20:57 -07002468{
2469 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002470 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002471 streamType,
2472 sampleRate,
2473 channelMask,
2474 format,
2475 frameCount,
2476 buffer,
2477 bufferSize,
2478 flags,
2479 timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002480 frameCountToBeReady,
2481 speed);
Andy Hung8d31fd22023-06-26 19:20:57 -07002482}
2483
Andy Hung87c693c2023-07-06 20:56:16 -07002484PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002485 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002486 uint32_t sampleRate,
2487 audio_channel_mask_t channelMask,
2488 audio_format_t format,
2489 size_t frameCount,
2490 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002491 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002492 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002493 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002494 size_t frameCountToBeReady,
2495 float speed)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002496 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002497 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002498 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002499 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002500 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
guonaichao3acc9b12024-06-07 09:27:21 +08002501 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed),
2502 PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
2503 true /*clientInServer*/) : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002504 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002505{
guonaichao3acc9b12024-06-07 09:27:21 +08002506 if (mProxy != nullptr) {
2507 sp<AudioTrackClientProxy>::cast(mProxy)->setPlaybackRate({
2508 /* .mSpeed = */ speed,
2509 /* .mPitch = */ AUDIO_TIMESTRETCH_PITCH_NORMAL,
2510 /* .mStretchMode = */ AUDIO_TIMESTRETCH_STRETCH_DEFAULT,
2511 /* .mFallbackMode = */ AUDIO_TIMESTRETCH_FALLBACK_FAIL
2512 });
2513 }
Andy Hung9d84af52018-09-12 18:03:44 -07002514 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2515 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002516 (int)mPeerTimeout.tv_sec,
2517 (int)(mPeerTimeout.tv_nsec / 1000000));
2518}
2519
Andy Hung8d31fd22023-06-26 19:20:57 -07002520PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002521{
Andy Hungabfab202019-03-07 19:45:54 -08002522 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002523}
2524
Andy Hung8d31fd22023-06-26 19:20:57 -07002525size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002526{
2527 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2528 return std::numeric_limits<size_t>::max();
2529 } else {
2530 return Track::framesReady();
2531 }
2532}
2533
Andy Hung8d31fd22023-06-26 19:20:57 -07002534status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002535 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002536{
2537 status_t status = Track::start(event, triggerSession);
2538 if (status != NO_ERROR) {
2539 return status;
2540 }
2541 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2542 return status;
2543}
2544
Eric Laurent83b88082014-06-20 18:31:16 -07002545// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002546status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002547 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002548{
Andy Hung9d84af52018-09-12 18:03:44 -07002549 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002550 Proxy::Buffer buf;
2551 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002552 if (ATRACE_ENABLED()) {
2553 std::string traceName("PTnReq");
2554 traceName += std::to_string(id());
2555 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2556 }
Eric Laurent83b88082014-06-20 18:31:16 -07002557 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002558 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002559 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002560 if (ATRACE_ENABLED()) {
2561 std::string traceName("PTnObt");
2562 traceName += std::to_string(id());
2563 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2564 }
Eric Laurent83b88082014-06-20 18:31:16 -07002565 if (buf.mFrameCount == 0) {
2566 return WOULD_BLOCK;
2567 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002568 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002569 return status;
2570}
2571
Andy Hung8d31fd22023-06-26 19:20:57 -07002572void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002573{
Andy Hung9d84af52018-09-12 18:03:44 -07002574 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002575 Proxy::Buffer buf;
2576 buf.mFrameCount = buffer->frameCount;
2577 buf.mRaw = buffer->raw;
2578 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002579 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002580}
2581
Andy Hung8d31fd22023-06-26 19:20:57 -07002582status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002583 const struct timespec *timeOut)
2584{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002585 status_t status = NO_ERROR;
2586 static const int32_t kMaxTries = 5;
2587 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002588 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002589 do {
2590 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002591 deferRestartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002592 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002593 }
2594 status = mProxy->obtainBuffer(buffer, timeOut);
2595 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2596 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002597}
2598
Andy Hung8d31fd22023-06-26 19:20:57 -07002599void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002600{
2601 mProxy->releaseBuffer(buffer);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002602 deferRestartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002603
2604 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2605 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2606 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2607 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002608 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002609 && audio_is_linear_pcm(mFormat)
2610 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002611 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002612 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002613 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002614 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2615 / playbackThread->sampleRate();
2616 if (framesReady() < frameCount) {
2617 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002618 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002619 }
2620 }
2621 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002622}
2623
Andy Hung8d31fd22023-06-26 19:20:57 -07002624void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002625{
Eric Laurent83b88082014-06-20 18:31:16 -07002626 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002627 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002628 start();
2629 }
Eric Laurent83b88082014-06-20 18:31:16 -07002630}
2631
Eric Laurent81784c32012-11-19 14:55:58 -08002632// ----------------------------------------------------------------------------
2633// Record
2634// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002635
2636
Andy Hung9d84af52018-09-12 18:03:44 -07002637#undef LOG_TAG
2638#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002639
Andy Hunga5a7fc92023-06-23 19:27:19 -07002640class RecordHandle : public android::media::BnAudioRecord {
2641public:
Andy Hungd29af632023-06-23 19:27:19 -07002642 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002643 ~RecordHandle() override;
2644 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2645 int /*audio_session_t*/ triggerSession) final;
2646 binder::Status stop() final;
2647 binder::Status getActiveMicrophones(
2648 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2649 binder::Status setPreferredMicrophoneDirection(
2650 int /*audio_microphone_direction_t*/ direction) final;
2651 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2652 binder::Status shareAudioHistory(
2653 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2654
2655private:
Andy Hungd29af632023-06-23 19:27:19 -07002656 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002657
2658 // for use from destructor
2659 void stop_nonvirtual();
2660};
2661
2662/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002663sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2664 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002665 return sp<RecordHandle>::make(recordTrack);
2666}
2667
2668RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002669 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002670 : BnAudioRecord(),
2671 mRecordTrack(recordTrack)
2672{
Andy Hung225aef62022-12-06 16:33:20 -08002673 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hung58b01b12024-03-26 18:04:29 -07002674 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -08002675}
2676
Andy Hunga5a7fc92023-06-23 19:27:19 -07002677RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002678 stop_nonvirtual();
2679 mRecordTrack->destroy();
2680}
2681
Andy Hunga5a7fc92023-06-23 19:27:19 -07002682binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002683 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002684 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002685 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002686 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002687}
2688
Andy Hunga5a7fc92023-06-23 19:27:19 -07002689binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002690 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002691 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002692}
2693
Andy Hunga5a7fc92023-06-23 19:27:19 -07002694void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002695 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002696 mRecordTrack->stop();
2697}
2698
Andy Hunga5a7fc92023-06-23 19:27:19 -07002699binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002700 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002701 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002702 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002703}
2704
Andy Hunga5a7fc92023-06-23 19:27:19 -07002705binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002706 int /*audio_microphone_direction_t*/ direction) {
2707 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002708 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002709 static_cast<audio_microphone_direction_t>(direction)));
2710}
2711
Andy Hunga5a7fc92023-06-23 19:27:19 -07002712binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002713 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002714 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002715}
2716
Andy Hunga5a7fc92023-06-23 19:27:19 -07002717binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002718 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2719 return binderStatusFromStatusT(
2720 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2721}
2722
Eric Laurent81784c32012-11-19 14:55:58 -08002723// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002724#undef LOG_TAG
2725#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002726
Andy Hung8d31fd22023-06-26 19:20:57 -07002727
Andy Hung99b1ba62023-07-14 11:00:08 -07002728/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002729sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002730 const sp<Client>& client,
2731 const audio_attributes_t& attr,
2732 uint32_t sampleRate,
2733 audio_format_t format,
2734 audio_channel_mask_t channelMask,
2735 size_t frameCount,
2736 void* buffer,
2737 size_t bufferSize,
2738 audio_session_t sessionId,
2739 pid_t creatorPid,
2740 const AttributionSourceState& attributionSource,
2741 audio_input_flags_t flags,
2742 track_type type,
2743 audio_port_handle_t portId,
2744 int32_t startFrames)
2745{
2746 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002747 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002748 client,
2749 attr,
2750 sampleRate,
2751 format,
2752 channelMask,
2753 frameCount,
2754 buffer,
2755 bufferSize,
2756 sessionId,
2757 creatorPid,
2758 attributionSource,
2759 flags,
2760 type,
2761 portId,
2762 startFrames);
2763}
2764
Glenn Kasten05997e22014-03-13 15:08:33 -07002765// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002766RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002767 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002768 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002769 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002770 uint32_t sampleRate,
2771 audio_format_t format,
2772 audio_channel_mask_t channelMask,
2773 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002774 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002775 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002776 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002777 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002778 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002779 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002780 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002781 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002782 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002783 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002784 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002785 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002786 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002787 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002788 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002789 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002790 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002791 type, portId,
2792 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002793 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002794 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002795 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002796 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002797 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002798 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002799{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002800 if (mCblk == NULL) {
2801 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002802 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002803
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002804 if (!isDirect()) {
2805 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002806 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002807 channelMask, format, sampleRate);
2808 // Check if the RecordBufferConverter construction was successful.
2809 // If not, don't continue with construction.
2810 //
2811 // NOTE: It would be extremely rare that the record track cannot be created
2812 // for the current device, but a pending or future device change would make
2813 // the record track configuration valid.
2814 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002815 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002816 return;
2817 }
Andy Hung97a893e2015-03-29 01:03:07 -07002818 }
2819
Andy Hung6ae58432016-02-16 18:32:24 -08002820 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002821 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002822
Andy Hung97a893e2015-03-29 01:03:07 -07002823 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002824
Eric Laurent05067782016-06-01 18:27:28 -07002825 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002826 ALOG_ASSERT(thread->fastTrackAvailable());
2827 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002828 } else {
2829 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002830 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002831 }
Andy Hung8946a282018-04-19 20:04:56 -07002832#ifdef TEE_SINK
2833 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2834 + "_" + std::to_string(mId)
2835 + "_R");
2836#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002837
2838 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002839 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002840}
2841
Andy Hung8d31fd22023-06-26 19:20:57 -07002842RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002843{
Andy Hung9d84af52018-09-12 18:03:44 -07002844 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002845 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002846 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002847}
2848
Andy Hung8d31fd22023-06-26 19:20:57 -07002849status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002850{
2851 status_t status = TrackBase::initCheck();
2852 if (status == NO_ERROR && mServerProxy == 0) {
2853 status = BAD_VALUE;
2854 }
2855 return status;
2856}
2857
Eric Laurent81784c32012-11-19 14:55:58 -08002858// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002859status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002860{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002861 ServerProxy::Buffer buf;
2862 buf.mFrameCount = buffer->frameCount;
2863 status_t status = mServerProxy->obtainBuffer(&buf);
2864 buffer->frameCount = buf.mFrameCount;
2865 buffer->raw = buf.mRaw;
2866 if (buf.mFrameCount == 0) {
2867 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002868 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002869 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002870 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002871}
2872
Andy Hung8d31fd22023-06-26 19:20:57 -07002873status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002874 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002875{
Andy Hung87c693c2023-07-06 20:56:16 -07002876 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002877 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002878 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002879 return recordThread->start(this, event, triggerSession);
2880 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002881 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2882 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002883 }
2884}
2885
Andy Hung8d31fd22023-06-26 19:20:57 -07002886void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002887{
Andy Hung87c693c2023-07-06 20:56:16 -07002888 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002889 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002890 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002891 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002892 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002893 }
2894 }
2895}
2896
Andy Hung8d31fd22023-06-26 19:20:57 -07002897void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002898{
Andy Hung8d31fd22023-06-26 19:20:57 -07002899 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002900 sp<RecordTrack> keep(this);
2901 {
Andy Hungce685402018-10-05 17:23:27 -07002902 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002903 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002904 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07002905 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002906 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002907 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002908 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002909 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002910 }
Andy Hungce685402018-10-05 17:23:27 -07002911 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2912 }
2913 // APM portid/client management done outside of lock.
2914 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2915 if (isExternalTrack()) {
2916 switch (priorState) {
2917 case ACTIVE: // invalidated while still active
2918 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2919 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2920 AudioSystem::stopInput(mPortId);
2921 break;
2922
2923 case STARTING_1: // invalidated/start-aborted and startInput not successful
2924 case PAUSED: // OK, not active
2925 case IDLE: // OK, not active
2926 break;
2927
2928 case STOPPED: // unexpected (destroyed)
2929 default:
2930 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2931 }
2932 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002933 }
2934 }
2935}
2936
Andy Hung8d31fd22023-06-26 19:20:57 -07002937void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002938{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002939 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002940 // FIXME should use proxy, and needs work
2941 audio_track_cblk_t* cblk = mCblk;
2942 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2943 android_atomic_release_store(0x40000000, &cblk->mFutex);
2944 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002945 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002946}
2947
Eric Laurent81784c32012-11-19 14:55:58 -08002948
Andy Hung8d31fd22023-06-26 19:20:57 -07002949void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002950{
Eric Laurent973db022018-11-20 14:54:31 -08002951 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002952 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002953 " Server FrmCnt FrmRdy Sil%s\n",
2954 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002955}
2956
Andy Hung8d31fd22023-06-26 19:20:57 -07002957void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002958{
Eric Laurent973db022018-11-20 14:54:31 -08002959 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002960 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002961 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002962 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002963 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002964 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002965 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002966 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002967 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002968 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002969 mCblk->mFlags,
2970
Eric Laurent81784c32012-11-19 14:55:58 -08002971 mFormat,
2972 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002973 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002974 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002975
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002976 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002977 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002978 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002979 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002980 );
Andy Hung000adb52018-06-01 15:43:26 -07002981 if (isServerLatencySupported()) {
2982 double latencyMs;
2983 bool fromTrack;
2984 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2985 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2986 // or 'k' if estimated from kernel (usually for debugging).
2987 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2988 } else {
2989 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2990 }
2991 }
2992 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002993}
2994
Andy Hung93bb5732023-05-04 21:16:34 -07002995// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002996void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002997 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002998{
Andy Hung93bb5732023-05-04 21:16:34 -07002999 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07003000 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07003001 if (threadBase != 0) {
3002 // TODO: use actual buffer filling status instead of 2 buffers when info is available
3003 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07003004 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003005 }
Andy Hung93bb5732023-05-04 21:16:34 -07003006
3007 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003008}
3009
Andy Hung8d31fd22023-06-26 19:20:57 -07003010void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003011{
Andy Hung93bb5732023-05-04 21:16:34 -07003012 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003013}
3014
Andy Hung8d31fd22023-06-26 19:20:57 -07003015void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08003016 int64_t trackFramesReleased, int64_t sourceFramesRead,
3017 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
3018{
Andy Hung30282562018-08-08 18:27:03 -07003019 // Make the kernel frametime available.
3020 const FrameTime ft{
3021 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
3022 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
3023 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
3024 mKernelFrameTime.store(ft);
3025 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05003026 // Stream is direct, return provided timestamp with no conversion
3027 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07003028 return;
3029 }
3030
Andy Hung3f0c9022016-01-15 17:49:46 -08003031 ExtendedTimestamp local = timestamp;
3032
3033 // Convert HAL frames to server-side track frames at track sample rate.
3034 // We use trackFramesReleased and sourceFramesRead as an anchor point.
3035 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
3036 if (local.mTimeNs[i] != 0) {
3037 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
3038 const int64_t relativeTrackFrames = relativeServerFrames
3039 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3040 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3041 }
3042 }
Andy Hung6ae58432016-02-16 18:32:24 -08003043 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003044
3045 // Compute latency info.
3046 const bool useTrackTimestamp = true; // use track unless debugging.
3047 const double latencyMs = - (useTrackTimestamp
3048 ? local.getOutputServerLatencyMs(sampleRate())
3049 : timestamp.getOutputServerLatencyMs(halSampleRate));
3050
3051 mServerLatencyFromTrack.store(useTrackTimestamp);
3052 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003053}
Eric Laurent83b88082014-06-20 18:31:16 -07003054
Andy Hung8d31fd22023-06-26 19:20:57 -07003055status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07003056 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003057{
Andy Hung87c693c2023-07-06 20:56:16 -07003058 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003059 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003060 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003061 return recordThread->getActiveMicrophones(activeMicrophones);
3062 } else {
3063 return BAD_VALUE;
3064 }
3065}
3066
Andy Hung8d31fd22023-06-26 19:20:57 -07003067status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003068 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003069 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003070 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003071 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003072 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003073 } else {
3074 return BAD_VALUE;
3075 }
3076}
3077
Andy Hung8d31fd22023-06-26 19:20:57 -07003078status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003079 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003080 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003081 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003082 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003083 } else {
3084 return BAD_VALUE;
3085 }
3086}
3087
Andy Hung8d31fd22023-06-26 19:20:57 -07003088status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003089 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3090
3091 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3092 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3093 if (callingUid != mUid || callingPid != mCreatorPid) {
3094 return PERMISSION_DENIED;
3095 }
3096
Svet Ganov33761132021-05-13 22:51:08 +00003097 AttributionSourceState attributionSource{};
3098 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3099 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3100 attributionSource.token = sp<BBinder>::make();
3101 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003102 return PERMISSION_DENIED;
3103 }
3104
Andy Hung87c693c2023-07-06 20:56:16 -07003105 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003106 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003107 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003108 status_t status = recordThread->shareAudioHistory(
3109 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3110 if (status == NO_ERROR) {
3111 mSharedAudioPackageName = sharedAudioPackageName;
3112 }
3113 return status;
3114 } else {
3115 return BAD_VALUE;
3116 }
3117}
3118
Andy Hung8d31fd22023-06-26 19:20:57 -07003119void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003120{
3121
3122 // Do not forward PatchRecord metadata with unspecified audio source
3123 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3124 return;
3125 }
3126
3127 // No track is invalid as this is called after prepareTrack_l in the same critical section
3128 record_track_metadata_v7_t metadata;
3129 metadata.base = {
3130 .source = mAttr.source,
3131 .gain = 1, // capture tracks do not have volumes
3132 };
3133 metadata.channel_mask = mChannelMask;
3134 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3135
3136 *backInserter++ = metadata;
3137}
Eric Laurentec376dc2021-04-08 20:41:22 +02003138
Andy Hung9d84af52018-09-12 18:03:44 -07003139// ----------------------------------------------------------------------------
3140#undef LOG_TAG
3141#define LOG_TAG "AF::PatchRecord"
3142
Andy Hung8d31fd22023-06-26 19:20:57 -07003143/* static */
3144sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003145 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003146 uint32_t sampleRate,
3147 audio_channel_mask_t channelMask,
3148 audio_format_t format,
3149 size_t frameCount,
3150 void *buffer,
3151 size_t bufferSize,
3152 audio_input_flags_t flags,
3153 const Timeout& timeout,
3154 audio_source_t source)
3155{
3156 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003157 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003158 sampleRate,
3159 channelMask,
3160 format,
3161 frameCount,
3162 buffer,
3163 bufferSize,
3164 flags,
3165 timeout,
3166 source);
3167}
3168
Andy Hung87c693c2023-07-06 20:56:16 -07003169PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003170 uint32_t sampleRate,
3171 audio_channel_mask_t channelMask,
3172 audio_format_t format,
3173 size_t frameCount,
3174 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003175 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003176 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003177 const Timeout& timeout,
3178 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003179 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003180 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003181 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003182 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003183 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003184 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3185 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003186 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003187{
Andy Hung9d84af52018-09-12 18:03:44 -07003188 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3189 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003190 (int)mPeerTimeout.tv_sec,
3191 (int)(mPeerTimeout.tv_nsec / 1000000));
3192}
3193
Andy Hung8d31fd22023-06-26 19:20:57 -07003194PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003195{
Andy Hungabfab202019-03-07 19:45:54 -08003196 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003197}
3198
Mikhail Naganov8296c252019-09-25 14:59:54 -07003199static size_t writeFramesHelper(
3200 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3201{
3202 AudioBufferProvider::Buffer patchBuffer;
3203 patchBuffer.frameCount = frameCount;
3204 auto status = dest->getNextBuffer(&patchBuffer);
3205 if (status != NO_ERROR) {
3206 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3207 __func__, status, strerror(-status));
3208 return 0;
3209 }
3210 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3211 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3212 size_t framesWritten = patchBuffer.frameCount;
3213 dest->releaseBuffer(&patchBuffer);
3214 return framesWritten;
3215}
3216
3217// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003218size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003219 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3220{
3221 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3222 // On buffer wrap, the buffer frame count will be less than requested,
3223 // when this happens a second buffer needs to be used to write the leftover audio
3224 const size_t framesLeft = frameCount - framesWritten;
3225 if (framesWritten != 0 && framesLeft != 0) {
3226 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3227 framesLeft, frameSize);
3228 }
3229 return framesWritten;
3230}
3231
Eric Laurent83b88082014-06-20 18:31:16 -07003232// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003233status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003234 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003235{
Andy Hung9d84af52018-09-12 18:03:44 -07003236 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003237 Proxy::Buffer buf;
3238 buf.mFrameCount = buffer->frameCount;
3239 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3240 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003241 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003242 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003243 if (ATRACE_ENABLED()) {
3244 std::string traceName("PRnObt");
3245 traceName += std::to_string(id());
3246 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3247 }
Eric Laurent83b88082014-06-20 18:31:16 -07003248 if (buf.mFrameCount == 0) {
3249 return WOULD_BLOCK;
3250 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003251 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003252 return status;
3253}
3254
Andy Hung8d31fd22023-06-26 19:20:57 -07003255void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003256{
Andy Hung9d84af52018-09-12 18:03:44 -07003257 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003258 Proxy::Buffer buf;
3259 buf.mFrameCount = buffer->frameCount;
3260 buf.mRaw = buffer->raw;
3261 mPeerProxy->releaseBuffer(&buf);
3262 TrackBase::releaseBuffer(buffer);
3263}
3264
Andy Hung8d31fd22023-06-26 19:20:57 -07003265status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003266 const struct timespec *timeOut)
3267{
3268 return mProxy->obtainBuffer(buffer, timeOut);
3269}
3270
Andy Hung8d31fd22023-06-26 19:20:57 -07003271void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003272{
3273 mProxy->releaseBuffer(buffer);
3274}
3275
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003276#undef LOG_TAG
3277#define LOG_TAG "AF::PthrPatchRecord"
3278
3279static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3280{
3281 void *ptr = nullptr;
3282 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003283 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003284}
3285
Andy Hung8d31fd22023-06-26 19:20:57 -07003286/* static */
3287sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003288 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003289 uint32_t sampleRate,
3290 audio_channel_mask_t channelMask,
3291 audio_format_t format,
3292 size_t frameCount,
3293 audio_input_flags_t flags,
3294 audio_source_t source)
3295{
3296 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003297 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003298 sampleRate,
3299 channelMask,
3300 format,
3301 frameCount,
3302 flags,
3303 source);
3304}
3305
3306PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003307 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003308 uint32_t sampleRate,
3309 audio_channel_mask_t channelMask,
3310 audio_format_t format,
3311 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003312 audio_input_flags_t flags,
3313 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003314 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003315 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003316 mPatchRecordAudioBufferProvider(*this),
3317 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3318 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3319{
3320 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3321}
3322
Andy Hung8d31fd22023-06-26 19:20:57 -07003323sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003324 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003325{
3326 *thread = mThread.promote();
3327 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003328 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07003329 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07003330 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003331}
3332
3333// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003334status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003335 Proxy::Buffer* buffer, const struct timespec* timeOut)
3336{
3337 if (mUnconsumedFrames) {
3338 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3339 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3340 return PatchRecord::obtainBuffer(buffer, timeOut);
3341 }
3342
3343 // Otherwise, execute a read from HAL and write into the buffer.
3344 nsecs_t startTimeNs = 0;
3345 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3346 // Will need to correct timeOut by elapsed time.
3347 startTimeNs = systemTime();
3348 }
3349 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3350 buffer->mFrameCount = 0;
3351 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003352 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003353 sp<StreamInHalInterface> stream = obtainStream(&thread);
3354 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3355
3356 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003357 size_t bytesRead = 0;
3358 {
3359 ATRACE_NAME("read");
3360 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3361 if (result != NO_ERROR) goto stream_error;
3362 if (bytesRead == 0) return NO_ERROR;
3363 }
3364
3365 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003366 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003367 mReadBytes += bytesRead;
3368 mReadError = NO_ERROR;
3369 }
3370 mReadCV.notify_one();
3371 // writeFrames handles wraparound and should write all the provided frames.
3372 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3373 buffer->mFrameCount = writeFrames(
3374 &mPatchRecordAudioBufferProvider,
3375 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3376 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3377 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3378 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003379 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003380 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003381 // Correct the timeout by elapsed time.
3382 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003383 if (newTimeOutNs < 0) newTimeOutNs = 0;
3384 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3385 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003386 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003387 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003388 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003389
3390stream_error:
3391 stream->standby();
3392 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003393 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003394 mReadError = result;
3395 }
3396 mReadCV.notify_one();
3397 return result;
3398}
3399
Andy Hung8d31fd22023-06-26 19:20:57 -07003400void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003401{
3402 if (buffer->mFrameCount <= mUnconsumedFrames) {
3403 mUnconsumedFrames -= buffer->mFrameCount;
3404 } else {
3405 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3406 buffer->mFrameCount, mUnconsumedFrames);
3407 mUnconsumedFrames = 0;
3408 }
3409 PatchRecord::releaseBuffer(buffer);
3410}
3411
3412// AudioBufferProvider and Source methods are called on RecordThread
3413// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3414// and 'releaseBuffer' are stubbed out and ignore their input.
3415// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3416// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003417status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003418 void* buffer, size_t bytes, size_t* read)
3419{
3420 bytes = std::min(bytes, mFrameCount * mFrameSize);
3421 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003422 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003423 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3424 if (mReadError != NO_ERROR) {
3425 mLastReadFrames = 0;
3426 return mReadError;
3427 }
3428 *read = std::min(bytes, mReadBytes);
3429 mReadBytes -= *read;
3430 }
3431 mLastReadFrames = *read / mFrameSize;
3432 memset(buffer, 0, *read);
3433 return 0;
3434}
3435
Andy Hung8d31fd22023-06-26 19:20:57 -07003436status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003437 int64_t* frames, int64_t* time)
3438{
Andy Hung87c693c2023-07-06 20:56:16 -07003439 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003440 sp<StreamInHalInterface> stream = obtainStream(&thread);
3441 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3442}
3443
Andy Hung8d31fd22023-06-26 19:20:57 -07003444status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003445{
3446 // RecordThread issues 'standby' command in two major cases:
3447 // 1. Error on read--this case is handled in 'obtainBuffer'.
3448 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3449 // output, this can only happen when the software patch
3450 // is being torn down. In this case, the RecordThread
3451 // will terminate and close the HAL stream.
3452 return 0;
3453}
3454
3455// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003456status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003457 AudioBufferProvider::Buffer* buffer)
3458{
3459 buffer->frameCount = mLastReadFrames;
3460 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3461 return NO_ERROR;
3462}
3463
Andy Hung8d31fd22023-06-26 19:20:57 -07003464void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003465 AudioBufferProvider::Buffer* buffer)
3466{
3467 buffer->frameCount = 0;
3468 buffer->raw = nullptr;
3469}
3470
Andy Hung9d84af52018-09-12 18:03:44 -07003471// ----------------------------------------------------------------------------
3472#undef LOG_TAG
3473#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003474
Andy Hung8d31fd22023-06-26 19:20:57 -07003475/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003476sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003477 const audio_attributes_t& attr,
3478 uint32_t sampleRate,
3479 audio_format_t format,
3480 audio_channel_mask_t channelMask,
3481 audio_session_t sessionId,
3482 bool isOut,
3483 const android::content::AttributionSourceState& attributionSource,
3484 pid_t creatorPid,
3485 audio_port_handle_t portId)
3486{
3487 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003488 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003489 attr,
3490 sampleRate,
3491 format,
3492 channelMask,
3493 sessionId,
3494 isOut,
3495 attributionSource,
3496 creatorPid,
3497 portId);
3498}
3499
Andy Hung87c693c2023-07-06 20:56:16 -07003500MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003501 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003502 uint32_t sampleRate,
3503 audio_format_t format,
3504 audio_channel_mask_t channelMask,
3505 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003506 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003507 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003508 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003509 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003510 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003511 channelMask, (size_t)0 /* frameCount */,
3512 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003513 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003514 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003515 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003516 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003517 TYPE_DEFAULT, portId,
3518 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003519 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003520 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003521{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003522 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003523 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003524}
3525
Andy Hung8d31fd22023-06-26 19:20:57 -07003526MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003527{
3528}
3529
Andy Hung8d31fd22023-06-26 19:20:57 -07003530status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003531{
3532 return NO_ERROR;
3533}
3534
Andy Hung8d31fd22023-06-26 19:20:57 -07003535status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003536 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003537{
3538 return NO_ERROR;
3539}
3540
Andy Hung8d31fd22023-06-26 19:20:57 -07003541void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003542{
3543}
3544
3545// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003546status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003547{
3548 buffer->frameCount = 0;
3549 buffer->raw = nullptr;
3550 return INVALID_OPERATION;
3551}
3552
3553// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003554size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003555 return 0;
3556}
3557
Andy Hung8d31fd22023-06-26 19:20:57 -07003558int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003559{
3560 return 0;
3561}
3562
Andy Hung8d31fd22023-06-26 19:20:57 -07003563void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003564{
3565}
3566
Andy Hung8d31fd22023-06-26 19:20:57 -07003567void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003568{
3569 if (mMuteState == muteState) {
3570 // mute state did not change, do nothing
3571 return;
3572 }
3573
3574 status_t result = UNKNOWN_ERROR;
3575 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3576 if (mMuteEventExtras == nullptr) {
3577 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3578 }
3579 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3580 static_cast<int>(muteState));
3581
3582 result = audioManager->portEvent(mPortId,
3583 PLAYER_UPDATE_MUTED,
3584 mMuteEventExtras);
3585 }
3586
3587 if (result == OK) {
Andy Hung0e26ec62024-02-20 16:32:57 -08003588 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
3589 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popaec1788e2022-08-04 11:23:30 +02003590 mMuteState = muteState;
3591 } else {
3592 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3593 __func__,
3594 id(),
3595 mPortId,
3596 result);
3597 }
3598}
3599
Andy Hung8d31fd22023-06-26 19:20:57 -07003600void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003601{
Eric Laurent973db022018-11-20 14:54:31 -08003602 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003603 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003604}
3605
Andy Hung8d31fd22023-06-26 19:20:57 -07003606void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003607{
Eric Laurent973db022018-11-20 14:54:31 -08003608 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003609 mPid,
3610 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003611 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003612 mFormat,
3613 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003614 mSampleRate,
3615 mAttr.flags);
3616 if (isOut()) {
3617 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3618 } else {
3619 result.appendFormat("%6x", mAttr.source);
3620 }
3621 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003622}
3623
Glenn Kasten63238ef2015-03-02 15:50:29 -08003624} // namespace android