blob: a34f6d74544b54641b994fd4ad4932bb52090f4f [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 Hung3ff4b552023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung837229a2023-07-14 16:57:01 -0700318 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
Andy Hung837229a2023-07-14 16:57:01 -0700325 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
326 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung3ff4b552023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hungaaa18282023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hungaaa18282023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hungaaa18282023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hungaaa18282023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hung02a6c4e2023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hung225aef62022-12-06 16:33:20 -0800391 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hungf2b4a182024-03-26 18:04:29 -0700392 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -0800393}
394
Andy Hungaaa18282023-06-23 19:27:19 -0700395TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800396 // just stop the track on deletion, associated resources
397 // will be freed from the main thread once all pending buffers have
398 // been played. Unless it's not in the active track list, in which
399 // case we free everything now...
400 mTrack->destroy();
401}
402
Andy Hungaaa18282023-06-23 19:27:19 -0700403Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800404 std::optional<media::SharedFileRegion>* _aidl_return) {
405 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
406 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800407}
408
Andy Hungaaa18282023-06-23 19:27:19 -0700409Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800410 *_aidl_return = mTrack->start();
411 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800412}
413
Andy Hungaaa18282023-06-23 19:27:19 -0700414Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800415 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800416 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800417}
418
Andy Hungaaa18282023-06-23 19:27:19 -0700419Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800420 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800422}
423
Andy Hungaaa18282023-06-23 19:27:19 -0700424Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800425 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800426 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800427}
428
Andy Hungaaa18282023-06-23 19:27:19 -0700429Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800430 int32_t* _aidl_return) {
431 *_aidl_return = mTrack->attachAuxEffect(effectId);
432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hungaaa18282023-06-23 19:27:19 -0700435Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800436 int32_t* _aidl_return) {
437 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
438 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700439}
440
Andy Hungaaa18282023-06-23 19:27:19 -0700441Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800442 int32_t* _aidl_return) {
443 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
444 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800445}
446
Andy Hungaaa18282023-06-23 19:27:19 -0700447Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800448 int32_t* _aidl_return) {
449 AudioTimestamp legacy;
450 *_aidl_return = mTrack->getTimestamp(legacy);
451 if (*_aidl_return != OK) {
452 return Status::ok();
453 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000454
455 // restrict position modulo INT_MAX to avoid integer sanitization abort
456 legacy.mPosition &= INT_MAX;
457
Andy Hung973638a2020-12-08 20:47:45 -0800458 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800460}
461
Andy Hungaaa18282023-06-23 19:27:19 -0700462Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800463 mTrack->signal();
464 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800465}
466
Andy Hungaaa18282023-06-23 19:27:19 -0700467Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800468 const media::VolumeShaperConfiguration& configuration,
469 const media::VolumeShaperOperation& operation,
470 int32_t* _aidl_return) {
471 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
472 *_aidl_return = conf->readFromParcelable(configuration);
473 if (*_aidl_return != OK) {
474 return Status::ok();
475 }
476
477 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
478 *_aidl_return = op->readFromParcelable(operation);
479 if (*_aidl_return != OK) {
480 return Status::ok();
481 }
482
483 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
484 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700485}
486
Andy Hungaaa18282023-06-23 19:27:19 -0700487Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800488 int32_t id,
489 std::optional<media::VolumeShaperState>* _aidl_return) {
490 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
491 if (legacy == nullptr) {
492 _aidl_return->reset();
493 return Status::ok();
494 }
495 media::VolumeShaperState aidl;
496 legacy->writeToParcelable(&aidl);
497 *_aidl_return = aidl;
498 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800499}
500
Andy Hungaaa18282023-06-23 19:27:19 -0700501Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000502 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800503{
504 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
505 const status_t status = mTrack->getDualMonoMode(&mode)
506 ?: AudioValidator::validateDualMonoMode(mode);
507 if (status == OK) {
508 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
509 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
510 }
511 return binderStatusFromStatusT(status);
512}
513
Andy Hungaaa18282023-06-23 19:27:19 -0700514Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000515 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800516{
517 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
518 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
519 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
520 ?: mTrack->setDualMonoMode(localMonoMode));
521}
522
Andy Hungaaa18282023-06-23 19:27:19 -0700523Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800524{
525 float leveldB = -std::numeric_limits<float>::infinity();
526 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
527 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
528 if (status == OK) *_aidl_return = leveldB;
529 return binderStatusFromStatusT(status);
530}
531
Andy Hungaaa18282023-06-23 19:27:19 -0700532Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800533{
534 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
535 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
536}
537
Andy Hungaaa18282023-06-23 19:27:19 -0700538Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000539 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800540{
541 audio_playback_rate_t localPlaybackRate{};
542 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
543 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
544 if (status == NO_ERROR) {
545 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
546 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
547 }
548 return binderStatusFromStatusT(status);
549}
550
Andy Hungaaa18282023-06-23 19:27:19 -0700551Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000552 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800553{
554 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
555 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
556 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
557 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
558}
559
Eric Laurent81784c32012-11-19 14:55:58 -0800560// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800561// AppOp for audio playback
562// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700563
564// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700565sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung44f27182023-07-06 20:56:16 -0700566 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000567 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700568 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800569{
Vlad Popa103be862023-07-10 20:27:41 -0700570 Vector<String16> packages;
571 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000572 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700573 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700574 if (packages.isEmpty()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000575 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700576 uid);
577 return nullptr;
578 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800579 }
580 // stream type has been filtered by audio policy to indicate whether it can be muted
581 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700582 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700583 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800584 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700585 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
586 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
587 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
588 id, attr.flags);
589 return nullptr;
590 }
Vlad Popa103be862023-07-10 20:27:41 -0700591 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700592}
593
Andy Hung44f27182023-07-06 20:56:16 -0700594OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
595 const AttributionSourceState& attributionSource,
596 audio_usage_t usage, int id, uid_t uid)
597 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa103be862023-07-10 20:27:41 -0700598 mHasOpPlayAudio(true),
Vlad Popa103be862023-07-10 20:27:41 -0700599 mUsage((int32_t)usage),
600 mId(id),
601 mUid(uid),
602 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
603 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800604
Andy Hung3ff4b552023-06-26 19:20:57 -0700605OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800606{
607 if (mOpCallback != 0) {
608 mAppOpsManager.stopWatchingMode(mOpCallback);
609 }
610 mOpCallback.clear();
611}
612
Andy Hung3ff4b552023-06-26 19:20:57 -0700613void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700614{
Vlad Popad2152122023-08-02 18:36:04 -0700615 // make sure not to broadcast the initial state since it is not needed and could
616 // cause a deadlock since this method can be called with the mThread->mLock held
617 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000618 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700619 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000620 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
621 } else {
622 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700623 }
624}
625
Andy Hung3ff4b552023-06-26 19:20:57 -0700626bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800627 return mHasOpPlayAudio.load();
628}
629
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700630// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800631// - not called from constructor due to check on UID,
632// - not called from PlayAudioOpCallback because the callback is not installed in this case
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000633void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
634 const bool hasAppOps =
635 mPackageName.size() &&
636 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
637 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa103be862023-07-10 20:27:41 -0700638
639 bool shouldChange = !hasAppOps; // check if we need to update.
640 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000641 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000642 String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
Vlad Popad2152122023-08-02 18:36:04 -0700643 if (doBroadcast) {
644 auto thread = mThread.promote();
Andy Hung71742ab2023-07-07 13:47:37 -0700645 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popad2152122023-08-02 18:36:04 -0700646 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87e82412023-08-29 14:26:09 -0700647 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad2152122023-08-02 18:36:04 -0700648 thread->broadcast_l();
649 }
Vlad Popa103be862023-07-10 20:27:41 -0700650 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800651 }
652}
653
Andy Hung3ff4b552023-06-26 19:20:57 -0700654OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800655 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
656{ }
657
Andy Hung3ff4b552023-06-26 19:20:57 -0700658void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800659 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800660 if (op != AppOpsManager::OP_PLAY_AUDIO) {
661 return;
662 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000663
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000664 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800665 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
666 if (monitor != NULL) {
Vlad Popad2152122023-08-02 18:36:04 -0700667 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800668 }
669}
670
Eric Laurent9066ad32019-05-20 14:40:10 -0700671// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700672void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700673 uid_t uid, Vector<String16>& packages)
674{
675 PermissionController permissionController;
676 permissionController.getPackagesForUid(uid, packages);
677}
678
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800679// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700680#undef LOG_TAG
681#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800682
Andy Hung3ff4b552023-06-26 19:20:57 -0700683/* static */
Andy Hung44f27182023-07-06 20:56:16 -0700684sp<IAfTrack> IAfTrack::create(
685 IAfPlaybackThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700686 const sp<Client>& client,
687 audio_stream_type_t streamType,
688 const audio_attributes_t& attr,
689 uint32_t sampleRate,
690 audio_format_t format,
691 audio_channel_mask_t channelMask,
692 size_t frameCount,
693 void *buffer,
694 size_t bufferSize,
695 const sp<IMemory>& sharedBuffer,
696 audio_session_t sessionId,
697 pid_t creatorPid,
698 const AttributionSourceState& attributionSource,
699 audio_output_flags_t flags,
700 track_type type,
701 audio_port_handle_t portId,
702 /** default behaviour is to start when there are as many frames
703 * ready as possible (aka. Buffer is full). */
704 size_t frameCountToBeReady,
705 float speed,
706 bool isSpatialized,
707 bool isBitPerfect) {
Andy Hung44f27182023-07-06 20:56:16 -0700708 return sp<Track>::make(thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700709 client,
710 streamType,
711 attr,
712 sampleRate,
713 format,
714 channelMask,
715 frameCount,
716 buffer,
717 bufferSize,
718 sharedBuffer,
719 sessionId,
720 creatorPid,
721 attributionSource,
722 flags,
723 type,
724 portId,
725 frameCountToBeReady,
726 speed,
727 isSpatialized,
728 isBitPerfect);
729}
730
Eric Laurent81784c32012-11-19 14:55:58 -0800731// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -0700732Track::Track(
Andy Hung44f27182023-07-06 20:56:16 -0700733 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800734 const sp<Client>& client,
735 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700736 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800737 uint32_t sampleRate,
738 audio_format_t format,
739 audio_channel_mask_t channelMask,
740 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700741 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700742 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800743 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800744 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700745 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000746 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700747 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800748 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100749 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000750 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200751 float speed,
jiabinc658e452022-10-21 20:52:21 +0000752 bool isSpatialized,
753 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700754 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700755 // TODO: Using unsecurePointer() has some associated security pitfalls
756 // (see declaration for details).
757 // Either document why it is safe in this case or address the
758 // issue (e.g. by copying).
759 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700760 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700761 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000762 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700763 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800764 type,
765 portId,
766 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung3ff4b552023-06-26 19:20:57 -0700767 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800768 // mRetryCount initialized later when needed
769 mSharedBuffer(sharedBuffer),
770 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700771 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800772 mAuxBuffer(NULL),
773 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700774 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700775 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa103be862023-07-10 20:27:41 -0700776 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700777 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700778 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800779 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800780 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700781 /* The track might not play immediately after being active, similarly as if its volume was 0.
782 * When the track starts playing, its volume will be computed. */
783 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800784 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700785 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000786 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200787 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000788 mIsSpatialized(isSpatialized),
789 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800790{
Eric Laurent83b88082014-06-20 18:31:16 -0700791 // client == 0 implies sharedBuffer == 0
792 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
793
Andy Hung9d84af52018-09-12 18:03:44 -0700794 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700795 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700796
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700797 if (mCblk == NULL) {
798 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800799 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700800
Svet Ganov33761132021-05-13 22:51:08 +0000801 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700802 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
803 ALOGE("%s(%d): no more tracks available", __func__, mId);
804 releaseCblk(); // this makes the track invalid.
805 return;
806 }
807
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700808 if (sharedBuffer == 0) {
809 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700810 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700811 } else {
812 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100813 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700814 }
815 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700816 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700817
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700818 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700819 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700820 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
821 // race with setSyncEvent(). However, if we call it, we cannot properly start
822 // static fast tracks (SoundPool) immediately after stopping.
823 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung44f27182023-07-06 20:56:16 -0700824 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
825 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700826 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700827 // FIXME This is too eager. We allocate a fast track index before the
828 // fast track becomes active. Since fast tracks are a scarce resource,
829 // this means we are potentially denying other more important fast tracks from
830 // being created. It would be better to allocate the index dynamically.
831 mFastIndex = i;
Andy Hung44f27182023-07-06 20:56:16 -0700832 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700833 }
Andy Hung8946a282018-04-19 20:04:56 -0700834
Dean Wheatley7b036912020-06-18 16:22:11 +1000835 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700836#ifdef TEE_SINK
837 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800838 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700839#endif
jiabin57303cc2018-12-18 15:45:57 -0800840
jiabineb3bda02020-06-30 14:07:03 -0700841 if (thread->supportsHapticPlayback()) {
842 // If the track is attached to haptic playback thread, it is potentially to have
843 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
844 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800845 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000846 std::string packageName = attributionSource.packageName.has_value() ?
847 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800848 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700849 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800850 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800851
852 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700853 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800854 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800855}
856
Andy Hung3ff4b552023-06-26 19:20:57 -0700857Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800858{
Andy Hung9d84af52018-09-12 18:03:44 -0700859 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700860
861 // The destructor would clear mSharedBuffer,
862 // but it will not push the decremented reference count,
863 // leaving the client's IMemory dangling indefinitely.
864 // This prevents that leak.
865 if (mSharedBuffer != 0) {
866 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700867 }
Eric Laurent81784c32012-11-19 14:55:58 -0800868}
869
Andy Hung3ff4b552023-06-26 19:20:57 -0700870status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700871{
872 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700873 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700874 status = NO_MEMORY;
875 }
876 return status;
877}
878
Andy Hung3ff4b552023-06-26 19:20:57 -0700879void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800880{
881 // NOTE: destroyTrack_l() can remove a strong reference to this Track
882 // by removing it from mTracks vector, so there is a risk that this Tracks's
883 // destructor is called. As the destructor needs to lock mLock,
884 // we must acquire a strong reference on this Track before locking mLock
885 // here so that the destructor is called only when exiting this function.
886 // On the other hand, as long as Track::destroy() is only called by
887 // TrackHandle destructor, the TrackHandle still holds a strong ref on
888 // this Track with its member mTrack.
889 sp<Track> keep(this);
890 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700891 bool wasActive = false;
Andy Hung44f27182023-07-06 20:56:16 -0700892 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800893 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -0800894 audio_utils::unique_lock ul(thread->mutex());
895 thread->waitWhileThreadBusy_l(ul);
896
Andy Hung44f27182023-07-06 20:56:16 -0700897 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700898 wasActive = playbackThread->destroyTrack_l(this);
jiabin6e506fc2023-06-27 18:22:35 +0000899 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700900 }
901 if (isExternalTrack() && !wasActive) {
Andy Hunga7187712023-12-05 17:28:17 -0800902 // If the track is not active, the TrackHandle is responsible for
903 // releasing the port id, not the ThreadBase::threadLoop().
904 // At this point, there is no concurrency issue as the track is going away.
Eric Laurentd7fe0862018-07-14 16:48:01 -0700905 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800906 }
907 }
908}
909
Andy Hung3ff4b552023-06-26 19:20:57 -0700910void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800911{
Eric Laurent973db022018-11-20 14:54:31 -0800912 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700913 " Format Chn mask SRate "
914 "ST Usg CT "
915 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000916 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700917 "%s\n",
918 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800919}
920
Andy Hung3ff4b552023-06-26 19:20:57 -0700921void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800922{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700923 char trackType;
924 switch (mType) {
925 case TYPE_DEFAULT:
926 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700927 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700928 trackType = 'S'; // static
929 } else {
930 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800931 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700932 break;
933 case TYPE_PATCH:
934 trackType = 'P';
935 break;
936 default:
937 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800938 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700939
940 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700941 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700942 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700943 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700944 }
945
Eric Laurent81784c32012-11-19 14:55:58 -0800946 char nowInUnderrun;
947 switch (mObservedUnderruns.mBitFields.mMostRecent) {
948 case UNDERRUN_FULL:
949 nowInUnderrun = ' ';
950 break;
951 case UNDERRUN_PARTIAL:
952 nowInUnderrun = '<';
953 break;
954 case UNDERRUN_EMPTY:
955 nowInUnderrun = '*';
956 break;
957 default:
958 nowInUnderrun = '?';
959 break;
960 }
Andy Hungda540db2017-04-20 14:06:17 -0700961
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700962 char fillingStatus;
Andy Hung3ff4b552023-06-26 19:20:57 -0700963 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700964 case FS_INVALID:
965 fillingStatus = 'I';
966 break;
967 case FS_FILLING:
968 fillingStatus = 'f';
969 break;
970 case FS_FILLED:
971 fillingStatus = 'F';
972 break;
973 case FS_ACTIVE:
974 fillingStatus = 'A';
975 break;
976 default:
977 fillingStatus = '?';
978 break;
979 }
980
981 // clip framesReadySafe to max representation in dump
982 const size_t framesReadySafe =
983 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
984
985 // obtain volumes
986 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
987 const std::pair<float /* volume */, bool /* active */> vsVolume =
988 mVolumeHandler->getLastVolume();
989
990 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
991 // as it may be reduced by the application.
992 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
993 // Check whether the buffer size has been modified by the app.
994 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
995 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
996 ? 'e' /* error */ : ' ' /* identical */;
997
Eric Laurent973db022018-11-20 14:54:31 -0800998 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700999 "%08X %08X %6u "
1000 "%2u %3x %2x "
1001 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +00001002 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -08001003 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001004 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001005 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001006 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001007 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001008 mCblk->mFlags,
1009
Eric Laurent81784c32012-11-19 14:55:58 -08001010 mFormat,
1011 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001012 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001013
1014 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001015 mAttr.usage,
1016 mAttr.content_type,
1017
1018 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001019 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1020 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001021 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1022 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001023
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001024 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001025 bufferSizeInFrames,
1026 modifiedBufferChar,
1027 framesReadySafe,
1028 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001029 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001030 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001031 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1032 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001033 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001034
1035 if (isServerLatencySupported()) {
1036 double latencyMs;
1037 bool fromTrack;
1038 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1039 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1040 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1041 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001042 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001043 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001044 }
1045 }
1046 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001047}
1048
Andy Hung3ff4b552023-06-26 19:20:57 -07001049uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001050 return mAudioTrackServerProxy->getSampleRate();
1051}
1052
Eric Laurent81784c32012-11-19 14:55:58 -08001053// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001054status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001055{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001056 ServerProxy::Buffer buf;
1057 size_t desiredFrames = buffer->frameCount;
1058 buf.mFrameCount = desiredFrames;
1059 status_t status = mServerProxy->obtainBuffer(&buf);
1060 buffer->frameCount = buf.mFrameCount;
1061 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001062 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001063 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001064 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001065 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001066 } else {
1067 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001068 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001069 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001070}
1071
Andy Hung3ff4b552023-06-26 19:20:57 -07001072void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001073{
1074 interceptBuffer(*buffer);
1075 TrackBase::releaseBuffer(buffer);
1076}
1077
1078// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001079void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001080 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001081 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001082 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001083 if (frameCount == 0) {
1084 return; // No audio to intercept.
1085 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1086 // does not allow 0 frame size request contrary to getNextBuffer
1087 }
Jiabin Huang98b8d452024-01-04 18:42:55 +00001088 TeePatches teePatches;
1089 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1090 // Cache a copy of tee patches in case it is updated while using.
1091 teePatches = mTeePatches;
1092 mTeePatchesRWLock.unlock();
1093 }
1094 for (auto& teePatch : teePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001095 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001096 const size_t framesWritten = patchRecord->writeFrames(
1097 sourceBuffer.i8, frameCount, mFrameSize);
1098 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001099 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001100 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001101 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001102 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001103 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1104 using namespace std::chrono_literals;
1105 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001106 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang98b8d452024-01-04 18:42:55 +00001107 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001108}
1109
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001110// ExtendedAudioBufferProvider interface
1111
Andy Hung27876c02014-09-09 18:07:55 -07001112// framesReady() may return an approximation of the number of frames if called
1113// from a different thread than the one calling Proxy->obtainBuffer() and
1114// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1115// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001116size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001117 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1118 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1119 // The remainder of the buffer is not drained.
1120 return 0;
1121 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001122 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001123}
1124
Andy Hung3ff4b552023-06-26 19:20:57 -07001125int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001126{
1127 return mAudioTrackServerProxy->framesReleased();
1128}
1129
Andy Hung3ff4b552023-06-26 19:20:57 -07001130void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001131{
1132 // This call comes from a FastTrack and should be kept lockless.
1133 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001134 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001135
Andy Hung818e7a32016-02-16 18:08:07 -08001136 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001137
1138 // Compute latency.
1139 // TODO: Consider whether the server latency may be passed in by FastMixer
1140 // as a constant for all active FastTracks.
1141 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1142 mServerLatencyFromTrack.store(true);
1143 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001144}
1145
Eric Laurent81784c32012-11-19 14:55:58 -08001146// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001147bool Track::isReady() const {
1148 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001149 return true;
1150 }
1151
Eric Laurent16498512014-03-17 17:22:08 -07001152 if (isStopping()) {
1153 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001154 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001155 }
Eric Laurent81784c32012-11-19 14:55:58 -08001156 return true;
1157 }
1158
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001159 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001160 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1161 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1162 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1163 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001164
1165 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1166 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1167 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001168 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001169 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001170 return true;
1171 }
1172 return false;
1173}
1174
Andy Hung3ff4b552023-06-26 19:20:57 -07001175status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001176 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001177{
1178 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001179 ALOGV("%s(%d): calling pid %d session %d",
1180 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001181
Andy Hung44f27182023-07-06 20:56:16 -07001182 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001183 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001184 if (isOffloaded()) {
Andy Hung2ac52f12023-08-28 18:36:53 -07001185 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hung94dfbb42023-09-06 19:41:47 -07001186 const bool nonOffloadableGlobalEffectEnabled =
1187 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hung87e82412023-08-29 14:26:09 -07001188 audio_utils::lock_guard _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001189 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung94dfbb42023-09-06 19:41:47 -07001190 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001191 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001192 invalidate();
1193 return PERMISSION_DENIED;
1194 }
1195 }
Andy Hunga7187712023-12-05 17:28:17 -08001196 audio_utils::unique_lock ul(thread->mutex());
1197 thread->waitWhileThreadBusy_l(ul);
1198
Eric Laurent81784c32012-11-19 14:55:58 -08001199 track_state state = mState;
1200 // here the track could be either new, or restarted
1201 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001202
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001203 // initial state-stopping. next state-pausing.
1204 // What if resume is called ?
1205
Zhou Song1ed46a22020-08-17 15:36:56 +08001206 if (state == FLUSHED) {
1207 // avoid underrun glitches when starting after flush
1208 reset();
1209 }
1210
kuowei.li576f1362021-05-11 18:02:32 +08001211 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1212 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001213 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001214 if (mResumeToStopping) {
1215 // happened we need to resume to STOPPING_1
1216 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001217 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1218 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001219 } else {
1220 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001221 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1222 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001223 }
Eric Laurent81784c32012-11-19 14:55:58 -08001224 } else {
1225 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001226 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1227 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001228 }
1229
Andy Hung44f27182023-07-06 20:56:16 -07001230 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001231
1232 // states to reset position info for pcm tracks
1233 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001234 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1235 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001236
1237 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1238 // Start point of track -> sink frame map. If the HAL returns a
1239 // frame position smaller than the first written frame in
1240 // updateTrackFrameInfo, the timestamp can be interpolated
1241 // instead of using a larger value.
1242 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1243 playbackThread->framesWritten());
1244 }
Andy Hunge10393e2015-06-12 13:59:33 -07001245 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001246 if (isFastTrack()) {
1247 // refresh fast track underruns on start because that field is never cleared
1248 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1249 // after stop.
1250 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1251 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001252 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001253 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001254 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001255 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001256 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001257 mState = state;
1258 }
1259 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001260
Andy Hungb68f5eb2019-12-03 16:49:17 -08001261 // Audio timing metrics are computed a few mix cycles after starting.
1262 {
1263 mLogStartCountdown = LOG_START_COUNTDOWN;
1264 mLogStartTimeNs = systemTime();
1265 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001266 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1267 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001268 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001269 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001270
Andy Hung1d3556d2018-03-29 16:30:14 -07001271 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1272 // for streaming tracks, remove the buffer read stop limit.
1273 mAudioTrackServerProxy->start();
1274 }
1275
Eric Laurentbfb1b832013-01-07 09:53:42 -08001276 // track was already in the active list, not a problem
1277 if (status == ALREADY_EXISTS) {
1278 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001279 } else {
1280 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1281 // It is usually unsafe to access the server proxy from a binder thread.
1282 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1283 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1284 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001285 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001286 ServerProxy::Buffer buffer;
1287 buffer.mFrameCount = 1;
1288 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001289 }
jiabin6e506fc2023-06-27 18:22:35 +00001290 if (status == NO_ERROR) {
1291 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1292 }
Eric Laurent81784c32012-11-19 14:55:58 -08001293 } else {
1294 status = BAD_VALUE;
1295 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001296 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001297 // send format to AudioManager for playback activity monitoring
Andy Hung2cbc2722023-07-17 17:05:00 -07001298 const sp<IAudioManager> audioManager =
1299 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001300 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1301 std::unique_ptr<os::PersistableBundle> bundle =
1302 std::make_unique<os::PersistableBundle>();
1303 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1304 isSpatialized());
1305 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1306 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1307 status_t result = audioManager->portEvent(mPortId,
1308 PLAYER_UPDATE_FORMAT, bundle);
1309 if (result != OK) {
1310 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1311 __func__, mPortId, result);
1312 }
1313 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001314 }
Eric Laurent81784c32012-11-19 14:55:58 -08001315 return status;
1316}
1317
Andy Hung3ff4b552023-06-26 19:20:57 -07001318void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001319{
Andy Hungc0691382018-09-12 18:01:57 -07001320 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001321 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001322 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -08001323 audio_utils::unique_lock ul(thread->mutex());
1324 thread->waitWhileThreadBusy_l(ul);
1325
Eric Laurent81784c32012-11-19 14:55:58 -08001326 track_state state = mState;
1327 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1328 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001329 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1330 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001331 reset();
1332 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001333 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1334 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1335 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001336 mState = STOPPED;
1337 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001338 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1339 // presentation is complete
1340 // For an offloaded track this starts a drain and state will
1341 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001342 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001343 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001344 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001345 }
Eric Laurent81784c32012-11-19 14:55:58 -08001346 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001347 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001348 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1349 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001350 }
jiabin6e506fc2023-06-27 18:22:35 +00001351 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001352 }
1353}
1354
Andy Hung3ff4b552023-06-26 19:20:57 -07001355void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001356{
Andy Hungc0691382018-09-12 18:01:57 -07001357 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001358 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001359 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -08001360 audio_utils::unique_lock ul(thread->mutex());
1361 thread->waitWhileThreadBusy_l(ul);
1362
Andy Hung44f27182023-07-06 20:56:16 -07001363 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001364 switch (mState) {
1365 case STOPPING_1:
1366 case STOPPING_2:
1367 if (!isOffloaded()) {
1368 /* nothing to do if track is not offloaded */
1369 break;
1370 }
1371
1372 // Offloaded track was draining, we need to carry on draining when resumed
1373 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001374 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001375 case ACTIVE:
1376 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001377 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001378 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1379 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001380 if (isOffloadedOrDirect()) {
1381 mPauseHwPending = true;
1382 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001383 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001384 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001385
Eric Laurentbfb1b832013-01-07 09:53:42 -08001386 default:
1387 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001388 }
jiabin6e506fc2023-06-27 18:22:35 +00001389 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1390 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001391 }
1392}
1393
Andy Hung3ff4b552023-06-26 19:20:57 -07001394void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001395{
Andy Hungc0691382018-09-12 18:01:57 -07001396 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001397 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001398 if (thread != 0) {
Andy Hunga7187712023-12-05 17:28:17 -08001399 audio_utils::unique_lock ul(thread->mutex());
1400 thread->waitWhileThreadBusy_l(ul);
1401
Andy Hung44f27182023-07-06 20:56:16 -07001402 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001403
Phil Burk4bb650b2016-09-09 12:11:17 -07001404 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1405 // Otherwise the flush would not be done until the track is resumed.
1406 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001407 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001408 (void)mServerProxy->flushBufferIfNeeded();
1409 }
1410
Eric Laurentbfb1b832013-01-07 09:53:42 -08001411 if (isOffloaded()) {
1412 // If offloaded we allow flush during any state except terminated
1413 // and keep the track active to avoid problems if user is seeking
1414 // rapidly and underlying hardware has a significant delay handling
1415 // a pause
1416 if (isTerminated()) {
1417 return;
1418 }
1419
Andy Hung9d84af52018-09-12 18:03:44 -07001420 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001421 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001422
1423 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001424 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1425 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001426 mState = ACTIVE;
1427 }
1428
Haynes Mathew George7844f672014-01-15 12:32:55 -08001429 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001430 mResumeToStopping = false;
1431 } else {
1432 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1433 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1434 return;
1435 }
1436 // No point remaining in PAUSED state after a flush => go to
1437 // FLUSHED state
1438 mState = FLUSHED;
1439 // do not reset the track if it is still in the process of being stopped or paused.
1440 // this will be done by prepareTracks_l() when the track is stopped.
1441 // prepareTracks_l() will see mState == FLUSHED, then
1442 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001443 if (isDirect()) {
1444 mFlushHwPending = true;
1445 }
Andy Hung44f27182023-07-06 20:56:16 -07001446 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001447 reset();
1448 }
Eric Laurent81784c32012-11-19 14:55:58 -08001449 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001450 // Prevent flush being lost if the track is flushed and then resumed
1451 // before mixer thread can run. This is important when offloading
1452 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001453 playbackThread->broadcast_l();
jiabin6e506fc2023-06-27 18:22:35 +00001454 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1455 // new data
1456 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001457 }
1458}
1459
Haynes Mathew George7844f672014-01-15 12:32:55 -08001460// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001461void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001462{
Andy Hung71ba4b32022-10-06 12:09:49 -07001463 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001464 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001465 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001466
Phil Burk4bb650b2016-09-09 12:11:17 -07001467 // Clear the client ring buffer so that the app can prime the buffer while paused.
1468 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1469 mServerProxy->flushBufferIfNeeded();
1470
Haynes Mathew George7844f672014-01-15 12:32:55 -08001471 mFlushHwPending = false;
1472}
1473
Andy Hung3ff4b552023-06-26 19:20:57 -07001474void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001475{
1476 mPauseHwPending = false;
1477}
1478
Andy Hung3ff4b552023-06-26 19:20:57 -07001479void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001480{
1481 // Do not reset twice to avoid discarding data written just after a flush and before
1482 // the audioflinger thread detects the track is stopped.
1483 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001484 // Force underrun condition to avoid false underrun callback until first data is
1485 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001486 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001487 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001488 mResetDone = true;
1489 if (mState == FLUSHED) {
1490 mState = IDLE;
1491 }
1492 }
1493}
1494
Andy Hung3ff4b552023-06-26 19:20:57 -07001495status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001496{
Andy Hung44f27182023-07-06 20:56:16 -07001497 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001498 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001499 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001500 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001501 } else if (thread->type() == IAfThreadBase::DIRECT
1502 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001503 return thread->setParameters(keyValuePairs);
1504 } else {
1505 return PERMISSION_DENIED;
1506 }
1507}
1508
Andy Hung3ff4b552023-06-26 19:20:57 -07001509status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001510 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001511 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001512 if (thread == 0) {
1513 ALOGE("thread is dead");
1514 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001515 } else if (thread->type() == IAfThreadBase::DIRECT
1516 || thread->type() == IAfThreadBase::OFFLOAD) {
1517 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001518 return directOutputThread->selectPresentation(presentationId, programId);
1519 }
1520 return INVALID_OPERATION;
1521}
1522
Andy Hung3ff4b552023-06-26 19:20:57 -07001523VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001524 const sp<VolumeShaper::Configuration>& configuration,
1525 const sp<VolumeShaper::Operation>& operation)
1526{
Andy Hungee86cee2022-12-13 19:19:53 -08001527 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001528
1529 if (isOffloadedOrDirect()) {
1530 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001531 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001532 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001533 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001534 thread->broadcast_l();
1535 }
1536 }
1537 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001538}
1539
Andy Hung3ff4b552023-06-26 19:20:57 -07001540sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001541{
1542 // Note: We don't check if Thread exists.
1543
1544 // mVolumeHandler is thread safe.
1545 return mVolumeHandler->getVolumeShaperState(id);
1546}
1547
Andy Hung3ff4b552023-06-26 19:20:57 -07001548void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001549{
jiabin76d94692022-12-15 21:51:21 +00001550 mFinalVolumeLeft = volumeLeft;
1551 mFinalVolumeRight = volumeRight;
1552 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001553 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1554 mFinalVolume = volume;
1555 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001556 mLogForceVolumeUpdate = true;
1557 }
1558 if (mLogForceVolumeUpdate) {
1559 mLogForceVolumeUpdate = false;
1560 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001561 }
1562}
1563
Andy Hung3ff4b552023-06-26 19:20:57 -07001564void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001565{
Eric Laurent49e39282022-06-24 18:42:45 +02001566 // Do not forward metadata for PatchTrack with unspecified stream type
1567 if (mStreamType == AUDIO_STREAM_PATCH) {
1568 return;
1569 }
1570
Eric Laurent94579172020-11-20 18:41:04 +01001571 playback_track_metadata_v7_t metadata;
1572 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001573 .usage = mAttr.usage,
1574 .content_type = mAttr.content_type,
1575 .gain = mFinalVolume,
1576 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001577
1578 // When attributes are undefined, derive default values from stream type.
1579 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1580 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1581 switch (mStreamType) {
1582 case AUDIO_STREAM_VOICE_CALL:
1583 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1584 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1585 break;
1586 case AUDIO_STREAM_SYSTEM:
1587 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1588 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1589 break;
1590 case AUDIO_STREAM_RING:
1591 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1592 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1593 break;
1594 case AUDIO_STREAM_MUSIC:
1595 metadata.base.usage = AUDIO_USAGE_MEDIA;
1596 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1597 break;
1598 case AUDIO_STREAM_ALARM:
1599 metadata.base.usage = AUDIO_USAGE_ALARM;
1600 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1601 break;
1602 case AUDIO_STREAM_NOTIFICATION:
1603 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1604 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1605 break;
1606 case AUDIO_STREAM_DTMF:
1607 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1608 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1609 break;
1610 case AUDIO_STREAM_ACCESSIBILITY:
1611 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1612 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1613 break;
1614 case AUDIO_STREAM_ASSISTANT:
1615 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1616 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1617 break;
1618 case AUDIO_STREAM_REROUTING:
1619 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1620 // unknown content type
1621 break;
1622 case AUDIO_STREAM_CALL_ASSISTANT:
1623 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1624 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1625 break;
1626 default:
1627 break;
1628 }
1629 }
1630
Eric Laurent78b07302022-10-07 16:20:34 +02001631 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001632 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1633 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001634}
1635
jiabin6e506fc2023-06-27 18:22:35 +00001636void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001637 if (mTeePatchesToUpdate.has_value()) {
jiabin6e506fc2023-06-27 18:22:35 +00001638 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang98b8d452024-01-04 18:42:55 +00001639 {
1640 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1641 mTeePatches = std::move(mTeePatchesToUpdate.value());
1642 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001643 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1644 mState == TrackBase::STOPPING_1) {
jiabin6e506fc2023-06-27 18:22:35 +00001645 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001646 }
1647 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001648 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001649}
1650
jiabin6e506fc2023-06-27 18:22:35 +00001651void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001652 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1653 "%s, existing tee patches to update will be ignored", __func__);
1654 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1655}
1656
Vlad Popae8d99472022-06-30 16:02:48 +02001657// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001658void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001659 IAudioManager>& audioManager, mute_state_t muteState)
1660{
1661 if (mMuteState == muteState) {
1662 // mute state did not change, do nothing
1663 return;
1664 }
1665
1666 status_t result = UNKNOWN_ERROR;
1667 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1668 if (mMuteEventExtras == nullptr) {
1669 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1670 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001671 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001672
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001673 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001674 }
1675
1676 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001677 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
Andy Hung6fb26892024-02-20 16:32:57 -08001678 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001679 mMuteState = muteState;
1680 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001681 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1682 mPortId, result);
Andy Hung818e7a32016-02-16 18:08:07 -08001683 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001684}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001685
Andy Hung3ff4b552023-06-26 19:20:57 -07001686status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001687{
1688 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001689 return INVALID_OPERATION; // normal tracks handled through SSQ
1690 }
Andy Hung44f27182023-07-06 20:56:16 -07001691 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001692 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001693 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001694 }
Phil Burk6140c792015-03-19 14:30:21 -07001695
Andy Hung87e82412023-08-29 14:26:09 -07001696 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001697 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001698 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001699}
1700
Andy Hung3ff4b552023-06-26 19:20:57 -07001701status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001702{
Andy Hung44f27182023-07-06 20:56:16 -07001703 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001704 if (thread == nullptr) {
1705 return DEAD_OBJECT;
1706 }
Eric Laurent81784c32012-11-19 14:55:58 -08001707
Andy Hung44f27182023-07-06 20:56:16 -07001708 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001709 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001710 sp<IAfPlaybackThread> srcThread;
Andy Hungfa2f4f32023-07-17 12:40:43 -07001711 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001712 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001713
Eric Laurent6c796322019-04-09 14:13:17 -07001714 if (EffectId != 0 && status == NO_ERROR) {
1715 status = dstThread->attachAuxEffect(this, EffectId);
1716 if (status == NO_ERROR) {
1717 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001718 }
Eric Laurent6c796322019-04-09 14:13:17 -07001719 }
1720
1721 if (status != NO_ERROR && srcThread != nullptr) {
1722 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001723 }
1724 return status;
1725}
1726
Andy Hung3ff4b552023-06-26 19:20:57 -07001727void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001728{
1729 mAuxEffectId = EffectId;
1730 mAuxBuffer = buffer;
1731}
1732
Andy Hung59de4262021-06-14 10:53:54 -07001733// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001734bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001735 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001736{
Andy Hung818e7a32016-02-16 18:08:07 -08001737 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1738 // This assists in proper timestamp computation as well as wakelock management.
1739
Eric Laurent81784c32012-11-19 14:55:58 -08001740 // a track is considered presented when the total number of frames written to audio HAL
1741 // corresponds to the number of frames written when presentationComplete() is called for the
1742 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001743 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1744 // to detect when all frames have been played. In this case framesWritten isn't
1745 // useful because it doesn't always reflect whether there is data in the h/w
1746 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001747 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1748 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001749 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001750 if (mPresentationCompleteFrames == 0) {
1751 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001752 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001753 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1754 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001755 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001756 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001757
Andy Hungc54b1ff2016-02-23 14:07:07 -08001758 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001759 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001760 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001761 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1762 __func__, mId, (complete ? "complete" : "waiting"),
1763 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001764 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001765 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001766 && mAudioTrackServerProxy->isDrained();
1767 }
1768
1769 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001770 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001771 return true;
1772 }
1773 return false;
1774}
1775
Andy Hung59de4262021-06-14 10:53:54 -07001776// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001777bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001778{
1779 // For Offloaded or Direct tracks.
1780
1781 // For a direct track, we incorporated time based testing for presentationComplete.
1782
1783 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1784 // to detect when all frames have been played. In this case latencyMs isn't
1785 // useful because it doesn't always reflect whether there is data in the h/w
1786 // buffers, particularly if a track has been paused and resumed during draining
1787
1788 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1789 if (mPresentationCompleteTimeNs == 0) {
1790 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1791 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1792 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1793 }
1794
1795 bool complete;
1796 if (isOffloaded()) {
1797 complete = true;
1798 } else { // Direct
1799 complete = systemTime() >= mPresentationCompleteTimeNs;
1800 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1801 }
1802 if (complete) {
1803 notifyPresentationComplete();
1804 return true;
1805 }
1806 return false;
1807}
1808
Andy Hung3ff4b552023-06-26 19:20:57 -07001809void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001810{
1811 // This only triggers once. TODO: should we enforce this?
1812 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1813 mAudioTrackServerProxy->setStreamEndDone();
1814}
1815
Andy Hung3ff4b552023-06-26 19:20:57 -07001816void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001817{
Andy Hung068e08e2023-05-15 19:02:55 -07001818 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1819 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001820 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001821 (*it)->trigger();
1822 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001823 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001824 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001825 }
1826 }
1827}
1828
1829// implement VolumeBufferProvider interface
1830
Andy Hung3ff4b552023-06-26 19:20:57 -07001831gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001832{
1833 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1834 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001835 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1836 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1837 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001838 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001839 if (vl > GAIN_FLOAT_UNITY) {
1840 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001841 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001842 if (vr > GAIN_FLOAT_UNITY) {
1843 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001844 }
1845 // now apply the cached master volume and stream type volume;
1846 // this is trusted but lacks any synchronization or barrier so may be stale
1847 float v = mCachedVolume;
1848 vl *= v;
1849 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001850 // re-combine into packed minifloat
1851 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001852 // FIXME look at mute, pause, and stop flags
1853 return vlr;
1854}
1855
Andy Hung3ff4b552023-06-26 19:20:57 -07001856status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001857 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001858{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001859 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001860 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1861 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001862 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1863 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001864 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001865 event->cancel();
1866 return INVALID_OPERATION;
1867 }
1868 (void) TrackBase::setSyncEvent(event);
1869 return NO_ERROR;
1870}
1871
Andy Hung3ff4b552023-06-26 19:20:57 -07001872void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001873{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001874 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001875 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001876}
1877
Andy Hung3ff4b552023-06-26 19:20:57 -07001878void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001879{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001880 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001881 signalClientFlag(CBLK_DISABLED);
1882}
1883
Andy Hung3ff4b552023-06-26 19:20:57 -07001884void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001885{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001886 // FIXME should use proxy, and needs work
1887 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001888 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001889 android_atomic_release_store(0x40000000, &cblk->mFutex);
1890 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001891 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001892}
1893
Andy Hung3ff4b552023-06-26 19:20:57 -07001894void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001895{
Andy Hung44f27182023-07-06 20:56:16 -07001896 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001897 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001898 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001899 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001900 t->broadcast_l();
1901 }
1902}
1903
Andy Hung3ff4b552023-06-26 19:20:57 -07001904status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001905{
1906 status_t status = INVALID_OPERATION;
1907 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001908 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001909 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001910 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001911 audio_utils::lock_guard _l(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001912 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001913 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1914 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1915 }
1916 }
1917 return status;
1918}
1919
Andy Hung3ff4b552023-06-26 19:20:57 -07001920status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001921{
1922 status_t status = INVALID_OPERATION;
1923 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001924 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001925 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001926 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001927 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001928 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001929 if (status == NO_ERROR) {
1930 mDualMonoMode = mode;
1931 }
1932 }
1933 }
1934 return status;
1935}
1936
Andy Hung3ff4b552023-06-26 19:20:57 -07001937status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001938{
1939 status_t status = INVALID_OPERATION;
1940 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001941 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001942 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001943 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001944 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001945 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001946 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1947 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1948 }
1949 }
1950 return status;
1951}
1952
Andy Hung3ff4b552023-06-26 19:20:57 -07001953status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001954{
1955 status_t status = INVALID_OPERATION;
1956 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001957 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001958 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001959 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001960 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001961 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001962 if (status == NO_ERROR) {
1963 mAudioDescriptionMixLevel = leveldB;
1964 }
1965 }
1966 }
1967 return status;
1968}
1969
Andy Hung3ff4b552023-06-26 19:20:57 -07001970status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001971 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001972{
1973 status_t status = INVALID_OPERATION;
1974 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001975 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001976 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001977 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001978 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001979 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001980 ALOGD_IF((status == NO_ERROR) &&
1981 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1982 "%s: playbackRate inconsistent", __func__);
1983 }
1984 }
1985 return status;
1986}
1987
Andy Hung3ff4b552023-06-26 19:20:57 -07001988status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001989 const audio_playback_rate_t& playbackRate)
1990{
1991 status_t status = INVALID_OPERATION;
1992 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001993 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001994 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001995 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001996 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001997 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001998 if (status == NO_ERROR) {
1999 mPlaybackRateParameters = playbackRate;
2000 }
2001 }
2002 }
2003 return status;
2004}
2005
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002006//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002007bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07002008 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002009 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07002010 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002011 /* Resume is pending if track was stopping before pause was called */
2012 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07002013 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002014 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07002015 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002016
2017 return false;
2018}
2019
2020//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002021void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07002022 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002023 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07002024 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002025
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002026 // Other possibility of pending resume is stopping_1 state
2027 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002028 // drain being called.
2029 if (mState == STOPPING_1) {
2030 mResumeToStopping = false;
2031 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002032}
Andy Hunge10393e2015-06-12 13:59:33 -07002033
2034//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002035void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002036 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002037 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002038 // Make the kernel frametime available.
2039 const FrameTime ft{
2040 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2041 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2042 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2043 mKernelFrameTime.store(ft);
2044 if (!audio_is_linear_pcm(mFormat)) {
2045 return;
2046 }
2047
Andy Hung818e7a32016-02-16 18:08:07 -08002048 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002049 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002050
2051 // adjust server times and set drained state.
2052 //
2053 // Our timestamps are only updated when the track is on the Thread active list.
2054 // We need to ensure that tracks are not removed before full drain.
2055 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002056 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002057 bool checked = false;
2058 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2059 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2060 // Lookup the track frame corresponding to the sink frame position.
2061 if (local.mTimeNs[i] > 0) {
2062 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2063 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002064 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002065 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002066 checked = true;
2067 }
2068 }
Andy Hunge10393e2015-06-12 13:59:33 -07002069 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002070
Andy Hung93bb5732023-05-04 21:16:34 -07002071 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2072 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002073 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002074 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002075 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002076 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002077
2078 // Compute latency info.
2079 const bool useTrackTimestamp = !drained;
2080 const double latencyMs = useTrackTimestamp
2081 ? local.getOutputServerLatencyMs(sampleRate())
2082 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2083
2084 mServerLatencyFromTrack.store(useTrackTimestamp);
2085 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002086
Andy Hung62921122020-05-18 10:47:31 -07002087 if (mLogStartCountdown > 0
2088 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2089 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2090 {
2091 if (mLogStartCountdown > 1) {
2092 --mLogStartCountdown;
2093 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2094 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002095 // startup is the difference in times for the current timestamp and our start
2096 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002097 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002098 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002099 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2100 * 1e3 / mSampleRate;
2101 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2102 " localTime:%lld startTime:%lld"
2103 " localPosition:%lld startPosition:%lld",
2104 __func__, latencyMs, startUpMs,
2105 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002106 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002107 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002108 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002109 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002110 }
Andy Hung62921122020-05-18 10:47:31 -07002111 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002112 }
Andy Hunge10393e2015-06-12 13:59:33 -07002113}
2114
Andy Hung3ff4b552023-06-26 19:20:57 -07002115bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002116 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002117 if (thread != 0) {
2118 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87e82412023-08-29 14:26:09 -07002119 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002120 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002121 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002122 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002123 ALOGD("%s, haptic playback was %s for track %d",
2124 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002125 mTrack->setHapticPlaybackEnabled(!muted);
2126 return true;
jiabin57303cc2018-12-18 15:45:57 -08002127 }
2128 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002129 return false;
2130}
2131
Andy Hung3ff4b552023-06-26 19:20:57 -07002132binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002133 /*out*/ bool *ret) {
2134 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002135 return binder::Status::ok();
2136}
2137
Andy Hung3ff4b552023-06-26 19:20:57 -07002138binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002139 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002140 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002141 return binder::Status::ok();
2142}
2143
Eric Laurent81784c32012-11-19 14:55:58 -08002144// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002145#undef LOG_TAG
2146#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002147
Andy Hung3ff4b552023-06-26 19:20:57 -07002148/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002149sp<IAfOutputTrack> IAfOutputTrack::create(
2150 IAfPlaybackThread* playbackThread,
2151 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002152 uint32_t sampleRate,
2153 audio_format_t format,
2154 audio_channel_mask_t channelMask,
2155 size_t frameCount,
2156 const AttributionSourceState& attributionSource) {
2157 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002158 playbackThread,
2159 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002160 sampleRate,
2161 format,
2162 channelMask,
2163 frameCount,
2164 attributionSource);
2165}
2166
2167OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002168 IAfPlaybackThread* playbackThread,
2169 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002170 uint32_t sampleRate,
2171 audio_format_t format,
2172 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002173 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002174 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002175 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002176 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002177 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002178 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002179 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002180 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002181 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002182{
2183
2184 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002185 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002186 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002187 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002188 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002189 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002190 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002191 // since client and server are in the same process,
2192 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002193 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2194 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002195 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002196 mClientProxy->setSendLevel(0.0);
2197 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002198 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002199 ALOGW("%s(%d): Error creating output track on thread %d",
2200 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002201 }
2202}
2203
Andy Hung3ff4b552023-06-26 19:20:57 -07002204OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002205{
2206 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002207 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002208}
2209
Andy Hung3ff4b552023-06-26 19:20:57 -07002210status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002211 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002212{
2213 status_t status = Track::start(event, triggerSession);
2214 if (status != NO_ERROR) {
2215 return status;
2216 }
2217
2218 mActive = true;
2219 mRetryCount = 127;
2220 return status;
2221}
2222
Andy Hung3ff4b552023-06-26 19:20:57 -07002223void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002224{
2225 Track::stop();
2226 clearBufferQueue();
2227 mOutBuffer.frameCount = 0;
2228 mActive = false;
2229}
2230
Andy Hung3ff4b552023-06-26 19:20:57 -07002231ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002232{
Eric Laurent19952e12023-04-20 10:08:29 +02002233 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002234 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002235 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002236 // preload one silent buffer to trigger mixer on start()
2237 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2238 status_t status = mClientProxy->obtainBuffer(&buf);
2239 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2240 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2241 return 0;
2242 }
2243 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2244 mClientProxy->releaseBuffer(&buf);
2245
2246 (void) start();
2247
2248 // wait for HAL stream to start before sending actual audio. Doing this on each
2249 // OutputTrack makes that playback start on all output streams is synchronized.
2250 // If another OutputTrack has already started it can underrun but this is OK
2251 // as only silence has been played so far and the retry count is very high on
2252 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002253 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002254 if (!pt->waitForHalStart()) {
2255 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2256 stop();
2257 return 0;
2258 }
2259
2260 // enqueue the first buffer and exit so that other OutputTracks will also start before
2261 // write() is called again and this buffer actually consumed.
2262 Buffer firstBuffer;
2263 firstBuffer.frameCount = frames;
2264 firstBuffer.raw = data;
2265 queueBuffer(firstBuffer);
2266 return frames;
2267 } else {
2268 (void) start();
2269 }
2270 }
2271
Eric Laurent81784c32012-11-19 14:55:58 -08002272 Buffer *pInBuffer;
2273 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002274 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002275 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002276 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002277 while (waitTimeLeftMs) {
2278 // First write pending buffers, then new data
2279 if (mBufferQueue.size()) {
2280 pInBuffer = mBufferQueue.itemAt(0);
2281 } else {
2282 pInBuffer = &inBuffer;
2283 }
2284
2285 if (pInBuffer->frameCount == 0) {
2286 break;
2287 }
2288
2289 if (mOutBuffer.frameCount == 0) {
2290 mOutBuffer.frameCount = pInBuffer->frameCount;
2291 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002292 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002293 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002294 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2295 __func__, mId,
2296 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002297 break;
2298 }
2299 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2300 if (waitTimeLeftMs >= waitTimeMs) {
2301 waitTimeLeftMs -= waitTimeMs;
2302 } else {
2303 waitTimeLeftMs = 0;
2304 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002305 if (status == NOT_ENOUGH_DATA) {
2306 restartIfDisabled();
2307 continue;
2308 }
Eric Laurent81784c32012-11-19 14:55:58 -08002309 }
2310
2311 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2312 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002313 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002314 Proxy::Buffer buf;
2315 buf.mFrameCount = outFrames;
2316 buf.mRaw = NULL;
2317 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002318 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002319 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002320 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002321 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002322 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002323
2324 if (pInBuffer->frameCount == 0) {
2325 if (mBufferQueue.size()) {
2326 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002327 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002328 if (pInBuffer != &inBuffer) {
2329 delete pInBuffer;
2330 }
Andy Hung9d84af52018-09-12 18:03:44 -07002331 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2332 __func__, mId,
2333 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002334 } else {
2335 break;
2336 }
2337 }
2338 }
2339
2340 // If we could not write all frames, allocate a buffer and queue it for next time.
2341 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002342 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002343 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002344 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002345 }
2346 }
2347
Andy Hungc25b84a2015-01-14 19:04:10 -08002348 // Calling write() with a 0 length buffer means that no more data will be written:
2349 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2350 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2351 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002352 }
2353
Andy Hung1c86ebe2018-05-29 20:29:08 -07002354 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002355}
2356
Andy Hung3ff4b552023-06-26 19:20:57 -07002357void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002358
2359 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2360 Buffer *pInBuffer = new Buffer;
2361 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2362 pInBuffer->mBuffer = malloc(bufferSize);
2363 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2364 "%s: Unable to malloc size %zu", __func__, bufferSize);
2365 pInBuffer->frameCount = inBuffer.frameCount;
2366 pInBuffer->raw = pInBuffer->mBuffer;
2367 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2368 mBufferQueue.add(pInBuffer);
2369 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2370 (int)mThreadIoHandle, mBufferQueue.size());
2371 // audio data is consumed (stored locally); set frameCount to 0.
2372 inBuffer.frameCount = 0;
2373 } else {
2374 ALOGW("%s(%d): thread %d no more overflow buffers",
2375 __func__, mId, (int)mThreadIoHandle);
2376 // TODO: return error for this.
2377 }
2378}
2379
Andy Hung3ff4b552023-06-26 19:20:57 -07002380void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002381{
Andy Hung87e82412023-08-29 14:26:09 -07002382 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002383 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2384}
2385
Andy Hung3ff4b552023-06-26 19:20:57 -07002386void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002387 {
Andy Hung87e82412023-08-29 14:26:09 -07002388 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002389 mTrackMetadatas = metadatas;
2390 }
2391 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2392 setMetadataHasChanged();
2393}
2394
Andy Hung3ff4b552023-06-26 19:20:57 -07002395status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002396 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2397{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002398 ClientProxy::Buffer buf;
2399 buf.mFrameCount = buffer->frameCount;
2400 struct timespec timeout;
2401 timeout.tv_sec = waitTimeMs / 1000;
2402 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2403 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2404 buffer->frameCount = buf.mFrameCount;
2405 buffer->raw = buf.mRaw;
2406 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002407}
2408
Andy Hung3ff4b552023-06-26 19:20:57 -07002409void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002410{
2411 size_t size = mBufferQueue.size();
2412
2413 for (size_t i = 0; i < size; i++) {
2414 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002415 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002416 delete pBuffer;
2417 }
2418 mBufferQueue.clear();
2419}
2420
Andy Hung3ff4b552023-06-26 19:20:57 -07002421void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002422{
2423 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2424 if (mActive && (flags & CBLK_DISABLED)) {
2425 start();
2426 }
2427}
Eric Laurent81784c32012-11-19 14:55:58 -08002428
Andy Hung9d84af52018-09-12 18:03:44 -07002429// ----------------------------------------------------------------------------
2430#undef LOG_TAG
2431#define LOG_TAG "AF::PatchTrack"
2432
Andy Hung3ff4b552023-06-26 19:20:57 -07002433/* static */
2434sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002435 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002436 audio_stream_type_t streamType,
2437 uint32_t sampleRate,
2438 audio_channel_mask_t channelMask,
2439 audio_format_t format,
2440 size_t frameCount,
2441 void* buffer,
2442 size_t bufferSize,
2443 audio_output_flags_t flags,
2444 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002445 size_t frameCountToBeReady, /** Default behaviour is to start
Andy Hung3ff4b552023-06-26 19:20:57 -07002446 * as soon as possible to have
2447 * the lowest possible latency
guonaichao3acc9b12024-06-07 09:27:21 +08002448 * even if it might glitch. */
2449 float speed)
Andy Hung3ff4b552023-06-26 19:20:57 -07002450{
2451 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002452 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002453 streamType,
2454 sampleRate,
2455 channelMask,
2456 format,
2457 frameCount,
2458 buffer,
2459 bufferSize,
2460 flags,
2461 timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002462 frameCountToBeReady,
2463 speed);
Andy Hung3ff4b552023-06-26 19:20:57 -07002464}
2465
Andy Hung44f27182023-07-06 20:56:16 -07002466PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002467 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002468 uint32_t sampleRate,
2469 audio_channel_mask_t channelMask,
2470 audio_format_t format,
2471 size_t frameCount,
2472 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002473 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002474 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002475 const Timeout& timeout,
guonaichao3acc9b12024-06-07 09:27:21 +08002476 size_t frameCountToBeReady,
2477 float speed)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002478 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002479 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002480 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002481 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002482 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
guonaichao3acc9b12024-06-07 09:27:21 +08002483 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed),
2484 PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
2485 true /*clientInServer*/) : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07002486 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002487{
guonaichao3acc9b12024-06-07 09:27:21 +08002488 if (mProxy != nullptr) {
2489 sp<AudioTrackClientProxy>::cast(mProxy)->setPlaybackRate({
2490 /* .mSpeed = */ speed,
2491 /* .mPitch = */ AUDIO_TIMESTRETCH_PITCH_NORMAL,
2492 /* .mStretchMode = */ AUDIO_TIMESTRETCH_STRETCH_DEFAULT,
2493 /* .mFallbackMode = */ AUDIO_TIMESTRETCH_FALLBACK_FAIL
2494 });
2495 }
Andy Hung9d84af52018-09-12 18:03:44 -07002496 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2497 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002498 (int)mPeerTimeout.tv_sec,
2499 (int)(mPeerTimeout.tv_nsec / 1000000));
2500}
2501
Andy Hung3ff4b552023-06-26 19:20:57 -07002502PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002503{
Andy Hungabfab202019-03-07 19:45:54 -08002504 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002505}
2506
Andy Hung3ff4b552023-06-26 19:20:57 -07002507size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002508{
2509 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2510 return std::numeric_limits<size_t>::max();
2511 } else {
2512 return Track::framesReady();
2513 }
2514}
2515
Andy Hung3ff4b552023-06-26 19:20:57 -07002516status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002517 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002518{
2519 status_t status = Track::start(event, triggerSession);
2520 if (status != NO_ERROR) {
2521 return status;
2522 }
2523 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2524 return status;
2525}
2526
Eric Laurent83b88082014-06-20 18:31:16 -07002527// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002528status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002529 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002530{
Andy Hung9d84af52018-09-12 18:03:44 -07002531 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002532 Proxy::Buffer buf;
2533 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002534 if (ATRACE_ENABLED()) {
2535 std::string traceName("PTnReq");
2536 traceName += std::to_string(id());
2537 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2538 }
Eric Laurent83b88082014-06-20 18:31:16 -07002539 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002540 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002541 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002542 if (ATRACE_ENABLED()) {
2543 std::string traceName("PTnObt");
2544 traceName += std::to_string(id());
2545 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2546 }
Eric Laurent83b88082014-06-20 18:31:16 -07002547 if (buf.mFrameCount == 0) {
2548 return WOULD_BLOCK;
2549 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002550 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002551 return status;
2552}
2553
Andy Hung3ff4b552023-06-26 19:20:57 -07002554void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002555{
Andy Hung9d84af52018-09-12 18:03:44 -07002556 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002557 Proxy::Buffer buf;
2558 buf.mFrameCount = buffer->frameCount;
2559 buf.mRaw = buffer->raw;
2560 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002561 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002562}
2563
Andy Hung3ff4b552023-06-26 19:20:57 -07002564status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002565 const struct timespec *timeOut)
2566{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002567 status_t status = NO_ERROR;
2568 static const int32_t kMaxTries = 5;
2569 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002570 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002571 do {
2572 if (status == NOT_ENOUGH_DATA) {
2573 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002574 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002575 }
2576 status = mProxy->obtainBuffer(buffer, timeOut);
2577 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2578 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002579}
2580
Andy Hung3ff4b552023-06-26 19:20:57 -07002581void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002582{
2583 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002584 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002585
2586 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2587 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2588 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2589 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002590 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002591 && audio_is_linear_pcm(mFormat)
2592 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002593 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002594 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002595 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002596 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2597 / playbackThread->sampleRate();
2598 if (framesReady() < frameCount) {
2599 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002600 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002601 }
2602 }
2603 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002604}
2605
Andy Hung3ff4b552023-06-26 19:20:57 -07002606void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002607{
Eric Laurent83b88082014-06-20 18:31:16 -07002608 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002609 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002610 start();
2611 }
Eric Laurent83b88082014-06-20 18:31:16 -07002612}
2613
Eric Laurent81784c32012-11-19 14:55:58 -08002614// ----------------------------------------------------------------------------
2615// Record
2616// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002617
2618
Andy Hung9d84af52018-09-12 18:03:44 -07002619#undef LOG_TAG
2620#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002621
Andy Hungaaa18282023-06-23 19:27:19 -07002622class RecordHandle : public android::media::BnAudioRecord {
2623public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002624 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002625 ~RecordHandle() override;
2626 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2627 int /*audio_session_t*/ triggerSession) final;
2628 binder::Status stop() final;
2629 binder::Status getActiveMicrophones(
2630 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2631 binder::Status setPreferredMicrophoneDirection(
2632 int /*audio_microphone_direction_t*/ direction) final;
2633 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2634 binder::Status shareAudioHistory(
2635 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2636
2637private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002638 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002639
2640 // for use from destructor
2641 void stop_nonvirtual();
2642};
2643
2644/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002645sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2646 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002647 return sp<RecordHandle>::make(recordTrack);
2648}
2649
2650RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002651 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002652 : BnAudioRecord(),
2653 mRecordTrack(recordTrack)
2654{
Andy Hung225aef62022-12-06 16:33:20 -08002655 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Andy Hungf2b4a182024-03-26 18:04:29 -07002656 setInheritRt(true);
Eric Laurent81784c32012-11-19 14:55:58 -08002657}
2658
Andy Hungaaa18282023-06-23 19:27:19 -07002659RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002660 stop_nonvirtual();
2661 mRecordTrack->destroy();
2662}
2663
Andy Hungaaa18282023-06-23 19:27:19 -07002664binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002665 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002666 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002667 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002668 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002669}
2670
Andy Hungaaa18282023-06-23 19:27:19 -07002671binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002672 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002673 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002674}
2675
Andy Hungaaa18282023-06-23 19:27:19 -07002676void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002677 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002678 mRecordTrack->stop();
2679}
2680
Andy Hungaaa18282023-06-23 19:27:19 -07002681binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002682 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002683 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002684 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002685}
2686
Andy Hungaaa18282023-06-23 19:27:19 -07002687binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002688 int /*audio_microphone_direction_t*/ direction) {
2689 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002690 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002691 static_cast<audio_microphone_direction_t>(direction)));
2692}
2693
Andy Hungaaa18282023-06-23 19:27:19 -07002694binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002695 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002696 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002697}
2698
Andy Hungaaa18282023-06-23 19:27:19 -07002699binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002700 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2701 return binderStatusFromStatusT(
2702 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2703}
2704
Eric Laurent81784c32012-11-19 14:55:58 -08002705// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002706#undef LOG_TAG
2707#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002708
Andy Hung3ff4b552023-06-26 19:20:57 -07002709
Andy Hung56126702023-07-14 11:00:08 -07002710/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002711sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002712 const sp<Client>& client,
2713 const audio_attributes_t& attr,
2714 uint32_t sampleRate,
2715 audio_format_t format,
2716 audio_channel_mask_t channelMask,
2717 size_t frameCount,
2718 void* buffer,
2719 size_t bufferSize,
2720 audio_session_t sessionId,
2721 pid_t creatorPid,
2722 const AttributionSourceState& attributionSource,
2723 audio_input_flags_t flags,
2724 track_type type,
2725 audio_port_handle_t portId,
2726 int32_t startFrames)
2727{
2728 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002729 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002730 client,
2731 attr,
2732 sampleRate,
2733 format,
2734 channelMask,
2735 frameCount,
2736 buffer,
2737 bufferSize,
2738 sessionId,
2739 creatorPid,
2740 attributionSource,
2741 flags,
2742 type,
2743 portId,
2744 startFrames);
2745}
2746
Glenn Kasten05997e22014-03-13 15:08:33 -07002747// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002748RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002749 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002750 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002751 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002752 uint32_t sampleRate,
2753 audio_format_t format,
2754 audio_channel_mask_t channelMask,
2755 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002756 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002757 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002758 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002759 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002760 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002761 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002762 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002763 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002764 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002765 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002766 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002767 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002768 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002769 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002770 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002771 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002772 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002773 type, portId,
2774 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002775 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002776 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002777 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002778 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002779 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002780 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002781{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002782 if (mCblk == NULL) {
2783 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002784 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002785
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002786 if (!isDirect()) {
2787 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002788 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002789 channelMask, format, sampleRate);
2790 // Check if the RecordBufferConverter construction was successful.
2791 // If not, don't continue with construction.
2792 //
2793 // NOTE: It would be extremely rare that the record track cannot be created
2794 // for the current device, but a pending or future device change would make
2795 // the record track configuration valid.
2796 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002797 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002798 return;
2799 }
Andy Hung97a893e2015-03-29 01:03:07 -07002800 }
2801
Andy Hung6ae58432016-02-16 18:32:24 -08002802 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002803 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002804
Andy Hung97a893e2015-03-29 01:03:07 -07002805 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002806
Eric Laurent05067782016-06-01 18:27:28 -07002807 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002808 ALOG_ASSERT(thread->fastTrackAvailable());
2809 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002810 } else {
2811 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002812 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002813 }
Andy Hung8946a282018-04-19 20:04:56 -07002814#ifdef TEE_SINK
2815 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2816 + "_" + std::to_string(mId)
2817 + "_R");
2818#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002819
2820 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002821 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002822}
2823
Andy Hung3ff4b552023-06-26 19:20:57 -07002824RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002825{
Andy Hung9d84af52018-09-12 18:03:44 -07002826 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002827 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002828 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002829}
2830
Andy Hung3ff4b552023-06-26 19:20:57 -07002831status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002832{
2833 status_t status = TrackBase::initCheck();
2834 if (status == NO_ERROR && mServerProxy == 0) {
2835 status = BAD_VALUE;
2836 }
2837 return status;
2838}
2839
Eric Laurent81784c32012-11-19 14:55:58 -08002840// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002841status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002842{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002843 ServerProxy::Buffer buf;
2844 buf.mFrameCount = buffer->frameCount;
2845 status_t status = mServerProxy->obtainBuffer(&buf);
2846 buffer->frameCount = buf.mFrameCount;
2847 buffer->raw = buf.mRaw;
2848 if (buf.mFrameCount == 0) {
2849 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002850 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002851 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002852 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002853}
2854
Andy Hung3ff4b552023-06-26 19:20:57 -07002855status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002856 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002857{
Andy Hung44f27182023-07-06 20:56:16 -07002858 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002859 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002860 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002861 return recordThread->start(this, event, triggerSession);
2862 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002863 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2864 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002865 }
2866}
2867
Andy Hung3ff4b552023-06-26 19:20:57 -07002868void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002869{
Andy Hung44f27182023-07-06 20:56:16 -07002870 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002871 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002872 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002873 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002874 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002875 }
2876 }
2877}
2878
Andy Hung3ff4b552023-06-26 19:20:57 -07002879void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002880{
Andy Hung3ff4b552023-06-26 19:20:57 -07002881 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002882 sp<RecordTrack> keep(this);
2883 {
Andy Hungce685402018-10-05 17:23:27 -07002884 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002885 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002886 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07002887 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002888 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002889 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002890 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002891 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002892 }
Andy Hungce685402018-10-05 17:23:27 -07002893 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2894 }
2895 // APM portid/client management done outside of lock.
2896 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2897 if (isExternalTrack()) {
2898 switch (priorState) {
2899 case ACTIVE: // invalidated while still active
2900 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2901 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2902 AudioSystem::stopInput(mPortId);
2903 break;
2904
2905 case STARTING_1: // invalidated/start-aborted and startInput not successful
2906 case PAUSED: // OK, not active
2907 case IDLE: // OK, not active
2908 break;
2909
2910 case STOPPED: // unexpected (destroyed)
2911 default:
2912 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2913 }
2914 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002915 }
2916 }
2917}
2918
Andy Hung3ff4b552023-06-26 19:20:57 -07002919void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002920{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002921 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002922 // FIXME should use proxy, and needs work
2923 audio_track_cblk_t* cblk = mCblk;
2924 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2925 android_atomic_release_store(0x40000000, &cblk->mFutex);
2926 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002927 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002928}
2929
Eric Laurent81784c32012-11-19 14:55:58 -08002930
Andy Hung3ff4b552023-06-26 19:20:57 -07002931void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002932{
Eric Laurent973db022018-11-20 14:54:31 -08002933 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002934 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002935 " Server FrmCnt FrmRdy Sil%s\n",
2936 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002937}
2938
Andy Hung3ff4b552023-06-26 19:20:57 -07002939void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002940{
Eric Laurent973db022018-11-20 14:54:31 -08002941 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002942 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002943 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002944 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002945 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002946 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002947 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002948 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002949 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002950 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002951 mCblk->mFlags,
2952
Eric Laurent81784c32012-11-19 14:55:58 -08002953 mFormat,
2954 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002955 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002956 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002957
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002958 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002959 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002960 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002961 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002962 );
Andy Hung000adb52018-06-01 15:43:26 -07002963 if (isServerLatencySupported()) {
2964 double latencyMs;
2965 bool fromTrack;
2966 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2967 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2968 // or 'k' if estimated from kernel (usually for debugging).
2969 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2970 } else {
2971 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2972 }
2973 }
2974 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002975}
2976
Andy Hung93bb5732023-05-04 21:16:34 -07002977// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002978void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002979 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002980{
Andy Hung93bb5732023-05-04 21:16:34 -07002981 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002982 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002983 if (threadBase != 0) {
2984 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2985 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002986 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002987 }
Andy Hung93bb5732023-05-04 21:16:34 -07002988
2989 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002990}
2991
Andy Hung3ff4b552023-06-26 19:20:57 -07002992void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002993{
Andy Hung93bb5732023-05-04 21:16:34 -07002994 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002995}
2996
Andy Hung3ff4b552023-06-26 19:20:57 -07002997void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002998 int64_t trackFramesReleased, int64_t sourceFramesRead,
2999 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
3000{
Andy Hung30282562018-08-08 18:27:03 -07003001 // Make the kernel frametime available.
3002 const FrameTime ft{
3003 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
3004 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
3005 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
3006 mKernelFrameTime.store(ft);
3007 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05003008 // Stream is direct, return provided timestamp with no conversion
3009 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07003010 return;
3011 }
3012
Andy Hung3f0c9022016-01-15 17:49:46 -08003013 ExtendedTimestamp local = timestamp;
3014
3015 // Convert HAL frames to server-side track frames at track sample rate.
3016 // We use trackFramesReleased and sourceFramesRead as an anchor point.
3017 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
3018 if (local.mTimeNs[i] != 0) {
3019 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
3020 const int64_t relativeTrackFrames = relativeServerFrames
3021 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3022 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3023 }
3024 }
Andy Hung6ae58432016-02-16 18:32:24 -08003025 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003026
3027 // Compute latency info.
3028 const bool useTrackTimestamp = true; // use track unless debugging.
3029 const double latencyMs = - (useTrackTimestamp
3030 ? local.getOutputServerLatencyMs(sampleRate())
3031 : timestamp.getOutputServerLatencyMs(halSampleRate));
3032
3033 mServerLatencyFromTrack.store(useTrackTimestamp);
3034 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003035}
Eric Laurent83b88082014-06-20 18:31:16 -07003036
Andy Hung3ff4b552023-06-26 19:20:57 -07003037status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003038 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003039{
Andy Hung44f27182023-07-06 20:56:16 -07003040 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003041 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003042 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003043 return recordThread->getActiveMicrophones(activeMicrophones);
3044 } else {
3045 return BAD_VALUE;
3046 }
3047}
3048
Andy Hung3ff4b552023-06-26 19:20:57 -07003049status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003050 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003051 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003052 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003053 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003054 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003055 } else {
3056 return BAD_VALUE;
3057 }
3058}
3059
Andy Hung3ff4b552023-06-26 19:20:57 -07003060status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003061 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003062 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003063 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003064 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003065 } else {
3066 return BAD_VALUE;
3067 }
3068}
3069
Andy Hung3ff4b552023-06-26 19:20:57 -07003070status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003071 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3072
3073 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3074 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3075 if (callingUid != mUid || callingPid != mCreatorPid) {
3076 return PERMISSION_DENIED;
3077 }
3078
Svet Ganov33761132021-05-13 22:51:08 +00003079 AttributionSourceState attributionSource{};
3080 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3081 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3082 attributionSource.token = sp<BBinder>::make();
3083 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003084 return PERMISSION_DENIED;
3085 }
3086
Andy Hung44f27182023-07-06 20:56:16 -07003087 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003088 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003089 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003090 status_t status = recordThread->shareAudioHistory(
3091 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3092 if (status == NO_ERROR) {
3093 mSharedAudioPackageName = sharedAudioPackageName;
3094 }
3095 return status;
3096 } else {
3097 return BAD_VALUE;
3098 }
3099}
3100
Andy Hung3ff4b552023-06-26 19:20:57 -07003101void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003102{
3103
3104 // Do not forward PatchRecord metadata with unspecified audio source
3105 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3106 return;
3107 }
3108
3109 // No track is invalid as this is called after prepareTrack_l in the same critical section
3110 record_track_metadata_v7_t metadata;
3111 metadata.base = {
3112 .source = mAttr.source,
3113 .gain = 1, // capture tracks do not have volumes
3114 };
3115 metadata.channel_mask = mChannelMask;
3116 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3117
3118 *backInserter++ = metadata;
3119}
Eric Laurentec376dc2021-04-08 20:41:22 +02003120
Andy Hung9d84af52018-09-12 18:03:44 -07003121// ----------------------------------------------------------------------------
3122#undef LOG_TAG
3123#define LOG_TAG "AF::PatchRecord"
3124
Andy Hung3ff4b552023-06-26 19:20:57 -07003125/* static */
3126sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003127 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003128 uint32_t sampleRate,
3129 audio_channel_mask_t channelMask,
3130 audio_format_t format,
3131 size_t frameCount,
3132 void *buffer,
3133 size_t bufferSize,
3134 audio_input_flags_t flags,
3135 const Timeout& timeout,
3136 audio_source_t source)
3137{
3138 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003139 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003140 sampleRate,
3141 channelMask,
3142 format,
3143 frameCount,
3144 buffer,
3145 bufferSize,
3146 flags,
3147 timeout,
3148 source);
3149}
3150
Andy Hung44f27182023-07-06 20:56:16 -07003151PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003152 uint32_t sampleRate,
3153 audio_channel_mask_t channelMask,
3154 audio_format_t format,
3155 size_t frameCount,
3156 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003157 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003158 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003159 const Timeout& timeout,
3160 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003161 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003162 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003163 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003164 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003165 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003166 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3167 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07003168 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003169{
Andy Hung9d84af52018-09-12 18:03:44 -07003170 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3171 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003172 (int)mPeerTimeout.tv_sec,
3173 (int)(mPeerTimeout.tv_nsec / 1000000));
3174}
3175
Andy Hung3ff4b552023-06-26 19:20:57 -07003176PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003177{
Andy Hungabfab202019-03-07 19:45:54 -08003178 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003179}
3180
Mikhail Naganov8296c252019-09-25 14:59:54 -07003181static size_t writeFramesHelper(
3182 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3183{
3184 AudioBufferProvider::Buffer patchBuffer;
3185 patchBuffer.frameCount = frameCount;
3186 auto status = dest->getNextBuffer(&patchBuffer);
3187 if (status != NO_ERROR) {
3188 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3189 __func__, status, strerror(-status));
3190 return 0;
3191 }
3192 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3193 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3194 size_t framesWritten = patchBuffer.frameCount;
3195 dest->releaseBuffer(&patchBuffer);
3196 return framesWritten;
3197}
3198
3199// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003200size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003201 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3202{
3203 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3204 // On buffer wrap, the buffer frame count will be less than requested,
3205 // when this happens a second buffer needs to be used to write the leftover audio
3206 const size_t framesLeft = frameCount - framesWritten;
3207 if (framesWritten != 0 && framesLeft != 0) {
3208 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3209 framesLeft, frameSize);
3210 }
3211 return framesWritten;
3212}
3213
Eric Laurent83b88082014-06-20 18:31:16 -07003214// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003215status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003216 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003217{
Andy Hung9d84af52018-09-12 18:03:44 -07003218 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003219 Proxy::Buffer buf;
3220 buf.mFrameCount = buffer->frameCount;
3221 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3222 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003223 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003224 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003225 if (ATRACE_ENABLED()) {
3226 std::string traceName("PRnObt");
3227 traceName += std::to_string(id());
3228 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3229 }
Eric Laurent83b88082014-06-20 18:31:16 -07003230 if (buf.mFrameCount == 0) {
3231 return WOULD_BLOCK;
3232 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003233 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003234 return status;
3235}
3236
Andy Hung3ff4b552023-06-26 19:20:57 -07003237void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003238{
Andy Hung9d84af52018-09-12 18:03:44 -07003239 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003240 Proxy::Buffer buf;
3241 buf.mFrameCount = buffer->frameCount;
3242 buf.mRaw = buffer->raw;
3243 mPeerProxy->releaseBuffer(&buf);
3244 TrackBase::releaseBuffer(buffer);
3245}
3246
Andy Hung3ff4b552023-06-26 19:20:57 -07003247status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003248 const struct timespec *timeOut)
3249{
3250 return mProxy->obtainBuffer(buffer, timeOut);
3251}
3252
Andy Hung3ff4b552023-06-26 19:20:57 -07003253void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003254{
3255 mProxy->releaseBuffer(buffer);
3256}
3257
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003258#undef LOG_TAG
3259#define LOG_TAG "AF::PthrPatchRecord"
3260
3261static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3262{
3263 void *ptr = nullptr;
3264 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003265 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003266}
3267
Andy Hung3ff4b552023-06-26 19:20:57 -07003268/* static */
3269sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003270 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003271 uint32_t sampleRate,
3272 audio_channel_mask_t channelMask,
3273 audio_format_t format,
3274 size_t frameCount,
3275 audio_input_flags_t flags,
3276 audio_source_t source)
3277{
3278 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003279 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003280 sampleRate,
3281 channelMask,
3282 format,
3283 frameCount,
3284 flags,
3285 source);
3286}
3287
3288PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003289 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003290 uint32_t sampleRate,
3291 audio_channel_mask_t channelMask,
3292 audio_format_t format,
3293 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003294 audio_input_flags_t flags,
3295 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003296 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003297 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003298 mPatchRecordAudioBufferProvider(*this),
3299 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3300 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3301{
3302 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3303}
3304
Andy Hung3ff4b552023-06-26 19:20:57 -07003305sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003306 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003307{
3308 *thread = mThread.promote();
3309 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003310 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07003311 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07003312 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003313}
3314
3315// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003316status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003317 Proxy::Buffer* buffer, const struct timespec* timeOut)
3318{
3319 if (mUnconsumedFrames) {
3320 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3321 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3322 return PatchRecord::obtainBuffer(buffer, timeOut);
3323 }
3324
3325 // Otherwise, execute a read from HAL and write into the buffer.
3326 nsecs_t startTimeNs = 0;
3327 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3328 // Will need to correct timeOut by elapsed time.
3329 startTimeNs = systemTime();
3330 }
3331 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3332 buffer->mFrameCount = 0;
3333 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003334 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003335 sp<StreamInHalInterface> stream = obtainStream(&thread);
3336 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3337
3338 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003339 size_t bytesRead = 0;
3340 {
3341 ATRACE_NAME("read");
3342 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3343 if (result != NO_ERROR) goto stream_error;
3344 if (bytesRead == 0) return NO_ERROR;
3345 }
3346
3347 {
Andy Hung094dc762023-08-28 19:12:14 -07003348 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003349 mReadBytes += bytesRead;
3350 mReadError = NO_ERROR;
3351 }
3352 mReadCV.notify_one();
3353 // writeFrames handles wraparound and should write all the provided frames.
3354 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3355 buffer->mFrameCount = writeFrames(
3356 &mPatchRecordAudioBufferProvider,
3357 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3358 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3359 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3360 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003361 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003362 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003363 // Correct the timeout by elapsed time.
3364 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003365 if (newTimeOutNs < 0) newTimeOutNs = 0;
3366 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3367 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003368 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003369 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003370 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003371
3372stream_error:
3373 stream->standby();
3374 {
Andy Hung094dc762023-08-28 19:12:14 -07003375 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003376 mReadError = result;
3377 }
3378 mReadCV.notify_one();
3379 return result;
3380}
3381
Andy Hung3ff4b552023-06-26 19:20:57 -07003382void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003383{
3384 if (buffer->mFrameCount <= mUnconsumedFrames) {
3385 mUnconsumedFrames -= buffer->mFrameCount;
3386 } else {
3387 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3388 buffer->mFrameCount, mUnconsumedFrames);
3389 mUnconsumedFrames = 0;
3390 }
3391 PatchRecord::releaseBuffer(buffer);
3392}
3393
3394// AudioBufferProvider and Source methods are called on RecordThread
3395// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3396// and 'releaseBuffer' are stubbed out and ignore their input.
3397// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3398// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003399status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003400 void* buffer, size_t bytes, size_t* read)
3401{
3402 bytes = std::min(bytes, mFrameCount * mFrameSize);
3403 {
Andy Hung094dc762023-08-28 19:12:14 -07003404 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003405 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3406 if (mReadError != NO_ERROR) {
3407 mLastReadFrames = 0;
3408 return mReadError;
3409 }
3410 *read = std::min(bytes, mReadBytes);
3411 mReadBytes -= *read;
3412 }
3413 mLastReadFrames = *read / mFrameSize;
3414 memset(buffer, 0, *read);
3415 return 0;
3416}
3417
Andy Hung3ff4b552023-06-26 19:20:57 -07003418status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003419 int64_t* frames, int64_t* time)
3420{
Andy Hung44f27182023-07-06 20:56:16 -07003421 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003422 sp<StreamInHalInterface> stream = obtainStream(&thread);
3423 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3424}
3425
Andy Hung3ff4b552023-06-26 19:20:57 -07003426status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003427{
3428 // RecordThread issues 'standby' command in two major cases:
3429 // 1. Error on read--this case is handled in 'obtainBuffer'.
3430 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3431 // output, this can only happen when the software patch
3432 // is being torn down. In this case, the RecordThread
3433 // will terminate and close the HAL stream.
3434 return 0;
3435}
3436
3437// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003438status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003439 AudioBufferProvider::Buffer* buffer)
3440{
3441 buffer->frameCount = mLastReadFrames;
3442 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3443 return NO_ERROR;
3444}
3445
Andy Hung3ff4b552023-06-26 19:20:57 -07003446void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003447 AudioBufferProvider::Buffer* buffer)
3448{
3449 buffer->frameCount = 0;
3450 buffer->raw = nullptr;
3451}
3452
Andy Hung9d84af52018-09-12 18:03:44 -07003453// ----------------------------------------------------------------------------
3454#undef LOG_TAG
3455#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003456
Andy Hung3ff4b552023-06-26 19:20:57 -07003457/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003458sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003459 const audio_attributes_t& attr,
3460 uint32_t sampleRate,
3461 audio_format_t format,
3462 audio_channel_mask_t channelMask,
3463 audio_session_t sessionId,
3464 bool isOut,
3465 const android::content::AttributionSourceState& attributionSource,
3466 pid_t creatorPid,
3467 audio_port_handle_t portId)
3468{
3469 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003470 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003471 attr,
3472 sampleRate,
3473 format,
3474 channelMask,
3475 sessionId,
3476 isOut,
3477 attributionSource,
3478 creatorPid,
3479 portId);
3480}
3481
Andy Hung44f27182023-07-06 20:56:16 -07003482MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003483 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003484 uint32_t sampleRate,
3485 audio_format_t format,
3486 audio_channel_mask_t channelMask,
3487 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003488 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003489 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003490 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003491 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003492 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003493 channelMask, (size_t)0 /* frameCount */,
3494 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003495 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003496 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003497 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003498 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003499 TYPE_DEFAULT, portId,
3500 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003501 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003502 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003503{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003504 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003505 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003506}
3507
Andy Hung3ff4b552023-06-26 19:20:57 -07003508MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003509{
3510}
3511
Andy Hung3ff4b552023-06-26 19:20:57 -07003512status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003513{
3514 return NO_ERROR;
3515}
3516
Andy Hung3ff4b552023-06-26 19:20:57 -07003517status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003518 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003519{
3520 return NO_ERROR;
3521}
3522
Andy Hung3ff4b552023-06-26 19:20:57 -07003523void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003524{
3525}
3526
3527// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003528status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003529{
3530 buffer->frameCount = 0;
3531 buffer->raw = nullptr;
3532 return INVALID_OPERATION;
3533}
3534
3535// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003536size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003537 return 0;
3538}
3539
Andy Hung3ff4b552023-06-26 19:20:57 -07003540int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003541{
3542 return 0;
3543}
3544
Andy Hung3ff4b552023-06-26 19:20:57 -07003545void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003546{
3547}
3548
Andy Hung3ff4b552023-06-26 19:20:57 -07003549void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003550{
3551 if (mMuteState == muteState) {
3552 // mute state did not change, do nothing
3553 return;
3554 }
3555
3556 status_t result = UNKNOWN_ERROR;
3557 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3558 if (mMuteEventExtras == nullptr) {
3559 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3560 }
3561 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3562 static_cast<int>(muteState));
3563
3564 result = audioManager->portEvent(mPortId,
3565 PLAYER_UPDATE_MUTED,
3566 mMuteEventExtras);
3567 }
3568
3569 if (result == OK) {
Andy Hung6fb26892024-02-20 16:32:57 -08003570 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
3571 static_cast<int>(mMuteState), static_cast<int>(muteState));
Vlad Popaec1788e2022-08-04 11:23:30 +02003572 mMuteState = muteState;
3573 } else {
3574 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3575 __func__,
3576 id(),
3577 mPortId,
3578 result);
3579 }
3580}
3581
Andy Hung3ff4b552023-06-26 19:20:57 -07003582void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003583{
Eric Laurent973db022018-11-20 14:54:31 -08003584 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003585 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003586}
3587
Andy Hung3ff4b552023-06-26 19:20:57 -07003588void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003589{
Eric Laurent973db022018-11-20 14:54:31 -08003590 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003591 mPid,
3592 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003593 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003594 mFormat,
3595 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003596 mSampleRate,
3597 mAttr.flags);
3598 if (isOut()) {
3599 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3600 } else {
3601 result.appendFormat("%6x", mAttr.source);
3602 }
3603 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003604}
3605
Glenn Kasten63238ef2015-03-02 15:50:29 -08003606} // namespace android