blob: ce6006c3d5f873945f62156fb4cba0b508997132 [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 Hungce240472023-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 Hungce240472023-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 Hung3ff4b552023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung44f27182023-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 Hung02a6c4e2023-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 Hung3ff4b552023-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 Hung3ff4b552023-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 Hung2ac52f12023-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 Hung3ff4b552023-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 Hung3ff4b552023-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 Hung3ff4b552023-06-26 19:20:57 -0700328PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung837229a2023-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 Hung837229a2023-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 Hung3ff4b552023-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 Hungaaa18282023-06-23 19:27:19 -0700354class TrackHandle : public android::media::BnAudioTrack {
355public:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700356 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hungaaa18282023-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 Hung02a6c4e2023-06-23 19:27:19 -0700390 const sp<IAfTrack> mTrack;
Andy Hungaaa18282023-06-23 19:27:19 -0700391};
392
393/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -0700394sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hungaaa18282023-06-23 19:27:19 -0700395 return sp<TrackHandle>::make(track);
396}
397
Andy Hung02a6c4e2023-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 Hungf2b4a182024-03-26 18:04:29 -0700403 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -0800404}
405
Andy Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-06-23 19:27:19 -0700512Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-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 Hungaaa18282023-06-23 19:27:19 -0700525Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-06-23 19:27:19 -0700549Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-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 Hungaaa18282023-06-23 19:27:19 -0700562Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-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 Hung3ff4b552023-06-26 19:20:57 -0700576sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung44f27182023-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 Popa103be862023-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 Popa103be862023-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 Hung44f27182023-07-06 20:56:16 -0700605OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
606 const AttributionSourceState& attributionSource,
607 audio_usage_t usage, int id, uid_t uid)
608 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa103be862023-07-10 20:27:41 -0700609 mHasOpPlayAudio(true),
Vlad Popa103be862023-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 Hung3ff4b552023-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 Hung3ff4b552023-06-26 19:20:57 -0700624void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700625{
Vlad Popad2152122023-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 Hung3ff4b552023-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 Popa103be862023-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 Popad2152122023-08-02 18:36:04 -0700654 if (doBroadcast) {
655 auto thread = mThread.promote();
Andy Hung71742ab2023-07-07 13:47:37 -0700656 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popad2152122023-08-02 18:36:04 -0700657 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87e82412023-08-29 14:26:09 -0700658 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad2152122023-08-02 18:36:04 -0700659 thread->broadcast_l();
660 }
Vlad Popa103be862023-07-10 20:27:41 -0700661 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800662 }
663}
664
Andy Hung3ff4b552023-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 Hung3ff4b552023-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 Popad2152122023-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 Hung3ff4b552023-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 Hung3ff4b552023-06-26 19:20:57 -0700694/* static */
Andy Hung44f27182023-07-06 20:56:16 -0700695sp<IAfTrack> IAfTrack::create(
696 IAfPlaybackThread* thread,
Andy Hung3ff4b552023-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 Hung44f27182023-07-06 20:56:16 -0700719 return sp<Track>::make(thread,
Andy Hung3ff4b552023-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 Hung3ff4b552023-06-26 19:20:57 -0700743Track::Track(
Andy Hung44f27182023-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 Hung3ff4b552023-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 Popa103be862023-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 Hung44f27182023-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 Hung44f27182023-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 Hung3ff4b552023-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 Hung3ff4b552023-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 Hung3ff4b552023-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 Hung44f27182023-07-06 20:56:16 -0700903 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800904 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -0800905 audio_utils::unique_lock ul(thread->mutex());
906 thread->waitWhileThreadBusy_l(ul);
907
Andy Hung44f27182023-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);
jiabin6e506fc2023-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 Hunga7187712023-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 Hung3ff4b552023-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 "
jiabin5eaf0962022-12-20 20:11:38 +0000927 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700928 "%s\n",
929 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800930}
931
Andy Hung3ff4b552023-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 Hung3ff4b552023-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 "
jiabin5eaf0962022-12-20 20:11:38 +00001013 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
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,
1043 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001044 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001045
1046 if (isServerLatencySupported()) {
1047 double latencyMs;
1048 bool fromTrack;
1049 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1050 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1051 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1052 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001053 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001054 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001055 }
1056 }
1057 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001058}
1059
Andy Hung3ff4b552023-06-26 19:20:57 -07001060uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001061 return mAudioTrackServerProxy->getSampleRate();
1062}
1063
Eric Laurent81784c32012-11-19 14:55:58 -08001064// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001065status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001066{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001067 ServerProxy::Buffer buf;
1068 size_t desiredFrames = buffer->frameCount;
1069 buf.mFrameCount = desiredFrames;
1070 status_t status = mServerProxy->obtainBuffer(&buf);
1071 buffer->frameCount = buf.mFrameCount;
1072 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001073 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001074 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001075 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001076 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001077 } else {
1078 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001079 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001080 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001081}
1082
Andy Hung3ff4b552023-06-26 19:20:57 -07001083void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001084{
1085 interceptBuffer(*buffer);
1086 TrackBase::releaseBuffer(buffer);
1087}
1088
1089// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001090void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001091 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001092 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001093 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001094 if (frameCount == 0) {
1095 return; // No audio to intercept.
1096 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1097 // does not allow 0 frame size request contrary to getNextBuffer
1098 }
Jiabin Huang98b8d452024-01-04 18:42:55 +00001099 TeePatches teePatches;
1100 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1101 // Cache a copy of tee patches in case it is updated while using.
1102 teePatches = mTeePatches;
1103 mTeePatchesRWLock.unlock();
1104 }
1105 for (auto& teePatch : teePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001106 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001107 const size_t framesWritten = patchRecord->writeFrames(
1108 sourceBuffer.i8, frameCount, mFrameSize);
1109 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001110 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001111 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001112 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001113 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001114 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1115 using namespace std::chrono_literals;
1116 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001117 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang98b8d452024-01-04 18:42:55 +00001118 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001119}
1120
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001121// ExtendedAudioBufferProvider interface
1122
Andy Hung27876c02014-09-09 18:07:55 -07001123// framesReady() may return an approximation of the number of frames if called
1124// from a different thread than the one calling Proxy->obtainBuffer() and
1125// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1126// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001127size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001128 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1129 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1130 // The remainder of the buffer is not drained.
1131 return 0;
1132 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001133 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001134}
1135
Andy Hung3ff4b552023-06-26 19:20:57 -07001136int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001137{
1138 return mAudioTrackServerProxy->framesReleased();
1139}
1140
Andy Hung3ff4b552023-06-26 19:20:57 -07001141void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001142{
1143 // This call comes from a FastTrack and should be kept lockless.
1144 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001145 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001146
Andy Hung818e7a32016-02-16 18:08:07 -08001147 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001148
1149 // Compute latency.
1150 // TODO: Consider whether the server latency may be passed in by FastMixer
1151 // as a constant for all active FastTracks.
1152 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1153 mServerLatencyFromTrack.store(true);
1154 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001155}
1156
Eric Laurent81784c32012-11-19 14:55:58 -08001157// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001158bool Track::isReady() const {
1159 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001160 return true;
1161 }
1162
Eric Laurent16498512014-03-17 17:22:08 -07001163 if (isStopping()) {
1164 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001165 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001166 }
Eric Laurent81784c32012-11-19 14:55:58 -08001167 return true;
1168 }
1169
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001170 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001171 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1172 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1173 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1174 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001175
1176 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1177 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1178 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001179 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001180 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001181 return true;
1182 }
1183 return false;
1184}
1185
Andy Hung3ff4b552023-06-26 19:20:57 -07001186status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001187 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001188{
1189 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001190 ALOGV("%s(%d): calling pid %d session %d",
1191 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001192
Andy Hung44f27182023-07-06 20:56:16 -07001193 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001194 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001195 if (isOffloaded()) {
Andy Hung2ac52f12023-08-28 18:36:53 -07001196 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hung94dfbb42023-09-06 19:41:47 -07001197 const bool nonOffloadableGlobalEffectEnabled =
1198 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hung87e82412023-08-29 14:26:09 -07001199 audio_utils::lock_guard _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001200 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung94dfbb42023-09-06 19:41:47 -07001201 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001202 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001203 invalidate();
1204 return PERMISSION_DENIED;
1205 }
1206 }
Andy Hunga7187712023-12-05 17:28:17 -08001207 audio_utils::unique_lock ul(thread->mutex());
1208 thread->waitWhileThreadBusy_l(ul);
1209
Eric Laurent81784c32012-11-19 14:55:58 -08001210 track_state state = mState;
1211 // here the track could be either new, or restarted
1212 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001213
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001214 // initial state-stopping. next state-pausing.
1215 // What if resume is called ?
1216
Zhou Song1ed46a22020-08-17 15:36:56 +08001217 if (state == FLUSHED) {
1218 // avoid underrun glitches when starting after flush
1219 reset();
1220 }
1221
kuowei.li576f1362021-05-11 18:02:32 +08001222 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1223 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001224 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001225 if (mResumeToStopping) {
1226 // happened we need to resume to STOPPING_1
1227 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001228 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1229 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001230 } else {
1231 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001232 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1233 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001234 }
Eric Laurent81784c32012-11-19 14:55:58 -08001235 } else {
1236 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001237 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1238 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001239 }
1240
Andy Hung44f27182023-07-06 20:56:16 -07001241 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001242
1243 // states to reset position info for pcm tracks
1244 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001245 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1246 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001247
1248 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1249 // Start point of track -> sink frame map. If the HAL returns a
1250 // frame position smaller than the first written frame in
1251 // updateTrackFrameInfo, the timestamp can be interpolated
1252 // instead of using a larger value.
1253 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1254 playbackThread->framesWritten());
1255 }
Andy Hunge10393e2015-06-12 13:59:33 -07001256 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001257 if (isFastTrack()) {
1258 // refresh fast track underruns on start because that field is never cleared
1259 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1260 // after stop.
1261 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1262 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001263 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001264 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001265 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001266 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001267 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001268 mState = state;
1269 }
1270 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001271
Andy Hungb68f5eb2019-12-03 16:49:17 -08001272 // Audio timing metrics are computed a few mix cycles after starting.
1273 {
1274 mLogStartCountdown = LOG_START_COUNTDOWN;
1275 mLogStartTimeNs = systemTime();
1276 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001277 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1278 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001279 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001280 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001281
Andy Hung1d3556d2018-03-29 16:30:14 -07001282 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1283 // for streaming tracks, remove the buffer read stop limit.
1284 mAudioTrackServerProxy->start();
1285 }
1286
Eric Laurentbfb1b832013-01-07 09:53:42 -08001287 // track was already in the active list, not a problem
1288 if (status == ALREADY_EXISTS) {
1289 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001290 } else {
1291 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1292 // It is usually unsafe to access the server proxy from a binder thread.
1293 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1294 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1295 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001296 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001297 ServerProxy::Buffer buffer;
1298 buffer.mFrameCount = 1;
1299 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001300 }
jiabin6e506fc2023-06-27 18:22:35 +00001301 if (status == NO_ERROR) {
1302 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1303 }
Eric Laurent81784c32012-11-19 14:55:58 -08001304 } else {
1305 status = BAD_VALUE;
1306 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001307 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001308 // send format to AudioManager for playback activity monitoring
Andy Hung2cbc2722023-07-17 17:05:00 -07001309 const sp<IAudioManager> audioManager =
1310 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001311 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1312 std::unique_ptr<os::PersistableBundle> bundle =
1313 std::make_unique<os::PersistableBundle>();
1314 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1315 isSpatialized());
1316 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1317 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1318 status_t result = audioManager->portEvent(mPortId,
1319 PLAYER_UPDATE_FORMAT, bundle);
1320 if (result != OK) {
1321 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1322 __func__, mPortId, result);
1323 }
1324 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001325 }
Eric Laurent81784c32012-11-19 14:55:58 -08001326 return status;
1327}
1328
Andy Hung3ff4b552023-06-26 19:20:57 -07001329void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001330{
Andy Hungc0691382018-09-12 18:01:57 -07001331 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001332 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001333 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -08001334 audio_utils::unique_lock ul(thread->mutex());
1335 thread->waitWhileThreadBusy_l(ul);
1336
Eric Laurent81784c32012-11-19 14:55:58 -08001337 track_state state = mState;
1338 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1339 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001340 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1341 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001342 reset();
1343 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001344 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1345 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1346 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001347 mState = STOPPED;
1348 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001349 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1350 // presentation is complete
1351 // For an offloaded track this starts a drain and state will
1352 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001353 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001354 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001355 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001356 }
Eric Laurent81784c32012-11-19 14:55:58 -08001357 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001358 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001359 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1360 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001361 }
jiabin6e506fc2023-06-27 18:22:35 +00001362 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001363 }
1364}
1365
Andy Hung3ff4b552023-06-26 19:20:57 -07001366void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001367{
Andy Hungc0691382018-09-12 18:01:57 -07001368 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001369 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001370 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -08001371 audio_utils::unique_lock ul(thread->mutex());
1372 thread->waitWhileThreadBusy_l(ul);
1373
Andy Hung44f27182023-07-06 20:56:16 -07001374 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001375 switch (mState) {
1376 case STOPPING_1:
1377 case STOPPING_2:
1378 if (!isOffloaded()) {
1379 /* nothing to do if track is not offloaded */
1380 break;
1381 }
1382
1383 // Offloaded track was draining, we need to carry on draining when resumed
1384 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001385 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001386 case ACTIVE:
1387 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001388 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001389 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1390 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001391 if (isOffloadedOrDirect()) {
1392 mPauseHwPending = true;
1393 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001394 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001395 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001396
Eric Laurentbfb1b832013-01-07 09:53:42 -08001397 default:
1398 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001399 }
jiabin6e506fc2023-06-27 18:22:35 +00001400 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1401 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001402 }
1403}
1404
Andy Hung3ff4b552023-06-26 19:20:57 -07001405void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001406{
Andy Hungc0691382018-09-12 18:01:57 -07001407 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001408 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001409 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -08001410 audio_utils::unique_lock ul(thread->mutex());
1411 thread->waitWhileThreadBusy_l(ul);
1412
Andy Hung44f27182023-07-06 20:56:16 -07001413 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001414
Phil Burk4bb650b2016-09-09 12:11:17 -07001415 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1416 // Otherwise the flush would not be done until the track is resumed.
1417 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001418 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001419 (void)mServerProxy->flushBufferIfNeeded();
1420 }
1421
Eric Laurentbfb1b832013-01-07 09:53:42 -08001422 if (isOffloaded()) {
1423 // If offloaded we allow flush during any state except terminated
1424 // and keep the track active to avoid problems if user is seeking
1425 // rapidly and underlying hardware has a significant delay handling
1426 // a pause
1427 if (isTerminated()) {
1428 return;
1429 }
1430
Andy Hung9d84af52018-09-12 18:03:44 -07001431 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001432 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001433
1434 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001435 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1436 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001437 mState = ACTIVE;
1438 }
1439
Haynes Mathew George7844f672014-01-15 12:32:55 -08001440 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001441 mResumeToStopping = false;
1442 } else {
1443 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1444 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1445 return;
1446 }
1447 // No point remaining in PAUSED state after a flush => go to
1448 // FLUSHED state
1449 mState = FLUSHED;
1450 // do not reset the track if it is still in the process of being stopped or paused.
1451 // this will be done by prepareTracks_l() when the track is stopped.
1452 // prepareTracks_l() will see mState == FLUSHED, then
1453 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001454 if (isDirect()) {
1455 mFlushHwPending = true;
1456 }
Andy Hung44f27182023-07-06 20:56:16 -07001457 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001458 reset();
1459 }
Eric Laurent81784c32012-11-19 14:55:58 -08001460 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001461 // Prevent flush being lost if the track is flushed and then resumed
1462 // before mixer thread can run. This is important when offloading
1463 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001464 playbackThread->broadcast_l();
jiabin6e506fc2023-06-27 18:22:35 +00001465 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1466 // new data
1467 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001468 }
1469}
1470
Haynes Mathew George7844f672014-01-15 12:32:55 -08001471// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001472void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001473{
Andy Hung71ba4b32022-10-06 12:09:49 -07001474 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001475 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001476 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001477
Phil Burk4bb650b2016-09-09 12:11:17 -07001478 // Clear the client ring buffer so that the app can prime the buffer while paused.
1479 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1480 mServerProxy->flushBufferIfNeeded();
1481
Haynes Mathew George7844f672014-01-15 12:32:55 -08001482 mFlushHwPending = false;
1483}
1484
Andy Hung3ff4b552023-06-26 19:20:57 -07001485void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001486{
1487 mPauseHwPending = false;
1488}
1489
Andy Hung3ff4b552023-06-26 19:20:57 -07001490void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001491{
1492 // Do not reset twice to avoid discarding data written just after a flush and before
1493 // the audioflinger thread detects the track is stopped.
1494 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001495 // Force underrun condition to avoid false underrun callback until first data is
1496 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001497 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001498 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001499 mResetDone = true;
1500 if (mState == FLUSHED) {
1501 mState = IDLE;
1502 }
1503 }
1504}
1505
Andy Hung3ff4b552023-06-26 19:20:57 -07001506status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001507{
Andy Hung44f27182023-07-06 20:56:16 -07001508 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001509 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001510 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001511 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001512 } else if (thread->type() == IAfThreadBase::DIRECT
1513 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001514 return thread->setParameters(keyValuePairs);
1515 } else {
1516 return PERMISSION_DENIED;
1517 }
1518}
1519
Andy Hung3ff4b552023-06-26 19:20:57 -07001520status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001521 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001522 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001523 if (thread == 0) {
1524 ALOGE("thread is dead");
1525 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001526 } else if (thread->type() == IAfThreadBase::DIRECT
1527 || thread->type() == IAfThreadBase::OFFLOAD) {
1528 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001529 return directOutputThread->selectPresentation(presentationId, programId);
1530 }
1531 return INVALID_OPERATION;
1532}
1533
Andy Hung3ff4b552023-06-26 19:20:57 -07001534VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001535 const sp<VolumeShaper::Configuration>& configuration,
1536 const sp<VolumeShaper::Operation>& operation)
1537{
Andy Hungee86cee2022-12-13 19:19:53 -08001538 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001539
1540 if (isOffloadedOrDirect()) {
1541 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001542 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001543 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001544 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001545 thread->broadcast_l();
1546 }
1547 }
1548 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001549}
1550
Andy Hung3ff4b552023-06-26 19:20:57 -07001551sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001552{
1553 // Note: We don't check if Thread exists.
1554
1555 // mVolumeHandler is thread safe.
1556 return mVolumeHandler->getVolumeShaperState(id);
1557}
1558
Andy Hung3ff4b552023-06-26 19:20:57 -07001559void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001560{
jiabin76d94692022-12-15 21:51:21 +00001561 mFinalVolumeLeft = volumeLeft;
1562 mFinalVolumeRight = volumeRight;
1563 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001564 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1565 mFinalVolume = volume;
1566 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001567 mLogForceVolumeUpdate = true;
1568 }
1569 if (mLogForceVolumeUpdate) {
1570 mLogForceVolumeUpdate = false;
1571 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001572 }
1573}
1574
Andy Hung3ff4b552023-06-26 19:20:57 -07001575void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001576{
Eric Laurent49e39282022-06-24 18:42:45 +02001577 // Do not forward metadata for PatchTrack with unspecified stream type
1578 if (mStreamType == AUDIO_STREAM_PATCH) {
1579 return;
1580 }
1581
Eric Laurent94579172020-11-20 18:41:04 +01001582 playback_track_metadata_v7_t metadata;
1583 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001584 .usage = mAttr.usage,
1585 .content_type = mAttr.content_type,
1586 .gain = mFinalVolume,
1587 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001588
1589 // When attributes are undefined, derive default values from stream type.
1590 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1591 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1592 switch (mStreamType) {
1593 case AUDIO_STREAM_VOICE_CALL:
1594 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1595 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1596 break;
1597 case AUDIO_STREAM_SYSTEM:
1598 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1599 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1600 break;
1601 case AUDIO_STREAM_RING:
1602 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1603 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1604 break;
1605 case AUDIO_STREAM_MUSIC:
1606 metadata.base.usage = AUDIO_USAGE_MEDIA;
1607 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1608 break;
1609 case AUDIO_STREAM_ALARM:
1610 metadata.base.usage = AUDIO_USAGE_ALARM;
1611 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1612 break;
1613 case AUDIO_STREAM_NOTIFICATION:
1614 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1615 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1616 break;
1617 case AUDIO_STREAM_DTMF:
1618 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1619 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1620 break;
1621 case AUDIO_STREAM_ACCESSIBILITY:
1622 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1623 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1624 break;
1625 case AUDIO_STREAM_ASSISTANT:
1626 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1627 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1628 break;
1629 case AUDIO_STREAM_REROUTING:
1630 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1631 // unknown content type
1632 break;
1633 case AUDIO_STREAM_CALL_ASSISTANT:
1634 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1635 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1636 break;
1637 default:
1638 break;
1639 }
1640 }
1641
Eric Laurent78b07302022-10-07 16:20:34 +02001642 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001643 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1644 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001645}
1646
jiabin6e506fc2023-06-27 18:22:35 +00001647void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001648 if (mTeePatchesToUpdate.has_value()) {
jiabin6e506fc2023-06-27 18:22:35 +00001649 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang98b8d452024-01-04 18:42:55 +00001650 {
1651 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1652 mTeePatches = std::move(mTeePatchesToUpdate.value());
1653 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001654 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1655 mState == TrackBase::STOPPING_1) {
jiabin6e506fc2023-06-27 18:22:35 +00001656 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001657 }
1658 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001659 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001660}
1661
jiabin6e506fc2023-06-27 18:22:35 +00001662void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001663 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1664 "%s, existing tee patches to update will be ignored", __func__);
1665 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1666}
1667
Vlad Popae8d99472022-06-30 16:02:48 +02001668// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001669void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001670 IAudioManager>& audioManager, mute_state_t muteState)
1671{
1672 if (mMuteState == muteState) {
1673 // mute state did not change, do nothing
1674 return;
1675 }
1676
1677 status_t result = UNKNOWN_ERROR;
1678 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1679 if (mMuteEventExtras == nullptr) {
1680 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1681 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001682 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001683
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001684 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001685 }
1686
1687 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001688 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
Andy Hung6fb26892024-02-20 16:32:57 -08001689 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001690 mMuteState = muteState;
1691 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001692 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1693 mPortId, result);
Andy Hung818e7a32016-02-16 18:08:07 -08001694 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001695}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001696
Andy Hung3ff4b552023-06-26 19:20:57 -07001697status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001698{
1699 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001700 return INVALID_OPERATION; // normal tracks handled through SSQ
1701 }
Andy Hung44f27182023-07-06 20:56:16 -07001702 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001703 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001704 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001705 }
Phil Burk6140c792015-03-19 14:30:21 -07001706
Andy Hung87e82412023-08-29 14:26:09 -07001707 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001708 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001709 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001710}
1711
Andy Hung3ff4b552023-06-26 19:20:57 -07001712status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001713{
Andy Hung44f27182023-07-06 20:56:16 -07001714 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001715 if (thread == nullptr) {
1716 return DEAD_OBJECT;
1717 }
Eric Laurent81784c32012-11-19 14:55:58 -08001718
Andy Hung44f27182023-07-06 20:56:16 -07001719 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001720 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001721 sp<IAfPlaybackThread> srcThread;
Andy Hungfa2f4f32023-07-17 12:40:43 -07001722 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001723 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001724
Eric Laurent6c796322019-04-09 14:13:17 -07001725 if (EffectId != 0 && status == NO_ERROR) {
1726 status = dstThread->attachAuxEffect(this, EffectId);
1727 if (status == NO_ERROR) {
1728 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001729 }
Eric Laurent6c796322019-04-09 14:13:17 -07001730 }
1731
1732 if (status != NO_ERROR && srcThread != nullptr) {
1733 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001734 }
1735 return status;
1736}
1737
Andy Hung3ff4b552023-06-26 19:20:57 -07001738void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001739{
1740 mAuxEffectId = EffectId;
1741 mAuxBuffer = buffer;
1742}
1743
Andy Hung59de4262021-06-14 10:53:54 -07001744// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001745bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001746 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001747{
Andy Hung818e7a32016-02-16 18:08:07 -08001748 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1749 // This assists in proper timestamp computation as well as wakelock management.
1750
Eric Laurent81784c32012-11-19 14:55:58 -08001751 // a track is considered presented when the total number of frames written to audio HAL
1752 // corresponds to the number of frames written when presentationComplete() is called for the
1753 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001754 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1755 // to detect when all frames have been played. In this case framesWritten isn't
1756 // useful because it doesn't always reflect whether there is data in the h/w
1757 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001758 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1759 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001760 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001761 if (mPresentationCompleteFrames == 0) {
1762 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001763 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001764 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1765 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001766 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001767 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001768
Andy Hungc54b1ff2016-02-23 14:07:07 -08001769 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001770 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001771 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001772 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1773 __func__, mId, (complete ? "complete" : "waiting"),
1774 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001775 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001776 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001777 && mAudioTrackServerProxy->isDrained();
1778 }
1779
1780 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001781 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001782 return true;
1783 }
1784 return false;
1785}
1786
Andy Hung59de4262021-06-14 10:53:54 -07001787// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001788bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001789{
1790 // For Offloaded or Direct tracks.
1791
1792 // For a direct track, we incorporated time based testing for presentationComplete.
1793
1794 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1795 // to detect when all frames have been played. In this case latencyMs isn't
1796 // useful because it doesn't always reflect whether there is data in the h/w
1797 // buffers, particularly if a track has been paused and resumed during draining
1798
1799 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1800 if (mPresentationCompleteTimeNs == 0) {
1801 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1802 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1803 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1804 }
1805
1806 bool complete;
1807 if (isOffloaded()) {
1808 complete = true;
1809 } else { // Direct
1810 complete = systemTime() >= mPresentationCompleteTimeNs;
1811 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1812 }
1813 if (complete) {
1814 notifyPresentationComplete();
1815 return true;
1816 }
1817 return false;
1818}
1819
Andy Hung3ff4b552023-06-26 19:20:57 -07001820void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001821{
1822 // This only triggers once. TODO: should we enforce this?
1823 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1824 mAudioTrackServerProxy->setStreamEndDone();
1825}
1826
Andy Hung3ff4b552023-06-26 19:20:57 -07001827void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001828{
Andy Hung068e08e2023-05-15 19:02:55 -07001829 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1830 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001831 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001832 (*it)->trigger();
1833 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001834 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001835 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001836 }
1837 }
1838}
1839
1840// implement VolumeBufferProvider interface
1841
Andy Hung3ff4b552023-06-26 19:20:57 -07001842gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001843{
1844 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1845 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001846 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1847 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1848 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001849 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001850 if (vl > GAIN_FLOAT_UNITY) {
1851 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001852 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001853 if (vr > GAIN_FLOAT_UNITY) {
1854 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001855 }
1856 // now apply the cached master volume and stream type volume;
1857 // this is trusted but lacks any synchronization or barrier so may be stale
1858 float v = mCachedVolume;
1859 vl *= v;
1860 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001861 // re-combine into packed minifloat
1862 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001863 // FIXME look at mute, pause, and stop flags
1864 return vlr;
1865}
1866
Andy Hung3ff4b552023-06-26 19:20:57 -07001867status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001868 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001869{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001870 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001871 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1872 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001873 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1874 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001875 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001876 event->cancel();
1877 return INVALID_OPERATION;
1878 }
1879 (void) TrackBase::setSyncEvent(event);
1880 return NO_ERROR;
1881}
1882
Andy Hung3ff4b552023-06-26 19:20:57 -07001883void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001884{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001885 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001886 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001887}
1888
Andy Hung3ff4b552023-06-26 19:20:57 -07001889void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001890{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001891 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001892 signalClientFlag(CBLK_DISABLED);
1893}
1894
Andy Hung3ff4b552023-06-26 19:20:57 -07001895void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001896{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001897 // FIXME should use proxy, and needs work
1898 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001899 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001900 android_atomic_release_store(0x40000000, &cblk->mFutex);
1901 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001902 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001903}
1904
Andy Hung3ff4b552023-06-26 19:20:57 -07001905void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001906{
Andy Hung44f27182023-07-06 20:56:16 -07001907 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001908 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001909 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001910 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001911 t->broadcast_l();
1912 }
1913}
1914
Andy Hung3ff4b552023-06-26 19:20:57 -07001915status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001916{
1917 status_t status = INVALID_OPERATION;
1918 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001919 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001920 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001921 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001922 audio_utils::lock_guard _l(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001923 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001924 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1925 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1926 }
1927 }
1928 return status;
1929}
1930
Andy Hung3ff4b552023-06-26 19:20:57 -07001931status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932{
1933 status_t status = INVALID_OPERATION;
1934 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001935 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001936 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001937 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001938 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001939 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001940 if (status == NO_ERROR) {
1941 mDualMonoMode = mode;
1942 }
1943 }
1944 }
1945 return status;
1946}
1947
Andy Hung3ff4b552023-06-26 19:20:57 -07001948status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001949{
1950 status_t status = INVALID_OPERATION;
1951 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001952 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001953 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001954 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001955 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001956 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001957 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1958 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1959 }
1960 }
1961 return status;
1962}
1963
Andy Hung3ff4b552023-06-26 19:20:57 -07001964status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001965{
1966 status_t status = INVALID_OPERATION;
1967 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001968 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001969 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001970 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001971 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001972 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001973 if (status == NO_ERROR) {
1974 mAudioDescriptionMixLevel = leveldB;
1975 }
1976 }
1977 }
1978 return status;
1979}
1980
Andy Hung3ff4b552023-06-26 19:20:57 -07001981status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001982 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001983{
1984 status_t status = INVALID_OPERATION;
1985 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001986 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001987 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001988 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001989 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001990 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001991 ALOGD_IF((status == NO_ERROR) &&
1992 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1993 "%s: playbackRate inconsistent", __func__);
1994 }
1995 }
1996 return status;
1997}
1998
Andy Hung3ff4b552023-06-26 19:20:57 -07001999status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002000 const audio_playback_rate_t& playbackRate)
2001{
2002 status_t status = INVALID_OPERATION;
2003 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002004 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002005 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07002006 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07002007 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002008 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08002009 if (status == NO_ERROR) {
2010 mPlaybackRateParameters = playbackRate;
2011 }
2012 }
2013 }
2014 return status;
2015}
2016
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002017//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002018bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07002019 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002020 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07002021 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002022 /* Resume is pending if track was stopping before pause was called */
2023 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07002024 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002025 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07002026 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002027
2028 return false;
2029}
2030
2031//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002032void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07002033 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002034 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07002035 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002036
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002037 // Other possibility of pending resume is stopping_1 state
2038 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002039 // drain being called.
2040 if (mState == STOPPING_1) {
2041 mResumeToStopping = false;
2042 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002043}
Andy Hunge10393e2015-06-12 13:59:33 -07002044
2045//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002046void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002047 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002048 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002049 // Make the kernel frametime available.
2050 const FrameTime ft{
2051 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2052 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2053 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2054 mKernelFrameTime.store(ft);
2055 if (!audio_is_linear_pcm(mFormat)) {
2056 return;
2057 }
2058
Andy Hung818e7a32016-02-16 18:08:07 -08002059 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002060 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002061
2062 // adjust server times and set drained state.
2063 //
2064 // Our timestamps are only updated when the track is on the Thread active list.
2065 // We need to ensure that tracks are not removed before full drain.
2066 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002067 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002068 bool checked = false;
2069 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2070 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2071 // Lookup the track frame corresponding to the sink frame position.
2072 if (local.mTimeNs[i] > 0) {
2073 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2074 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002075 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002076 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002077 checked = true;
2078 }
2079 }
Andy Hunge10393e2015-06-12 13:59:33 -07002080 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002081
Andy Hung93bb5732023-05-04 21:16:34 -07002082 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2083 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002084 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002085 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002086 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002087 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002088
2089 // Compute latency info.
2090 const bool useTrackTimestamp = !drained;
2091 const double latencyMs = useTrackTimestamp
2092 ? local.getOutputServerLatencyMs(sampleRate())
2093 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2094
2095 mServerLatencyFromTrack.store(useTrackTimestamp);
2096 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002097
Andy Hung62921122020-05-18 10:47:31 -07002098 if (mLogStartCountdown > 0
2099 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2100 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2101 {
2102 if (mLogStartCountdown > 1) {
2103 --mLogStartCountdown;
2104 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2105 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002106 // startup is the difference in times for the current timestamp and our start
2107 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002108 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002109 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002110 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2111 * 1e3 / mSampleRate;
2112 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2113 " localTime:%lld startTime:%lld"
2114 " localPosition:%lld startPosition:%lld",
2115 __func__, latencyMs, startUpMs,
2116 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002117 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002118 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002119 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002120 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002121 }
Andy Hung62921122020-05-18 10:47:31 -07002122 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002123 }
Andy Hunge10393e2015-06-12 13:59:33 -07002124}
2125
Andy Hung3ff4b552023-06-26 19:20:57 -07002126bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002127 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002128 if (thread != 0) {
2129 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87e82412023-08-29 14:26:09 -07002130 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002131 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002132 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002133 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002134 ALOGD("%s, haptic playback was %s for track %d",
2135 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002136 mTrack->setHapticPlaybackEnabled(!muted);
2137 return true;
jiabin57303cc2018-12-18 15:45:57 -08002138 }
2139 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002140 return false;
2141}
2142
Andy Hung3ff4b552023-06-26 19:20:57 -07002143binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002144 /*out*/ bool *ret) {
2145 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002146 return binder::Status::ok();
2147}
2148
Andy Hung3ff4b552023-06-26 19:20:57 -07002149binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002150 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002151 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002152 return binder::Status::ok();
2153}
2154
Eric Laurent81784c32012-11-19 14:55:58 -08002155// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002156#undef LOG_TAG
2157#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002158
Andy Hung3ff4b552023-06-26 19:20:57 -07002159/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002160sp<IAfOutputTrack> IAfOutputTrack::create(
2161 IAfPlaybackThread* playbackThread,
2162 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002163 uint32_t sampleRate,
2164 audio_format_t format,
2165 audio_channel_mask_t channelMask,
2166 size_t frameCount,
2167 const AttributionSourceState& attributionSource) {
2168 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002169 playbackThread,
2170 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002171 sampleRate,
2172 format,
2173 channelMask,
2174 frameCount,
2175 attributionSource);
2176}
2177
2178OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002179 IAfPlaybackThread* playbackThread,
2180 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002181 uint32_t sampleRate,
2182 audio_format_t format,
2183 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002184 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002185 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002186 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002187 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002188 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002189 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002190 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002191 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002192 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002193{
2194
2195 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002196 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002197 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002198 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002199 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002200 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002201 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002202 // since client and server are in the same process,
2203 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002204 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2205 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002206 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002207 mClientProxy->setSendLevel(0.0);
2208 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002209 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002210 ALOGW("%s(%d): Error creating output track on thread %d",
2211 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002212 }
2213}
2214
Andy Hung3ff4b552023-06-26 19:20:57 -07002215OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002216{
2217 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002218 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002219}
2220
Andy Hung3ff4b552023-06-26 19:20:57 -07002221status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002222 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002223{
2224 status_t status = Track::start(event, triggerSession);
2225 if (status != NO_ERROR) {
2226 return status;
2227 }
2228
2229 mActive = true;
2230 mRetryCount = 127;
2231 return status;
2232}
2233
Andy Hung3ff4b552023-06-26 19:20:57 -07002234void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002235{
2236 Track::stop();
2237 clearBufferQueue();
2238 mOutBuffer.frameCount = 0;
2239 mActive = false;
2240}
2241
Andy Hung3ff4b552023-06-26 19:20:57 -07002242ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002243{
Eric Laurent19952e12023-04-20 10:08:29 +02002244 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002245 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002246 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002247 // preload one silent buffer to trigger mixer on start()
2248 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2249 status_t status = mClientProxy->obtainBuffer(&buf);
2250 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2251 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2252 return 0;
2253 }
2254 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2255 mClientProxy->releaseBuffer(&buf);
2256
2257 (void) start();
2258
2259 // wait for HAL stream to start before sending actual audio. Doing this on each
2260 // OutputTrack makes that playback start on all output streams is synchronized.
2261 // If another OutputTrack has already started it can underrun but this is OK
2262 // as only silence has been played so far and the retry count is very high on
2263 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002264 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002265 if (!pt->waitForHalStart()) {
2266 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2267 stop();
2268 return 0;
2269 }
2270
2271 // enqueue the first buffer and exit so that other OutputTracks will also start before
2272 // write() is called again and this buffer actually consumed.
2273 Buffer firstBuffer;
2274 firstBuffer.frameCount = frames;
2275 firstBuffer.raw = data;
2276 queueBuffer(firstBuffer);
2277 return frames;
2278 } else {
2279 (void) start();
2280 }
2281 }
2282
Eric Laurent81784c32012-11-19 14:55:58 -08002283 Buffer *pInBuffer;
2284 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002285 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002286 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002287 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002288 while (waitTimeLeftMs) {
2289 // First write pending buffers, then new data
2290 if (mBufferQueue.size()) {
2291 pInBuffer = mBufferQueue.itemAt(0);
2292 } else {
2293 pInBuffer = &inBuffer;
2294 }
2295
2296 if (pInBuffer->frameCount == 0) {
2297 break;
2298 }
2299
2300 if (mOutBuffer.frameCount == 0) {
2301 mOutBuffer.frameCount = pInBuffer->frameCount;
2302 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002303 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002304 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002305 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2306 __func__, mId,
2307 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002308 break;
2309 }
2310 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2311 if (waitTimeLeftMs >= waitTimeMs) {
2312 waitTimeLeftMs -= waitTimeMs;
2313 } else {
2314 waitTimeLeftMs = 0;
2315 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002316 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002317 deferRestartIfDisabled();
Eric Laurent4d231dc2016-03-11 18:38:23 -08002318 continue;
2319 }
Eric Laurent81784c32012-11-19 14:55:58 -08002320 }
2321
2322 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2323 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002324 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002325 Proxy::Buffer buf;
2326 buf.mFrameCount = outFrames;
2327 buf.mRaw = NULL;
2328 mClientProxy->releaseBuffer(&buf);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002329 deferRestartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002330 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002331 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002332 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002333 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002334
2335 if (pInBuffer->frameCount == 0) {
2336 if (mBufferQueue.size()) {
2337 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002338 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002339 if (pInBuffer != &inBuffer) {
2340 delete pInBuffer;
2341 }
Andy Hung9d84af52018-09-12 18:03:44 -07002342 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2343 __func__, mId,
2344 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002345 } else {
2346 break;
2347 }
2348 }
2349 }
2350
2351 // If we could not write all frames, allocate a buffer and queue it for next time.
2352 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002353 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002354 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002355 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002356 }
2357 }
2358
Andy Hungc25b84a2015-01-14 19:04:10 -08002359 // Calling write() with a 0 length buffer means that no more data will be written:
2360 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2361 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2362 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002363 }
2364
Andy Hung1c86ebe2018-05-29 20:29:08 -07002365 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002366}
2367
Andy Hung3ff4b552023-06-26 19:20:57 -07002368void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002369
2370 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2371 Buffer *pInBuffer = new Buffer;
2372 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2373 pInBuffer->mBuffer = malloc(bufferSize);
2374 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2375 "%s: Unable to malloc size %zu", __func__, bufferSize);
2376 pInBuffer->frameCount = inBuffer.frameCount;
2377 pInBuffer->raw = pInBuffer->mBuffer;
2378 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2379 mBufferQueue.add(pInBuffer);
2380 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2381 (int)mThreadIoHandle, mBufferQueue.size());
2382 // audio data is consumed (stored locally); set frameCount to 0.
2383 inBuffer.frameCount = 0;
2384 } else {
2385 ALOGW("%s(%d): thread %d no more overflow buffers",
2386 __func__, mId, (int)mThreadIoHandle);
2387 // TODO: return error for this.
2388 }
2389}
2390
Andy Hung3ff4b552023-06-26 19:20:57 -07002391void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002392{
Andy Hung87e82412023-08-29 14:26:09 -07002393 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002394 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2395}
2396
Andy Hung3ff4b552023-06-26 19:20:57 -07002397void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002398 {
Andy Hung87e82412023-08-29 14:26:09 -07002399 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002400 mTrackMetadatas = metadatas;
2401 }
2402 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2403 setMetadataHasChanged();
2404}
2405
Andy Hung3ff4b552023-06-26 19:20:57 -07002406status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002407 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2408{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002409 ClientProxy::Buffer buf;
2410 buf.mFrameCount = buffer->frameCount;
2411 struct timespec timeout;
2412 timeout.tv_sec = waitTimeMs / 1000;
2413 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2414 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2415 buffer->frameCount = buf.mFrameCount;
2416 buffer->raw = buf.mRaw;
2417 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002418}
2419
Andy Hung3ff4b552023-06-26 19:20:57 -07002420void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002421{
2422 size_t size = mBufferQueue.size();
2423
2424 for (size_t i = 0; i < size; i++) {
2425 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002426 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002427 delete pBuffer;
2428 }
2429 mBufferQueue.clear();
2430}
2431
Andy Hung3ff4b552023-06-26 19:20:57 -07002432void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002433{
2434 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2435 if (mActive && (flags & CBLK_DISABLED)) {
2436 start();
2437 }
2438}
Eric Laurent81784c32012-11-19 14:55:58 -08002439
Andy Hung9d84af52018-09-12 18:03:44 -07002440// ----------------------------------------------------------------------------
2441#undef LOG_TAG
2442#define LOG_TAG "AF::PatchTrack"
2443
Andy Hung3ff4b552023-06-26 19:20:57 -07002444/* static */
2445sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002446 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002447 audio_stream_type_t streamType,
2448 uint32_t sampleRate,
2449 audio_channel_mask_t channelMask,
2450 audio_format_t format,
2451 size_t frameCount,
2452 void* buffer,
2453 size_t bufferSize,
2454 audio_output_flags_t flags,
2455 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002456 size_t frameCountToBeReady, /** Default behaviour is to start
Andy Hung3ff4b552023-06-26 19:20:57 -07002457 * as soon as possible to have
2458 * the lowest possible latency
guonaichao3acc9b12024-06-07 09:27:21 +08002459 * even if it might glitch. */
2460 float speed)
Andy Hung3ff4b552023-06-26 19:20:57 -07002461{
2462 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002463 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002464 streamType,
2465 sampleRate,
2466 channelMask,
2467 format,
2468 frameCount,
2469 buffer,
2470 bufferSize,
2471 flags,
2472 timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002473 frameCountToBeReady,
2474 speed);
Andy Hung3ff4b552023-06-26 19:20:57 -07002475}
2476
Andy Hung44f27182023-07-06 20:56:16 -07002477PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002478 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002479 uint32_t sampleRate,
2480 audio_channel_mask_t channelMask,
2481 audio_format_t format,
2482 size_t frameCount,
2483 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002484 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002485 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002486 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002487 size_t frameCountToBeReady,
2488 float speed)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002489 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002490 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002491 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002492 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002493 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
guonaichao3acc9b12024-06-07 09:27:21 +08002494 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed),
2495 PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
2496 true /*clientInServer*/) : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07002497 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002498{
guonaichao3acc9b12024-06-07 09:27:21 +08002499 if (mProxy != nullptr) {
2500 sp<AudioTrackClientProxy>::cast(mProxy)->setPlaybackRate({
2501 /* .mSpeed = */ speed,
2502 /* .mPitch = */ AUDIO_TIMESTRETCH_PITCH_NORMAL,
2503 /* .mStretchMode = */ AUDIO_TIMESTRETCH_STRETCH_DEFAULT,
2504 /* .mFallbackMode = */ AUDIO_TIMESTRETCH_FALLBACK_FAIL
2505 });
2506 }
Andy Hung9d84af52018-09-12 18:03:44 -07002507 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2508 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002509 (int)mPeerTimeout.tv_sec,
2510 (int)(mPeerTimeout.tv_nsec / 1000000));
2511}
2512
Andy Hung3ff4b552023-06-26 19:20:57 -07002513PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002514{
Andy Hungabfab202019-03-07 19:45:54 -08002515 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002516}
2517
Andy Hung3ff4b552023-06-26 19:20:57 -07002518size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002519{
2520 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2521 return std::numeric_limits<size_t>::max();
2522 } else {
2523 return Track::framesReady();
2524 }
2525}
2526
Andy Hung3ff4b552023-06-26 19:20:57 -07002527status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002528 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002529{
2530 status_t status = Track::start(event, triggerSession);
2531 if (status != NO_ERROR) {
2532 return status;
2533 }
2534 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2535 return status;
2536}
2537
Eric Laurent83b88082014-06-20 18:31:16 -07002538// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002539status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002540 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002541{
Andy Hung9d84af52018-09-12 18:03:44 -07002542 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002543 Proxy::Buffer buf;
2544 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002545 if (ATRACE_ENABLED()) {
2546 std::string traceName("PTnReq");
2547 traceName += std::to_string(id());
2548 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2549 }
Eric Laurent83b88082014-06-20 18:31:16 -07002550 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002551 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002552 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002553 if (ATRACE_ENABLED()) {
2554 std::string traceName("PTnObt");
2555 traceName += std::to_string(id());
2556 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2557 }
Eric Laurent83b88082014-06-20 18:31:16 -07002558 if (buf.mFrameCount == 0) {
2559 return WOULD_BLOCK;
2560 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002561 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002562 return status;
2563}
2564
Andy Hung3ff4b552023-06-26 19:20:57 -07002565void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002566{
Andy Hung9d84af52018-09-12 18:03:44 -07002567 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002568 Proxy::Buffer buf;
2569 buf.mFrameCount = buffer->frameCount;
2570 buf.mRaw = buffer->raw;
2571 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002572 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002573}
2574
Andy Hung3ff4b552023-06-26 19:20:57 -07002575status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002576 const struct timespec *timeOut)
2577{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002578 status_t status = NO_ERROR;
2579 static const int32_t kMaxTries = 5;
2580 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002581 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002582 do {
2583 if (status == NOT_ENOUGH_DATA) {
Andy Hung56ce2ed2024-06-12 16:03:16 -07002584 deferRestartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002585 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002586 }
2587 status = mProxy->obtainBuffer(buffer, timeOut);
2588 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2589 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002590}
2591
Andy Hung3ff4b552023-06-26 19:20:57 -07002592void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002593{
2594 mProxy->releaseBuffer(buffer);
Andy Hung56ce2ed2024-06-12 16:03:16 -07002595 deferRestartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002596
2597 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2598 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2599 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2600 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002601 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002602 && audio_is_linear_pcm(mFormat)
2603 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002604 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002605 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002606 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002607 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2608 / playbackThread->sampleRate();
2609 if (framesReady() < frameCount) {
2610 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002611 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002612 }
2613 }
2614 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002615}
2616
Andy Hung3ff4b552023-06-26 19:20:57 -07002617void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002618{
Eric Laurent83b88082014-06-20 18:31:16 -07002619 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002620 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002621 start();
2622 }
Eric Laurent83b88082014-06-20 18:31:16 -07002623}
2624
Eric Laurent81784c32012-11-19 14:55:58 -08002625// ----------------------------------------------------------------------------
2626// Record
2627// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002628
2629
Andy Hung9d84af52018-09-12 18:03:44 -07002630#undef LOG_TAG
2631#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002632
Andy Hungaaa18282023-06-23 19:27:19 -07002633class RecordHandle : public android::media::BnAudioRecord {
2634public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002635 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002636 ~RecordHandle() override;
2637 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2638 int /*audio_session_t*/ triggerSession) final;
2639 binder::Status stop() final;
2640 binder::Status getActiveMicrophones(
2641 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2642 binder::Status setPreferredMicrophoneDirection(
2643 int /*audio_microphone_direction_t*/ direction) final;
2644 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2645 binder::Status shareAudioHistory(
2646 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2647
2648private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002649 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002650
2651 // for use from destructor
2652 void stop_nonvirtual();
2653};
2654
2655/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002656sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2657 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002658 return sp<RecordHandle>::make(recordTrack);
2659}
2660
2661RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002662 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002663 : BnAudioRecord(),
2664 mRecordTrack(recordTrack)
2665{
Andy Hung225aef62022-12-06 16:33:20 -08002666 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hungf2b4a182024-03-26 18:04:29 -07002667 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -08002668}
2669
Andy Hungaaa18282023-06-23 19:27:19 -07002670RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002671 stop_nonvirtual();
2672 mRecordTrack->destroy();
2673}
2674
Andy Hungaaa18282023-06-23 19:27:19 -07002675binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002676 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002677 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002678 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002679 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002680}
2681
Andy Hungaaa18282023-06-23 19:27:19 -07002682binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002683 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002684 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002685}
2686
Andy Hungaaa18282023-06-23 19:27:19 -07002687void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002688 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002689 mRecordTrack->stop();
2690}
2691
Andy Hungaaa18282023-06-23 19:27:19 -07002692binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002693 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002694 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002695 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002696}
2697
Andy Hungaaa18282023-06-23 19:27:19 -07002698binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002699 int /*audio_microphone_direction_t*/ direction) {
2700 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002701 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002702 static_cast<audio_microphone_direction_t>(direction)));
2703}
2704
Andy Hungaaa18282023-06-23 19:27:19 -07002705binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002706 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002707 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002708}
2709
Andy Hungaaa18282023-06-23 19:27:19 -07002710binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002711 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2712 return binderStatusFromStatusT(
2713 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2714}
2715
Eric Laurent81784c32012-11-19 14:55:58 -08002716// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002717#undef LOG_TAG
2718#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002719
Andy Hung3ff4b552023-06-26 19:20:57 -07002720
Andy Hung56126702023-07-14 11:00:08 -07002721/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002722sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002723 const sp<Client>& client,
2724 const audio_attributes_t& attr,
2725 uint32_t sampleRate,
2726 audio_format_t format,
2727 audio_channel_mask_t channelMask,
2728 size_t frameCount,
2729 void* buffer,
2730 size_t bufferSize,
2731 audio_session_t sessionId,
2732 pid_t creatorPid,
2733 const AttributionSourceState& attributionSource,
2734 audio_input_flags_t flags,
2735 track_type type,
2736 audio_port_handle_t portId,
2737 int32_t startFrames)
2738{
2739 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002740 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002741 client,
2742 attr,
2743 sampleRate,
2744 format,
2745 channelMask,
2746 frameCount,
2747 buffer,
2748 bufferSize,
2749 sessionId,
2750 creatorPid,
2751 attributionSource,
2752 flags,
2753 type,
2754 portId,
2755 startFrames);
2756}
2757
Glenn Kasten05997e22014-03-13 15:08:33 -07002758// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002759RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002760 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002761 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002762 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002763 uint32_t sampleRate,
2764 audio_format_t format,
2765 audio_channel_mask_t channelMask,
2766 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002767 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002768 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002769 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002770 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002771 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002772 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002773 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002774 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002775 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002776 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002777 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002778 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002779 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002780 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002781 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002782 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002783 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002784 type, portId,
2785 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002786 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002787 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002788 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002789 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002790 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002791 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002792{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002793 if (mCblk == NULL) {
2794 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002795 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002796
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002797 if (!isDirect()) {
2798 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002799 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002800 channelMask, format, sampleRate);
2801 // Check if the RecordBufferConverter construction was successful.
2802 // If not, don't continue with construction.
2803 //
2804 // NOTE: It would be extremely rare that the record track cannot be created
2805 // for the current device, but a pending or future device change would make
2806 // the record track configuration valid.
2807 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002808 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002809 return;
2810 }
Andy Hung97a893e2015-03-29 01:03:07 -07002811 }
2812
Andy Hung6ae58432016-02-16 18:32:24 -08002813 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002814 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002815
Andy Hung97a893e2015-03-29 01:03:07 -07002816 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002817
Eric Laurent05067782016-06-01 18:27:28 -07002818 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002819 ALOG_ASSERT(thread->fastTrackAvailable());
2820 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002821 } else {
2822 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002823 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002824 }
Andy Hung8946a282018-04-19 20:04:56 -07002825#ifdef TEE_SINK
2826 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2827 + "_" + std::to_string(mId)
2828 + "_R");
2829#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002830
2831 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002832 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002833}
2834
Andy Hung3ff4b552023-06-26 19:20:57 -07002835RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002836{
Andy Hung9d84af52018-09-12 18:03:44 -07002837 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002838 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002839 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002840}
2841
Andy Hung3ff4b552023-06-26 19:20:57 -07002842status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002843{
2844 status_t status = TrackBase::initCheck();
2845 if (status == NO_ERROR && mServerProxy == 0) {
2846 status = BAD_VALUE;
2847 }
2848 return status;
2849}
2850
Eric Laurent81784c32012-11-19 14:55:58 -08002851// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002852status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002853{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002854 ServerProxy::Buffer buf;
2855 buf.mFrameCount = buffer->frameCount;
2856 status_t status = mServerProxy->obtainBuffer(&buf);
2857 buffer->frameCount = buf.mFrameCount;
2858 buffer->raw = buf.mRaw;
2859 if (buf.mFrameCount == 0) {
2860 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002861 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002862 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002863 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002864}
2865
Andy Hung3ff4b552023-06-26 19:20:57 -07002866status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002867 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002868{
Andy Hung44f27182023-07-06 20:56:16 -07002869 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002870 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002871 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002872 return recordThread->start(this, event, triggerSession);
2873 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002874 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2875 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002876 }
2877}
2878
Andy Hung3ff4b552023-06-26 19:20:57 -07002879void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002880{
Andy Hung44f27182023-07-06 20:56:16 -07002881 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002882 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002883 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002884 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002885 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002886 }
2887 }
2888}
2889
Andy Hung3ff4b552023-06-26 19:20:57 -07002890void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002891{
Andy Hung3ff4b552023-06-26 19:20:57 -07002892 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002893 sp<RecordTrack> keep(this);
2894 {
Andy Hungce685402018-10-05 17:23:27 -07002895 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002896 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002897 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07002898 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002899 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002900 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002901 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002902 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002903 }
Andy Hungce685402018-10-05 17:23:27 -07002904 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2905 }
2906 // APM portid/client management done outside of lock.
2907 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2908 if (isExternalTrack()) {
2909 switch (priorState) {
2910 case ACTIVE: // invalidated while still active
2911 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2912 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2913 AudioSystem::stopInput(mPortId);
2914 break;
2915
2916 case STARTING_1: // invalidated/start-aborted and startInput not successful
2917 case PAUSED: // OK, not active
2918 case IDLE: // OK, not active
2919 break;
2920
2921 case STOPPED: // unexpected (destroyed)
2922 default:
2923 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2924 }
2925 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002926 }
2927 }
2928}
2929
Andy Hung3ff4b552023-06-26 19:20:57 -07002930void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002931{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002932 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002933 // FIXME should use proxy, and needs work
2934 audio_track_cblk_t* cblk = mCblk;
2935 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2936 android_atomic_release_store(0x40000000, &cblk->mFutex);
2937 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002938 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002939}
2940
Eric Laurent81784c32012-11-19 14:55:58 -08002941
Andy Hung3ff4b552023-06-26 19:20:57 -07002942void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002943{
Eric Laurent973db022018-11-20 14:54:31 -08002944 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002945 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002946 " Server FrmCnt FrmRdy Sil%s\n",
2947 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002948}
2949
Andy Hung3ff4b552023-06-26 19:20:57 -07002950void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002951{
Eric Laurent973db022018-11-20 14:54:31 -08002952 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002953 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002954 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002955 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002956 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002957 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002958 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002959 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002960 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002961 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002962 mCblk->mFlags,
2963
Eric Laurent81784c32012-11-19 14:55:58 -08002964 mFormat,
2965 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002966 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002967 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002968
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002969 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002970 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002971 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002972 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002973 );
Andy Hung000adb52018-06-01 15:43:26 -07002974 if (isServerLatencySupported()) {
2975 double latencyMs;
2976 bool fromTrack;
2977 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2978 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2979 // or 'k' if estimated from kernel (usually for debugging).
2980 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2981 } else {
2982 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2983 }
2984 }
2985 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002986}
2987
Andy Hung93bb5732023-05-04 21:16:34 -07002988// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002989void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002990 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002991{
Andy Hung93bb5732023-05-04 21:16:34 -07002992 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002993 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002994 if (threadBase != 0) {
2995 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2996 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002997 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002998 }
Andy Hung93bb5732023-05-04 21:16:34 -07002999
3000 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003001}
3002
Andy Hung3ff4b552023-06-26 19:20:57 -07003003void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003004{
Andy Hung93bb5732023-05-04 21:16:34 -07003005 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08003006}
3007
Andy Hung3ff4b552023-06-26 19:20:57 -07003008void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08003009 int64_t trackFramesReleased, int64_t sourceFramesRead,
3010 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
3011{
Andy Hung30282562018-08-08 18:27:03 -07003012 // Make the kernel frametime available.
3013 const FrameTime ft{
3014 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
3015 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
3016 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
3017 mKernelFrameTime.store(ft);
3018 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05003019 // Stream is direct, return provided timestamp with no conversion
3020 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07003021 return;
3022 }
3023
Andy Hung3f0c9022016-01-15 17:49:46 -08003024 ExtendedTimestamp local = timestamp;
3025
3026 // Convert HAL frames to server-side track frames at track sample rate.
3027 // We use trackFramesReleased and sourceFramesRead as an anchor point.
3028 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
3029 if (local.mTimeNs[i] != 0) {
3030 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
3031 const int64_t relativeTrackFrames = relativeServerFrames
3032 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3033 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3034 }
3035 }
Andy Hung6ae58432016-02-16 18:32:24 -08003036 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003037
3038 // Compute latency info.
3039 const bool useTrackTimestamp = true; // use track unless debugging.
3040 const double latencyMs = - (useTrackTimestamp
3041 ? local.getOutputServerLatencyMs(sampleRate())
3042 : timestamp.getOutputServerLatencyMs(halSampleRate));
3043
3044 mServerLatencyFromTrack.store(useTrackTimestamp);
3045 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003046}
Eric Laurent83b88082014-06-20 18:31:16 -07003047
Andy Hung3ff4b552023-06-26 19:20:57 -07003048status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003049 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003050{
Andy Hung44f27182023-07-06 20:56:16 -07003051 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003052 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003053 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003054 return recordThread->getActiveMicrophones(activeMicrophones);
3055 } else {
3056 return BAD_VALUE;
3057 }
3058}
3059
Andy Hung3ff4b552023-06-26 19:20:57 -07003060status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003061 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003062 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003063 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003064 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003065 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003066 } else {
3067 return BAD_VALUE;
3068 }
3069}
3070
Andy Hung3ff4b552023-06-26 19:20:57 -07003071status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003072 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003073 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003074 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003075 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003076 } else {
3077 return BAD_VALUE;
3078 }
3079}
3080
Andy Hung3ff4b552023-06-26 19:20:57 -07003081status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003082 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3083
3084 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3085 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3086 if (callingUid != mUid || callingPid != mCreatorPid) {
3087 return PERMISSION_DENIED;
3088 }
3089
Svet Ganov33761132021-05-13 22:51:08 +00003090 AttributionSourceState attributionSource{};
3091 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3092 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3093 attributionSource.token = sp<BBinder>::make();
3094 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003095 return PERMISSION_DENIED;
3096 }
3097
Andy Hung44f27182023-07-06 20:56:16 -07003098 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003099 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003100 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003101 status_t status = recordThread->shareAudioHistory(
3102 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3103 if (status == NO_ERROR) {
3104 mSharedAudioPackageName = sharedAudioPackageName;
3105 }
3106 return status;
3107 } else {
3108 return BAD_VALUE;
3109 }
3110}
3111
Andy Hung3ff4b552023-06-26 19:20:57 -07003112void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003113{
3114
3115 // Do not forward PatchRecord metadata with unspecified audio source
3116 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3117 return;
3118 }
3119
3120 // No track is invalid as this is called after prepareTrack_l in the same critical section
3121 record_track_metadata_v7_t metadata;
3122 metadata.base = {
3123 .source = mAttr.source,
3124 .gain = 1, // capture tracks do not have volumes
3125 };
3126 metadata.channel_mask = mChannelMask;
3127 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3128
3129 *backInserter++ = metadata;
3130}
Eric Laurentec376dc2021-04-08 20:41:22 +02003131
Andy Hung9d84af52018-09-12 18:03:44 -07003132// ----------------------------------------------------------------------------
3133#undef LOG_TAG
3134#define LOG_TAG "AF::PatchRecord"
3135
Andy Hung3ff4b552023-06-26 19:20:57 -07003136/* static */
3137sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003138 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003139 uint32_t sampleRate,
3140 audio_channel_mask_t channelMask,
3141 audio_format_t format,
3142 size_t frameCount,
3143 void *buffer,
3144 size_t bufferSize,
3145 audio_input_flags_t flags,
3146 const Timeout& timeout,
3147 audio_source_t source)
3148{
3149 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003150 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003151 sampleRate,
3152 channelMask,
3153 format,
3154 frameCount,
3155 buffer,
3156 bufferSize,
3157 flags,
3158 timeout,
3159 source);
3160}
3161
Andy Hung44f27182023-07-06 20:56:16 -07003162PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003163 uint32_t sampleRate,
3164 audio_channel_mask_t channelMask,
3165 audio_format_t format,
3166 size_t frameCount,
3167 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003168 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003169 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003170 const Timeout& timeout,
3171 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003172 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003173 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003174 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003175 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003176 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003177 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3178 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07003179 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003180{
Andy Hung9d84af52018-09-12 18:03:44 -07003181 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3182 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003183 (int)mPeerTimeout.tv_sec,
3184 (int)(mPeerTimeout.tv_nsec / 1000000));
3185}
3186
Andy Hung3ff4b552023-06-26 19:20:57 -07003187PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003188{
Andy Hungabfab202019-03-07 19:45:54 -08003189 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003190}
3191
Mikhail Naganov8296c252019-09-25 14:59:54 -07003192static size_t writeFramesHelper(
3193 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3194{
3195 AudioBufferProvider::Buffer patchBuffer;
3196 patchBuffer.frameCount = frameCount;
3197 auto status = dest->getNextBuffer(&patchBuffer);
3198 if (status != NO_ERROR) {
3199 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3200 __func__, status, strerror(-status));
3201 return 0;
3202 }
3203 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3204 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3205 size_t framesWritten = patchBuffer.frameCount;
3206 dest->releaseBuffer(&patchBuffer);
3207 return framesWritten;
3208}
3209
3210// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003211size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003212 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3213{
3214 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3215 // On buffer wrap, the buffer frame count will be less than requested,
3216 // when this happens a second buffer needs to be used to write the leftover audio
3217 const size_t framesLeft = frameCount - framesWritten;
3218 if (framesWritten != 0 && framesLeft != 0) {
3219 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3220 framesLeft, frameSize);
3221 }
3222 return framesWritten;
3223}
3224
Eric Laurent83b88082014-06-20 18:31:16 -07003225// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003226status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003227 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003228{
Andy Hung9d84af52018-09-12 18:03:44 -07003229 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003230 Proxy::Buffer buf;
3231 buf.mFrameCount = buffer->frameCount;
3232 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3233 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003234 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003235 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003236 if (ATRACE_ENABLED()) {
3237 std::string traceName("PRnObt");
3238 traceName += std::to_string(id());
3239 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3240 }
Eric Laurent83b88082014-06-20 18:31:16 -07003241 if (buf.mFrameCount == 0) {
3242 return WOULD_BLOCK;
3243 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003244 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003245 return status;
3246}
3247
Andy Hung3ff4b552023-06-26 19:20:57 -07003248void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003249{
Andy Hung9d84af52018-09-12 18:03:44 -07003250 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003251 Proxy::Buffer buf;
3252 buf.mFrameCount = buffer->frameCount;
3253 buf.mRaw = buffer->raw;
3254 mPeerProxy->releaseBuffer(&buf);
3255 TrackBase::releaseBuffer(buffer);
3256}
3257
Andy Hung3ff4b552023-06-26 19:20:57 -07003258status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003259 const struct timespec *timeOut)
3260{
3261 return mProxy->obtainBuffer(buffer, timeOut);
3262}
3263
Andy Hung3ff4b552023-06-26 19:20:57 -07003264void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003265{
3266 mProxy->releaseBuffer(buffer);
3267}
3268
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003269#undef LOG_TAG
3270#define LOG_TAG "AF::PthrPatchRecord"
3271
3272static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3273{
3274 void *ptr = nullptr;
3275 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003276 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003277}
3278
Andy Hung3ff4b552023-06-26 19:20:57 -07003279/* static */
3280sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003281 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003282 uint32_t sampleRate,
3283 audio_channel_mask_t channelMask,
3284 audio_format_t format,
3285 size_t frameCount,
3286 audio_input_flags_t flags,
3287 audio_source_t source)
3288{
3289 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003290 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003291 sampleRate,
3292 channelMask,
3293 format,
3294 frameCount,
3295 flags,
3296 source);
3297}
3298
3299PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003300 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003301 uint32_t sampleRate,
3302 audio_channel_mask_t channelMask,
3303 audio_format_t format,
3304 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003305 audio_input_flags_t flags,
3306 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003307 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003308 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003309 mPatchRecordAudioBufferProvider(*this),
3310 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3311 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3312{
3313 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3314}
3315
Andy Hung3ff4b552023-06-26 19:20:57 -07003316sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003317 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003318{
3319 *thread = mThread.promote();
3320 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003321 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07003322 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07003323 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003324}
3325
3326// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003327status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003328 Proxy::Buffer* buffer, const struct timespec* timeOut)
3329{
3330 if (mUnconsumedFrames) {
3331 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3332 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3333 return PatchRecord::obtainBuffer(buffer, timeOut);
3334 }
3335
3336 // Otherwise, execute a read from HAL and write into the buffer.
3337 nsecs_t startTimeNs = 0;
3338 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3339 // Will need to correct timeOut by elapsed time.
3340 startTimeNs = systemTime();
3341 }
3342 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3343 buffer->mFrameCount = 0;
3344 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003345 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003346 sp<StreamInHalInterface> stream = obtainStream(&thread);
3347 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3348
3349 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003350 size_t bytesRead = 0;
3351 {
3352 ATRACE_NAME("read");
3353 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3354 if (result != NO_ERROR) goto stream_error;
3355 if (bytesRead == 0) return NO_ERROR;
3356 }
3357
3358 {
Andy Hung094dc762023-08-28 19:12:14 -07003359 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003360 mReadBytes += bytesRead;
3361 mReadError = NO_ERROR;
3362 }
3363 mReadCV.notify_one();
3364 // writeFrames handles wraparound and should write all the provided frames.
3365 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3366 buffer->mFrameCount = writeFrames(
3367 &mPatchRecordAudioBufferProvider,
3368 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3369 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3370 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3371 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003372 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003373 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003374 // Correct the timeout by elapsed time.
3375 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003376 if (newTimeOutNs < 0) newTimeOutNs = 0;
3377 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3378 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003379 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003380 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003381 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003382
3383stream_error:
3384 stream->standby();
3385 {
Andy Hung094dc762023-08-28 19:12:14 -07003386 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003387 mReadError = result;
3388 }
3389 mReadCV.notify_one();
3390 return result;
3391}
3392
Andy Hung3ff4b552023-06-26 19:20:57 -07003393void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003394{
3395 if (buffer->mFrameCount <= mUnconsumedFrames) {
3396 mUnconsumedFrames -= buffer->mFrameCount;
3397 } else {
3398 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3399 buffer->mFrameCount, mUnconsumedFrames);
3400 mUnconsumedFrames = 0;
3401 }
3402 PatchRecord::releaseBuffer(buffer);
3403}
3404
3405// AudioBufferProvider and Source methods are called on RecordThread
3406// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3407// and 'releaseBuffer' are stubbed out and ignore their input.
3408// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3409// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003410status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003411 void* buffer, size_t bytes, size_t* read)
3412{
3413 bytes = std::min(bytes, mFrameCount * mFrameSize);
3414 {
Andy Hung094dc762023-08-28 19:12:14 -07003415 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003416 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3417 if (mReadError != NO_ERROR) {
3418 mLastReadFrames = 0;
3419 return mReadError;
3420 }
3421 *read = std::min(bytes, mReadBytes);
3422 mReadBytes -= *read;
3423 }
3424 mLastReadFrames = *read / mFrameSize;
3425 memset(buffer, 0, *read);
3426 return 0;
3427}
3428
Andy Hung3ff4b552023-06-26 19:20:57 -07003429status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003430 int64_t* frames, int64_t* time)
3431{
Andy Hung44f27182023-07-06 20:56:16 -07003432 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003433 sp<StreamInHalInterface> stream = obtainStream(&thread);
3434 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3435}
3436
Andy Hung3ff4b552023-06-26 19:20:57 -07003437status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003438{
3439 // RecordThread issues 'standby' command in two major cases:
3440 // 1. Error on read--this case is handled in 'obtainBuffer'.
3441 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3442 // output, this can only happen when the software patch
3443 // is being torn down. In this case, the RecordThread
3444 // will terminate and close the HAL stream.
3445 return 0;
3446}
3447
3448// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003449status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003450 AudioBufferProvider::Buffer* buffer)
3451{
3452 buffer->frameCount = mLastReadFrames;
3453 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3454 return NO_ERROR;
3455}
3456
Andy Hung3ff4b552023-06-26 19:20:57 -07003457void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003458 AudioBufferProvider::Buffer* buffer)
3459{
3460 buffer->frameCount = 0;
3461 buffer->raw = nullptr;
3462}
3463
Andy Hung9d84af52018-09-12 18:03:44 -07003464// ----------------------------------------------------------------------------
3465#undef LOG_TAG
3466#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003467
Andy Hung3ff4b552023-06-26 19:20:57 -07003468/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003469sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003470 const audio_attributes_t& attr,
3471 uint32_t sampleRate,
3472 audio_format_t format,
3473 audio_channel_mask_t channelMask,
3474 audio_session_t sessionId,
3475 bool isOut,
3476 const android::content::AttributionSourceState& attributionSource,
3477 pid_t creatorPid,
3478 audio_port_handle_t portId)
3479{
3480 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003481 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003482 attr,
3483 sampleRate,
3484 format,
3485 channelMask,
3486 sessionId,
3487 isOut,
3488 attributionSource,
3489 creatorPid,
3490 portId);
3491}
3492
Andy Hung44f27182023-07-06 20:56:16 -07003493MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003494 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003495 uint32_t sampleRate,
3496 audio_format_t format,
3497 audio_channel_mask_t channelMask,
3498 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003499 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003500 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003501 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003502 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003503 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003504 channelMask, (size_t)0 /* frameCount */,
3505 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003506 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003507 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003508 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003509 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003510 TYPE_DEFAULT, portId,
3511 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003512 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003513 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003514{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003515 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003516 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003517}
3518
Andy Hung3ff4b552023-06-26 19:20:57 -07003519MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003520{
3521}
3522
Andy Hung3ff4b552023-06-26 19:20:57 -07003523status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003524{
3525 return NO_ERROR;
3526}
3527
Andy Hung3ff4b552023-06-26 19:20:57 -07003528status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003529 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003530{
3531 return NO_ERROR;
3532}
3533
Andy Hung3ff4b552023-06-26 19:20:57 -07003534void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003535{
3536}
3537
3538// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003539status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003540{
3541 buffer->frameCount = 0;
3542 buffer->raw = nullptr;
3543 return INVALID_OPERATION;
3544}
3545
3546// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003547size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003548 return 0;
3549}
3550
Andy Hung3ff4b552023-06-26 19:20:57 -07003551int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003552{
3553 return 0;
3554}
3555
Andy Hung3ff4b552023-06-26 19:20:57 -07003556void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003557{
3558}
3559
Andy Hung3ff4b552023-06-26 19:20:57 -07003560void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003561{
3562 if (mMuteState == muteState) {
3563 // mute state did not change, do nothing
3564 return;
3565 }
3566
3567 status_t result = UNKNOWN_ERROR;
3568 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3569 if (mMuteEventExtras == nullptr) {
3570 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3571 }
3572 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3573 static_cast<int>(muteState));
3574
3575 result = audioManager->portEvent(mPortId,
3576 PLAYER_UPDATE_MUTED,
3577 mMuteEventExtras);
3578 }
3579
3580 if (result == OK) {
Andy Hung6fb26892024-02-20 16:32:57 -08003581 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
3582 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popaec1788e2022-08-04 11:23:30 +02003583 mMuteState = muteState;
3584 } else {
3585 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3586 __func__,
3587 id(),
3588 mPortId,
3589 result);
3590 }
3591}
3592
Andy Hung3ff4b552023-06-26 19:20:57 -07003593void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003594{
Eric Laurent973db022018-11-20 14:54:31 -08003595 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003596 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003597}
3598
Andy Hung3ff4b552023-06-26 19:20:57 -07003599void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003600{
Eric Laurent973db022018-11-20 14:54:31 -08003601 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003602 mPid,
3603 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003604 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003605 mFormat,
3606 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003607 mSampleRate,
3608 mAttr.flags);
3609 if (isOut()) {
3610 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3611 } else {
3612 result.appendFormat("%6x", mAttr.source);
3613 }
3614 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003615}
3616
Glenn Kasten63238ef2015-03-02 15:50:29 -08003617} // namespace android