blob: 1a0068189fbb7947e44d5fe76cfd90579982d2d6 [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Eric Laurent81784c32012-11-19 14:55:58 -080018#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070020#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080021
Andy Hung0f725b42023-07-19 11:40:07 -070022#include "MmapTracks.h"
23#include "PlaybackTracks.h"
24#include "RecordTracks.h"
25
26#include "Client.h"
27#include "IAfEffect.h"
28#include "IAfThread.h"
29#include "ResamplerBufferProvider.h"
30
31#include <audio_utils/minifloat.h>
32#include <media/AudioValidator.h>
33#include <media/RecordBufferConverter.h>
34#include <media/nbaio/Pipe.h>
35#include <media/nbaio/PipeReader.h>
36#include <mediautils/ServiceUtilities.h>
37#include <mediautils/SharedMemoryAllocator.h>
38#include <private/media/AudioTrackShared.h>
Eric Laurent81784c32012-11-19 14:55:58 -080039#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070040#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080041
Andy Hung0f725b42023-07-19 11:40:07 -070042#include <linux/futex.h>
43#include <math.h>
44#include <sys/syscall.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080045
Eric Laurent81784c32012-11-19 14:55:58 -080046// ----------------------------------------------------------------------------
47
48// Note: the following macro is used for extremely verbose logging message. In
49// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
50// 0; but one side effect of this is to turn all LOGV's as well. Some messages
51// are so verbose that we want to suppress them even when we have ALOG_ASSERT
52// turned on. Do not uncomment the #def below unless you really know what you
53// are doing and want to see all of the extremely verbose messages.
54//#define VERY_VERY_VERBOSE_LOGGING
55#ifdef VERY_VERY_VERBOSE_LOGGING
56#define ALOGVV ALOGV
57#else
58#define ALOGVV(a...) do { } while(0)
59#endif
60
Kuowei Lid4adbdb2020-08-13 14:44:25 +080061// TODO: Remove when this is put into AidlConversionUtil.h
62#define VALUE_OR_RETURN_BINDER_STATUS(x) \
63 ({ \
64 auto _tmp = (x); \
65 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
66 std::move(_tmp.value()); \
67 })
68
Eric Laurent81784c32012-11-19 14:55:58 -080069namespace android {
70
Kuowei Lid4adbdb2020-08-13 14:44:25 +080071using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080072using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000073using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070074using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080075// ----------------------------------------------------------------------------
76// TrackBase
77// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070078#undef LOG_TAG
79#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080080
Glenn Kastenda6ef132013-01-10 12:31:01 -080081static volatile int32_t nextTrackId = 55;
82
Eric Laurent81784c32012-11-19 14:55:58 -080083// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung87c693c2023-07-06 20:56:16 -070085 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080086 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070087 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080088 uint32_t sampleRate,
89 audio_format_t format,
90 audio_channel_mask_t channelMask,
91 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070092 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070093 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080094 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070095 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080096 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070097 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070098 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080099 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800100 audio_port_handle_t portId,
101 std::string metricsId)
Andy Hungd29af632023-06-23 19:27:19 -0700102 :
Eric Laurent81784c32012-11-19 14:55:58 -0800103 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700104 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800105 mClient(client),
106 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700107 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800108 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700109 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800110 mSampleRate(sampleRate),
111 mFormat(format),
112 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700113 mChannelCount(isOut ?
114 audio_channel_count_from_out_mask(channelMask) :
115 audio_channel_count_from_in_mask(channelMask)),
Phil Burkfdb3c072016-02-09 10:47:02 -0800116 mFrameSize(audio_has_proportional_frames(format) ?
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
118 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800119 mSessionId(sessionId),
120 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800121 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700122 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700123 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800124 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800125 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700126 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000127 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700128 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800129{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700130 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700131 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800132 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700133 "%s(%d): uid %d tried to pass itself off as %d",
134 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800135 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800136 }
137 // clientUid contains the uid of the app that is responsible for this track, so we can blame
138 // battery usage on it.
139 mUid = clientUid;
140
Eric Laurent81784c32012-11-19 14:55:58 -0800141 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800142
Andy Hung8fe68032017-06-05 16:17:51 -0700143 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800144 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700145 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800146 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700147 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800148 android_errorWriteLog(0x534e4554, "34749571");
149 return;
150 }
Andy Hung8fe68032017-06-05 16:17:51 -0700151 minBufferSize *= mFrameSize;
152
153 if (buffer == nullptr) {
154 bufferSize = minBufferSize; // allocated here.
155 } else if (minBufferSize > bufferSize) {
156 android_errorWriteLog(0x534e4554, "38340117");
157 return;
158 }
Andy Hung1883f692017-02-13 18:48:39 -0800159
Eric Laurent81784c32012-11-19 14:55:58 -0800160 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700161 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800162 // check overflow when computing allocation size for streaming tracks.
163 if (size > SIZE_MAX - bufferSize) {
164 android_errorWriteLog(0x534e4554, "34749571");
165 return;
166 }
Eric Laurent81784c32012-11-19 14:55:58 -0800167 size += bufferSize;
168 }
169
170 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400171 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
172 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700173 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700174 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700175 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400176 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700177 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800178 return;
179 }
180 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800181 mCblk = (audio_track_cblk_t *) malloc(size);
182 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700183 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800184 return;
185 }
Eric Laurent81784c32012-11-19 14:55:58 -0800186 }
187
188 // construct the shared structure in-place.
189 if (mCblk != NULL) {
190 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700191 switch (alloc) {
192 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700193 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
194 if (roHeap == 0 ||
195 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700196 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700197 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
198 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700199 if (roHeap != 0) {
200 roHeap->dump("buffer");
201 }
202 mCblkMemory.clear();
203 mBufferMemory.clear();
204 return;
205 }
Eric Laurent81784c32012-11-19 14:55:58 -0800206 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700207 } break;
208 case ALLOC_PIPE:
209 mBufferMemory = thread->pipeMemory();
210 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700211 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700212 // However in this case the TrackBase does not reference the buffer directly.
213 // It should references the buffer via the pipe.
214 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
215 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700216 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700217 break;
218 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700219 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700220 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700221 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
222 memset(mBuffer, 0, bufferSize);
223 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700224 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800225#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700226 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800227#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700228 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700229 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700230 case ALLOC_LOCAL:
231 mBuffer = calloc(1, bufferSize);
232 break;
233 case ALLOC_NONE:
234 mBuffer = buffer;
235 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700236 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700237 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800238 }
Andy Hung8fe68032017-06-05 16:17:51 -0700239 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800240
Glenn Kasten46909e72013-02-26 09:20:22 -0800241#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700242 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800243#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700244 // mState is mirrored for the client to read.
245 mState.setMirror(&mCblk->mState);
246 // ensure our state matches up until we consolidate the enumeration.
247 static_assert(CBLK_STATE_IDLE == IDLE);
248 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800249 }
250}
251
Svet Ganov33761132021-05-13 22:51:08 +0000252// TODO b/182392769: use attribution source util
253static AttributionSourceState audioServerAttributionSource(pid_t pid) {
254 AttributionSourceState attributionSource{};
255 attributionSource.uid = AID_AUDIOSERVER;
256 attributionSource.pid = pid;
257 attributionSource.token = sp<BBinder>::make();
258 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700259}
260
Andy Hung8d31fd22023-06-26 19:20:57 -0700261status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700262{
263 status_t status;
264 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
265 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
266 } else {
267 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
268 }
269 return status;
270}
271
Andy Hung8d31fd22023-06-26 19:20:57 -0700272TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800273{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800274 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700275 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700276 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800277 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
278 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700279 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung47c01172023-07-17 12:40:43 -0700280 Mutex::Autolock _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800281 // If the client's reference count drops to zero, the associated destructor
282 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
283 // relying on the automatic clear() at end of scope.
284 mClient.clear();
285 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700286 if (mAllocType == ALLOC_LOCAL) {
287 free(mBuffer);
288 mBuffer = nullptr;
289 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700290 // flush the binder command buffer
291 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800292}
293
294// AudioBufferProvider interface
295// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800296// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung8d31fd22023-06-26 19:20:57 -0700297void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800298{
Glenn Kasten46909e72013-02-26 09:20:22 -0800299#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700300 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800301#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800302
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800303 ServerProxy::Buffer buf;
304 buf.mFrameCount = buffer->frameCount;
305 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800306 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800307 buffer->raw = NULL;
308 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800309}
310
Andy Hung8d31fd22023-06-26 19:20:57 -0700311status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700312 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800313{
Andy Hung068e08e2023-05-15 19:02:55 -0700314 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800315 return NO_ERROR;
316}
317
Andy Hung8d31fd22023-06-26 19:20:57 -0700318PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700319 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800320 : mProxy(proxy)
321{
322 if (timeout) {
323 setPeerTimeout(*timeout);
324 } else {
325 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700326 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
327 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800328 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
329 }
330}
331
Andy Hung8d31fd22023-06-26 19:20:57 -0700332void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800333 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
334 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
335}
336
337
Eric Laurent81784c32012-11-19 14:55:58 -0800338// ----------------------------------------------------------------------------
339// Playback
340// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700341#undef LOG_TAG
342#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800343
Andy Hunga5a7fc92023-06-23 19:27:19 -0700344class TrackHandle : public android::media::BnAudioTrack {
345public:
Andy Hungd29af632023-06-23 19:27:19 -0700346 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700347 ~TrackHandle() override;
348
349 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
350 binder::Status start(int32_t* _aidl_return) final;
351 binder::Status stop() final;
352 binder::Status flush() final;
353 binder::Status pause() final;
354 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
355 binder::Status setParameters(const std::string& keyValuePairs,
356 int32_t* _aidl_return) final;
357 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
358 int32_t* _aidl_return) final;
359 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
360 int32_t* _aidl_return) final;
361 binder::Status signal() final;
362 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
363 const media::VolumeShaperOperation& operation,
364 int32_t* _aidl_return) final;
365 binder::Status getVolumeShaperState(
366 int32_t id,
367 std::optional<media::VolumeShaperState>* _aidl_return) final;
368 binder::Status getDualMonoMode(
369 media::audio::common::AudioDualMonoMode* _aidl_return) final;
370 binder::Status setDualMonoMode(
371 media::audio::common::AudioDualMonoMode mode) final;
372 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
373 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
374 binder::Status getPlaybackRateParameters(
375 media::audio::common::AudioPlaybackRate* _aidl_return) final;
376 binder::Status setPlaybackRateParameters(
377 const media::audio::common::AudioPlaybackRate& playbackRate) final;
378
379private:
Andy Hungd29af632023-06-23 19:27:19 -0700380 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700381};
382
383/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700384sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700385 return sp<TrackHandle>::make(track);
386}
387
Andy Hungd29af632023-06-23 19:27:19 -0700388TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800389 : BnAudioTrack(),
390 mTrack(track)
391{
Andy Hung225aef62022-12-06 16:33:20 -0800392 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800393}
394
Andy Hunga5a7fc92023-06-23 19:27:19 -0700395TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800396 // just stop the track on deletion, associated resources
397 // will be freed from the main thread once all pending buffers have
398 // been played. Unless it's not in the active track list, in which
399 // case we free everything now...
400 mTrack->destroy();
401}
402
Andy Hunga5a7fc92023-06-23 19:27:19 -0700403Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800404 std::optional<media::SharedFileRegion>* _aidl_return) {
405 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
406 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800407}
408
Andy Hunga5a7fc92023-06-23 19:27:19 -0700409Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800410 *_aidl_return = mTrack->start();
411 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800412}
413
Andy Hunga5a7fc92023-06-23 19:27:19 -0700414Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800415 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800416 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800417}
418
Andy Hunga5a7fc92023-06-23 19:27:19 -0700419Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800420 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800422}
423
Andy Hunga5a7fc92023-06-23 19:27:19 -0700424Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800425 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800426 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800427}
428
Andy Hunga5a7fc92023-06-23 19:27:19 -0700429Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800430 int32_t* _aidl_return) {
431 *_aidl_return = mTrack->attachAuxEffect(effectId);
432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hunga5a7fc92023-06-23 19:27:19 -0700435Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800436 int32_t* _aidl_return) {
437 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
438 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700439}
440
Andy Hunga5a7fc92023-06-23 19:27:19 -0700441Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800442 int32_t* _aidl_return) {
443 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
444 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800445}
446
Andy Hunga5a7fc92023-06-23 19:27:19 -0700447Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800448 int32_t* _aidl_return) {
449 AudioTimestamp legacy;
450 *_aidl_return = mTrack->getTimestamp(legacy);
451 if (*_aidl_return != OK) {
452 return Status::ok();
453 }
Andy Hung973638a2020-12-08 20:47:45 -0800454 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800455 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800456}
457
Andy Hunga5a7fc92023-06-23 19:27:19 -0700458Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 mTrack->signal();
460 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800461}
462
Andy Hunga5a7fc92023-06-23 19:27:19 -0700463Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800464 const media::VolumeShaperConfiguration& configuration,
465 const media::VolumeShaperOperation& operation,
466 int32_t* _aidl_return) {
467 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
468 *_aidl_return = conf->readFromParcelable(configuration);
469 if (*_aidl_return != OK) {
470 return Status::ok();
471 }
472
473 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
474 *_aidl_return = op->readFromParcelable(operation);
475 if (*_aidl_return != OK) {
476 return Status::ok();
477 }
478
479 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
480 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700481}
482
Andy Hunga5a7fc92023-06-23 19:27:19 -0700483Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800484 int32_t id,
485 std::optional<media::VolumeShaperState>* _aidl_return) {
486 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
487 if (legacy == nullptr) {
488 _aidl_return->reset();
489 return Status::ok();
490 }
491 media::VolumeShaperState aidl;
492 legacy->writeToParcelable(&aidl);
493 *_aidl_return = aidl;
494 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800495}
496
Andy Hunga5a7fc92023-06-23 19:27:19 -0700497Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000498 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800499{
500 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
501 const status_t status = mTrack->getDualMonoMode(&mode)
502 ?: AudioValidator::validateDualMonoMode(mode);
503 if (status == OK) {
504 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
505 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
506 }
507 return binderStatusFromStatusT(status);
508}
509
Andy Hunga5a7fc92023-06-23 19:27:19 -0700510Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000511 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800512{
513 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
514 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
515 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
516 ?: mTrack->setDualMonoMode(localMonoMode));
517}
518
Andy Hunga5a7fc92023-06-23 19:27:19 -0700519Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800520{
521 float leveldB = -std::numeric_limits<float>::infinity();
522 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
523 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
524 if (status == OK) *_aidl_return = leveldB;
525 return binderStatusFromStatusT(status);
526}
527
Andy Hunga5a7fc92023-06-23 19:27:19 -0700528Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800529{
530 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
531 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
532}
533
Andy Hunga5a7fc92023-06-23 19:27:19 -0700534Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000535 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800536{
537 audio_playback_rate_t localPlaybackRate{};
538 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
539 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
540 if (status == NO_ERROR) {
541 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
542 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
543 }
544 return binderStatusFromStatusT(status);
545}
546
Andy Hunga5a7fc92023-06-23 19:27:19 -0700547Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000548 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800549{
550 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
551 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
552 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
553 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
554}
555
Eric Laurent81784c32012-11-19 14:55:58 -0800556// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800557// AppOp for audio playback
558// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700559
560// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700561sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700562 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000563 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700564 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800565{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700566 Vector<String16> packages;
567 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000568 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700569 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700570 if (packages.isEmpty()) {
571 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
572 id,
573 attr.usage,
574 uid);
575 return nullptr;
576 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800577 }
578 // stream type has been filtered by audio policy to indicate whether it can be muted
579 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700580 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700581 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800582 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700583 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
584 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
585 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
586 id, attr.flags);
587 return nullptr;
588 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700589 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700590}
591
Andy Hung87c693c2023-07-06 20:56:16 -0700592OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700593 const AttributionSourceState& attributionSource,
594 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700595 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700596 mHasOpPlayAudio(true),
597 mAttributionSource(attributionSource),
598 mUsage((int32_t)usage),
599 mId(id),
600 mUid(uid),
601 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
602 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800603
Andy Hung8d31fd22023-06-26 19:20:57 -0700604OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800605{
606 if (mOpCallback != 0) {
607 mAppOpsManager.stopWatchingMode(mOpCallback);
608 }
609 mOpCallback.clear();
610}
611
Andy Hung8d31fd22023-06-26 19:20:57 -0700612void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700613{
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700614 checkPlayAudioForUsage();
Svet Ganov33761132021-05-13 22:51:08 +0000615 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700616 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700617 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700618 mPackageName, mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700619 }
620}
621
Andy Hung8d31fd22023-06-26 19:20:57 -0700622bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800623 return mHasOpPlayAudio.load();
624}
625
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700626// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800627// - not called from constructor due to check on UID,
628// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung8d31fd22023-06-26 19:20:57 -0700629void OpPlayAudioMonitor::checkPlayAudioForUsage()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800630{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700631 const bool hasAppOps = mAttributionSource.packageName.has_value()
632 && mAppOpsManager.checkAudioOpNoThrow(
633 AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
634 AppOpsManager::MODE_ALLOWED;
635
636 bool shouldChange = !hasAppOps; // check if we need to update.
637 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
638 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
639 auto thread = mThread.promote();
Andy Hungee58e4a2023-07-07 13:47:37 -0700640 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700641 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87c693c2023-07-06 20:56:16 -0700642 Mutex::Autolock _l(thread->mutex());
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700643 thread->broadcast_l();
644 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800645 }
646}
647
Andy Hung8d31fd22023-06-26 19:20:57 -0700648OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800649 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
650{ }
651
Andy Hung8d31fd22023-06-26 19:20:57 -0700652void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800653 const String16& packageName) {
654 // we only have uid, so we need to check all package names anyway
655 UNUSED(packageName);
656 if (op != AppOpsManager::OP_PLAY_AUDIO) {
657 return;
658 }
659 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
660 if (monitor != NULL) {
661 monitor->checkPlayAudioForUsage();
662 }
663}
664
Eric Laurent9066ad32019-05-20 14:40:10 -0700665// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700666void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700667 uid_t uid, Vector<String16>& packages)
668{
669 PermissionController permissionController;
670 permissionController.getPackagesForUid(uid, packages);
671}
672
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800673// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700674#undef LOG_TAG
675#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800676
Andy Hung8d31fd22023-06-26 19:20:57 -0700677/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700678sp<IAfTrack> IAfTrack::create(
679 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700680 const sp<Client>& client,
681 audio_stream_type_t streamType,
682 const audio_attributes_t& attr,
683 uint32_t sampleRate,
684 audio_format_t format,
685 audio_channel_mask_t channelMask,
686 size_t frameCount,
687 void *buffer,
688 size_t bufferSize,
689 const sp<IMemory>& sharedBuffer,
690 audio_session_t sessionId,
691 pid_t creatorPid,
692 const AttributionSourceState& attributionSource,
693 audio_output_flags_t flags,
694 track_type type,
695 audio_port_handle_t portId,
696 /** default behaviour is to start when there are as many frames
697 * ready as possible (aka. Buffer is full). */
698 size_t frameCountToBeReady,
699 float speed,
700 bool isSpatialized,
701 bool isBitPerfect) {
Andy Hung87c693c2023-07-06 20:56:16 -0700702 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700703 client,
704 streamType,
705 attr,
706 sampleRate,
707 format,
708 channelMask,
709 frameCount,
710 buffer,
711 bufferSize,
712 sharedBuffer,
713 sessionId,
714 creatorPid,
715 attributionSource,
716 flags,
717 type,
718 portId,
719 frameCountToBeReady,
720 speed,
721 isSpatialized,
722 isBitPerfect);
723}
724
Eric Laurent81784c32012-11-19 14:55:58 -0800725// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700726Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700727 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800728 const sp<Client>& client,
729 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700730 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800731 uint32_t sampleRate,
732 audio_format_t format,
733 audio_channel_mask_t channelMask,
734 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700735 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700736 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800737 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800738 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700739 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000740 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700741 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800742 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100743 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000744 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200745 float speed,
jiabinc658e452022-10-21 20:52:21 +0000746 bool isSpatialized,
747 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700748 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700749 // TODO: Using unsecurePointer() has some associated security pitfalls
750 // (see declaration for details).
751 // Either document why it is safe in this case or address the
752 // issue (e.g. by copying).
753 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700754 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700755 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000756 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700757 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800758 type,
759 portId,
760 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700761 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800762 // mRetryCount initialized later when needed
763 mSharedBuffer(sharedBuffer),
764 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700765 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800766 mAuxBuffer(NULL),
767 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700768 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700769 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700770 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700771 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700772 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800773 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800774 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700775 /* The track might not play immediately after being active, similarly as if its volume was 0.
776 * When the track starts playing, its volume will be computed. */
777 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800778 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700779 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000780 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200781 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000782 mIsSpatialized(isSpatialized),
783 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800784{
Eric Laurent83b88082014-06-20 18:31:16 -0700785 // client == 0 implies sharedBuffer == 0
786 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
787
Andy Hung9d84af52018-09-12 18:03:44 -0700788 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700789 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700790
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700791 if (mCblk == NULL) {
792 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800793 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700794
Svet Ganov33761132021-05-13 22:51:08 +0000795 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700796 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
797 ALOGE("%s(%d): no more tracks available", __func__, mId);
798 releaseCblk(); // this makes the track invalid.
799 return;
800 }
801
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700802 if (sharedBuffer == 0) {
803 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700804 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700805 } else {
806 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100807 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700808 }
809 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700810 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700811
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700812 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700813 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700814 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
815 // race with setSyncEvent(). However, if we call it, we cannot properly start
816 // static fast tracks (SoundPool) immediately after stopping.
817 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700818 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
819 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700820 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700821 // FIXME This is too eager. We allocate a fast track index before the
822 // fast track becomes active. Since fast tracks are a scarce resource,
823 // this means we are potentially denying other more important fast tracks from
824 // being created. It would be better to allocate the index dynamically.
825 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700826 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700827 }
Andy Hung8946a282018-04-19 20:04:56 -0700828
Dean Wheatley7b036912020-06-18 16:22:11 +1000829 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700830#ifdef TEE_SINK
831 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800832 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700833#endif
jiabin57303cc2018-12-18 15:45:57 -0800834
jiabineb3bda02020-06-30 14:07:03 -0700835 if (thread->supportsHapticPlayback()) {
836 // If the track is attached to haptic playback thread, it is potentially to have
837 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
838 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800839 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000840 std::string packageName = attributionSource.packageName.has_value() ?
841 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800842 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700843 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800844 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800845
846 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700847 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800848 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800849}
850
Andy Hung8d31fd22023-06-26 19:20:57 -0700851Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800852{
Andy Hung9d84af52018-09-12 18:03:44 -0700853 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700854
855 // The destructor would clear mSharedBuffer,
856 // but it will not push the decremented reference count,
857 // leaving the client's IMemory dangling indefinitely.
858 // This prevents that leak.
859 if (mSharedBuffer != 0) {
860 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700861 }
Eric Laurent81784c32012-11-19 14:55:58 -0800862}
863
Andy Hung8d31fd22023-06-26 19:20:57 -0700864status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700865{
866 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700867 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700868 status = NO_MEMORY;
869 }
870 return status;
871}
872
Andy Hung8d31fd22023-06-26 19:20:57 -0700873void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800874{
875 // NOTE: destroyTrack_l() can remove a strong reference to this Track
876 // by removing it from mTracks vector, so there is a risk that this Tracks's
877 // destructor is called. As the destructor needs to lock mLock,
878 // we must acquire a strong reference on this Track before locking mLock
879 // here so that the destructor is called only when exiting this function.
880 // On the other hand, as long as Track::destroy() is only called by
881 // TrackHandle destructor, the TrackHandle still holds a strong ref on
882 // this Track with its member mTrack.
883 sp<Track> keep(this);
884 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700885 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700886 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800887 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -0700888 Mutex::Autolock _l(thread->mutex());
889 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700890 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000891 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700892 }
893 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700894 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800895 }
896 }
897}
898
Andy Hung8d31fd22023-06-26 19:20:57 -0700899void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800900{
Eric Laurent973db022018-11-20 14:54:31 -0800901 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700902 " Format Chn mask SRate "
903 "ST Usg CT "
904 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000905 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700906 "%s\n",
907 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800908}
909
Andy Hung8d31fd22023-06-26 19:20:57 -0700910void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800911{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700912 char trackType;
913 switch (mType) {
914 case TYPE_DEFAULT:
915 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700916 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700917 trackType = 'S'; // static
918 } else {
919 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800920 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700921 break;
922 case TYPE_PATCH:
923 trackType = 'P';
924 break;
925 default:
926 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800927 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700928
929 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700930 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700931 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700932 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700933 }
934
Eric Laurent81784c32012-11-19 14:55:58 -0800935 char nowInUnderrun;
936 switch (mObservedUnderruns.mBitFields.mMostRecent) {
937 case UNDERRUN_FULL:
938 nowInUnderrun = ' ';
939 break;
940 case UNDERRUN_PARTIAL:
941 nowInUnderrun = '<';
942 break;
943 case UNDERRUN_EMPTY:
944 nowInUnderrun = '*';
945 break;
946 default:
947 nowInUnderrun = '?';
948 break;
949 }
Andy Hungda540db2017-04-20 14:06:17 -0700950
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700951 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700952 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700953 case FS_INVALID:
954 fillingStatus = 'I';
955 break;
956 case FS_FILLING:
957 fillingStatus = 'f';
958 break;
959 case FS_FILLED:
960 fillingStatus = 'F';
961 break;
962 case FS_ACTIVE:
963 fillingStatus = 'A';
964 break;
965 default:
966 fillingStatus = '?';
967 break;
968 }
969
970 // clip framesReadySafe to max representation in dump
971 const size_t framesReadySafe =
972 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
973
974 // obtain volumes
975 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
976 const std::pair<float /* volume */, bool /* active */> vsVolume =
977 mVolumeHandler->getLastVolume();
978
979 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
980 // as it may be reduced by the application.
981 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
982 // Check whether the buffer size has been modified by the app.
983 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
984 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
985 ? 'e' /* error */ : ' ' /* identical */;
986
Eric Laurent973db022018-11-20 14:54:31 -0800987 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700988 "%08X %08X %6u "
989 "%2u %3x %2x "
990 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000991 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800992 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700993 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700994 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -0800995 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -0800996 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700997 mCblk->mFlags,
998
Eric Laurent81784c32012-11-19 14:55:58 -0800999 mFormat,
1000 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001001 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001002
1003 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001004 mAttr.usage,
1005 mAttr.content_type,
1006
1007 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001008 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1009 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001010 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1011 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001012
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001013 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001014 bufferSizeInFrames,
1015 modifiedBufferChar,
1016 framesReadySafe,
1017 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001018 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001019 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001020 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1021 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001022 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001023
1024 if (isServerLatencySupported()) {
1025 double latencyMs;
1026 bool fromTrack;
1027 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1028 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1029 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1030 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001031 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001032 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001033 }
1034 }
1035 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001036}
1037
Andy Hung8d31fd22023-06-26 19:20:57 -07001038uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001039 return mAudioTrackServerProxy->getSampleRate();
1040}
1041
Eric Laurent81784c32012-11-19 14:55:58 -08001042// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001043status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001044{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001045 ServerProxy::Buffer buf;
1046 size_t desiredFrames = buffer->frameCount;
1047 buf.mFrameCount = desiredFrames;
1048 status_t status = mServerProxy->obtainBuffer(&buf);
1049 buffer->frameCount = buf.mFrameCount;
1050 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001051 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001052 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001053 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001054 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001055 } else {
1056 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001057 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001058 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001059}
1060
Andy Hung8d31fd22023-06-26 19:20:57 -07001061void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001062{
1063 interceptBuffer(*buffer);
1064 TrackBase::releaseBuffer(buffer);
1065}
1066
1067// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001068void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001069 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001070 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001071 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001072 if (frameCount == 0) {
1073 return; // No audio to intercept.
1074 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1075 // does not allow 0 frame size request contrary to getNextBuffer
1076 }
1077 for (auto& teePatch : mTeePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001078 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001079 const size_t framesWritten = patchRecord->writeFrames(
1080 sourceBuffer.i8, frameCount, mFrameSize);
1081 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001082 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001083 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001084 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001085 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001086 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1087 using namespace std::chrono_literals;
1088 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001089 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001090 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001091}
1092
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001093// ExtendedAudioBufferProvider interface
1094
Andy Hung27876c02014-09-09 18:07:55 -07001095// framesReady() may return an approximation of the number of frames if called
1096// from a different thread than the one calling Proxy->obtainBuffer() and
1097// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1098// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001099size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001100 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1101 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1102 // The remainder of the buffer is not drained.
1103 return 0;
1104 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001105 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001106}
1107
Andy Hung8d31fd22023-06-26 19:20:57 -07001108int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001109{
1110 return mAudioTrackServerProxy->framesReleased();
1111}
1112
Andy Hung8d31fd22023-06-26 19:20:57 -07001113void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001114{
1115 // This call comes from a FastTrack and should be kept lockless.
1116 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001117 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001118
Andy Hung818e7a32016-02-16 18:08:07 -08001119 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001120
1121 // Compute latency.
1122 // TODO: Consider whether the server latency may be passed in by FastMixer
1123 // as a constant for all active FastTracks.
1124 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1125 mServerLatencyFromTrack.store(true);
1126 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001127}
1128
Eric Laurent81784c32012-11-19 14:55:58 -08001129// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001130bool Track::isReady() const {
1131 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001132 return true;
1133 }
1134
Eric Laurent16498512014-03-17 17:22:08 -07001135 if (isStopping()) {
1136 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001137 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001138 }
Eric Laurent81784c32012-11-19 14:55:58 -08001139 return true;
1140 }
1141
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001142 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001143 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1144 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1145 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1146 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001147
1148 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1149 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1150 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001151 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001152 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001153 return true;
1154 }
1155 return false;
1156}
1157
Andy Hung8d31fd22023-06-26 19:20:57 -07001158status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001159 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001160{
1161 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001162 ALOGV("%s(%d): calling pid %d session %d",
1163 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001164
Andy Hung87c693c2023-07-06 20:56:16 -07001165 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001166 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001167 if (isOffloaded()) {
Andy Hung583043b2023-07-17 17:05:00 -07001168 Mutex::Autolock _laf(thread->afThreadCallback()->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001169 Mutex::Autolock _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001170 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung583043b2023-07-17 17:05:00 -07001171 if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001172 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001173 invalidate();
1174 return PERMISSION_DENIED;
1175 }
1176 }
Andy Hung87c693c2023-07-06 20:56:16 -07001177 Mutex::Autolock _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001178 track_state state = mState;
1179 // here the track could be either new, or restarted
1180 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001181
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001182 // initial state-stopping. next state-pausing.
1183 // What if resume is called ?
1184
Zhou Song1ed46a22020-08-17 15:36:56 +08001185 if (state == FLUSHED) {
1186 // avoid underrun glitches when starting after flush
1187 reset();
1188 }
1189
kuowei.li576f1362021-05-11 18:02:32 +08001190 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1191 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001192 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001193 if (mResumeToStopping) {
1194 // happened we need to resume to STOPPING_1
1195 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001196 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1197 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001198 } else {
1199 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001200 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1201 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001202 }
Eric Laurent81784c32012-11-19 14:55:58 -08001203 } else {
1204 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001205 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1206 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001207 }
1208
Andy Hung87c693c2023-07-06 20:56:16 -07001209 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001210
1211 // states to reset position info for pcm tracks
1212 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001213 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1214 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001215
1216 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1217 // Start point of track -> sink frame map. If the HAL returns a
1218 // frame position smaller than the first written frame in
1219 // updateTrackFrameInfo, the timestamp can be interpolated
1220 // instead of using a larger value.
1221 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1222 playbackThread->framesWritten());
1223 }
Andy Hunge10393e2015-06-12 13:59:33 -07001224 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001225 if (isFastTrack()) {
1226 // refresh fast track underruns on start because that field is never cleared
1227 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1228 // after stop.
1229 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1230 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001231 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001232 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001233 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001234 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001235 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001236 mState = state;
1237 }
1238 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001239
Andy Hungb68f5eb2019-12-03 16:49:17 -08001240 // Audio timing metrics are computed a few mix cycles after starting.
1241 {
1242 mLogStartCountdown = LOG_START_COUNTDOWN;
1243 mLogStartTimeNs = systemTime();
1244 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001245 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1246 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001247 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001248 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001249
Andy Hung1d3556d2018-03-29 16:30:14 -07001250 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1251 // for streaming tracks, remove the buffer read stop limit.
1252 mAudioTrackServerProxy->start();
1253 }
1254
Eric Laurentbfb1b832013-01-07 09:53:42 -08001255 // track was already in the active list, not a problem
1256 if (status == ALREADY_EXISTS) {
1257 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001258 } else {
1259 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1260 // It is usually unsafe to access the server proxy from a binder thread.
1261 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1262 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1263 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001264 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001265 ServerProxy::Buffer buffer;
1266 buffer.mFrameCount = 1;
1267 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001268 }
jiabin7434e812023-06-27 18:22:35 +00001269 if (status == NO_ERROR) {
1270 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1271 }
Eric Laurent81784c32012-11-19 14:55:58 -08001272 } else {
1273 status = BAD_VALUE;
1274 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001275 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001276 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001277 const sp<IAudioManager> audioManager =
1278 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001279 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1280 std::unique_ptr<os::PersistableBundle> bundle =
1281 std::make_unique<os::PersistableBundle>();
1282 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1283 isSpatialized());
1284 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1285 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1286 status_t result = audioManager->portEvent(mPortId,
1287 PLAYER_UPDATE_FORMAT, bundle);
1288 if (result != OK) {
1289 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1290 __func__, mPortId, result);
1291 }
1292 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001293 }
Eric Laurent81784c32012-11-19 14:55:58 -08001294 return status;
1295}
1296
Andy Hung8d31fd22023-06-26 19:20:57 -07001297void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001298{
Andy Hungc0691382018-09-12 18:01:57 -07001299 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001300 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001301 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001302 Mutex::Autolock _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001303 track_state state = mState;
1304 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1305 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001306 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1307 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001308 reset();
1309 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001310 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001311 mState = STOPPED;
1312 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001313 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1314 // presentation is complete
1315 // For an offloaded track this starts a drain and state will
1316 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001317 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001318 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001319 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001320 }
Eric Laurent81784c32012-11-19 14:55:58 -08001321 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001322 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001323 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1324 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001325 }
jiabin7434e812023-06-27 18:22:35 +00001326 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001327 }
1328}
1329
Andy Hung8d31fd22023-06-26 19:20:57 -07001330void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001331{
Andy Hungc0691382018-09-12 18:01:57 -07001332 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001333 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001334 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001335 Mutex::Autolock _l(thread->mutex());
1336 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001337 switch (mState) {
1338 case STOPPING_1:
1339 case STOPPING_2:
1340 if (!isOffloaded()) {
1341 /* nothing to do if track is not offloaded */
1342 break;
1343 }
1344
1345 // Offloaded track was draining, we need to carry on draining when resumed
1346 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001347 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001348 case ACTIVE:
1349 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001350 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001351 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1352 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001353 if (isOffloadedOrDirect()) {
1354 mPauseHwPending = true;
1355 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001356 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001357 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001358
Eric Laurentbfb1b832013-01-07 09:53:42 -08001359 default:
1360 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001361 }
jiabin7434e812023-06-27 18:22:35 +00001362 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1363 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001364 }
1365}
1366
Andy Hung8d31fd22023-06-26 19:20:57 -07001367void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001368{
Andy Hungc0691382018-09-12 18:01:57 -07001369 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001370 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001371 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001372 Mutex::Autolock _l(thread->mutex());
1373 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001374
Phil Burk4bb650b2016-09-09 12:11:17 -07001375 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1376 // Otherwise the flush would not be done until the track is resumed.
1377 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001378 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001379 (void)mServerProxy->flushBufferIfNeeded();
1380 }
1381
Eric Laurentbfb1b832013-01-07 09:53:42 -08001382 if (isOffloaded()) {
1383 // If offloaded we allow flush during any state except terminated
1384 // and keep the track active to avoid problems if user is seeking
1385 // rapidly and underlying hardware has a significant delay handling
1386 // a pause
1387 if (isTerminated()) {
1388 return;
1389 }
1390
Andy Hung9d84af52018-09-12 18:03:44 -07001391 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001392 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001393
1394 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001395 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1396 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001397 mState = ACTIVE;
1398 }
1399
Haynes Mathew George7844f672014-01-15 12:32:55 -08001400 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001401 mResumeToStopping = false;
1402 } else {
1403 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1404 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1405 return;
1406 }
1407 // No point remaining in PAUSED state after a flush => go to
1408 // FLUSHED state
1409 mState = FLUSHED;
1410 // do not reset the track if it is still in the process of being stopped or paused.
1411 // this will be done by prepareTracks_l() when the track is stopped.
1412 // prepareTracks_l() will see mState == FLUSHED, then
1413 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001414 if (isDirect()) {
1415 mFlushHwPending = true;
1416 }
Andy Hung87c693c2023-07-06 20:56:16 -07001417 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001418 reset();
1419 }
Eric Laurent81784c32012-11-19 14:55:58 -08001420 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001421 // Prevent flush being lost if the track is flushed and then resumed
1422 // before mixer thread can run. This is important when offloading
1423 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001424 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001425 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1426 // new data
1427 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001428 }
1429}
1430
Haynes Mathew George7844f672014-01-15 12:32:55 -08001431// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001432void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001433{
Andy Hung920f6572022-10-06 12:09:49 -07001434 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001435 return;
Andy Hung920f6572022-10-06 12:09:49 -07001436 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001437
Phil Burk4bb650b2016-09-09 12:11:17 -07001438 // Clear the client ring buffer so that the app can prime the buffer while paused.
1439 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1440 mServerProxy->flushBufferIfNeeded();
1441
Haynes Mathew George7844f672014-01-15 12:32:55 -08001442 mFlushHwPending = false;
1443}
1444
Andy Hung8d31fd22023-06-26 19:20:57 -07001445void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001446{
1447 mPauseHwPending = false;
1448}
1449
Andy Hung8d31fd22023-06-26 19:20:57 -07001450void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001451{
1452 // Do not reset twice to avoid discarding data written just after a flush and before
1453 // the audioflinger thread detects the track is stopped.
1454 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001455 // Force underrun condition to avoid false underrun callback until first data is
1456 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001457 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001458 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001459 mResetDone = true;
1460 if (mState == FLUSHED) {
1461 mState = IDLE;
1462 }
1463 }
1464}
1465
Andy Hung8d31fd22023-06-26 19:20:57 -07001466status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001467{
Andy Hung87c693c2023-07-06 20:56:16 -07001468 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001469 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001470 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001471 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001472 } else if (thread->type() == IAfThreadBase::DIRECT
1473 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001474 return thread->setParameters(keyValuePairs);
1475 } else {
1476 return PERMISSION_DENIED;
1477 }
1478}
1479
Andy Hung8d31fd22023-06-26 19:20:57 -07001480status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001481 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001482 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001483 if (thread == 0) {
1484 ALOGE("thread is dead");
1485 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001486 } else if (thread->type() == IAfThreadBase::DIRECT
1487 || thread->type() == IAfThreadBase::OFFLOAD) {
1488 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001489 return directOutputThread->selectPresentation(presentationId, programId);
1490 }
1491 return INVALID_OPERATION;
1492}
1493
Andy Hung8d31fd22023-06-26 19:20:57 -07001494VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001495 const sp<VolumeShaper::Configuration>& configuration,
1496 const sp<VolumeShaper::Operation>& operation)
1497{
Andy Hung398ffa22022-12-13 19:19:53 -08001498 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001499
1500 if (isOffloadedOrDirect()) {
1501 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001502 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001503 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001504 Mutex::Autolock _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001505 thread->broadcast_l();
1506 }
1507 }
1508 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001509}
1510
Andy Hung8d31fd22023-06-26 19:20:57 -07001511sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001512{
1513 // Note: We don't check if Thread exists.
1514
1515 // mVolumeHandler is thread safe.
1516 return mVolumeHandler->getVolumeShaperState(id);
1517}
1518
Andy Hung8d31fd22023-06-26 19:20:57 -07001519void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001520{
jiabin76d94692022-12-15 21:51:21 +00001521 mFinalVolumeLeft = volumeLeft;
1522 mFinalVolumeRight = volumeRight;
1523 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001524 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1525 mFinalVolume = volume;
1526 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001527 mLogForceVolumeUpdate = true;
1528 }
1529 if (mLogForceVolumeUpdate) {
1530 mLogForceVolumeUpdate = false;
1531 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001532 }
1533}
1534
Andy Hung8d31fd22023-06-26 19:20:57 -07001535void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001536{
Eric Laurent49e39282022-06-24 18:42:45 +02001537 // Do not forward metadata for PatchTrack with unspecified stream type
1538 if (mStreamType == AUDIO_STREAM_PATCH) {
1539 return;
1540 }
1541
Eric Laurent94579172020-11-20 18:41:04 +01001542 playback_track_metadata_v7_t metadata;
1543 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001544 .usage = mAttr.usage,
1545 .content_type = mAttr.content_type,
1546 .gain = mFinalVolume,
1547 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001548
1549 // When attributes are undefined, derive default values from stream type.
1550 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1551 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1552 switch (mStreamType) {
1553 case AUDIO_STREAM_VOICE_CALL:
1554 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1555 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1556 break;
1557 case AUDIO_STREAM_SYSTEM:
1558 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1559 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1560 break;
1561 case AUDIO_STREAM_RING:
1562 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1563 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1564 break;
1565 case AUDIO_STREAM_MUSIC:
1566 metadata.base.usage = AUDIO_USAGE_MEDIA;
1567 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1568 break;
1569 case AUDIO_STREAM_ALARM:
1570 metadata.base.usage = AUDIO_USAGE_ALARM;
1571 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1572 break;
1573 case AUDIO_STREAM_NOTIFICATION:
1574 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1575 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1576 break;
1577 case AUDIO_STREAM_DTMF:
1578 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1579 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1580 break;
1581 case AUDIO_STREAM_ACCESSIBILITY:
1582 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1583 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1584 break;
1585 case AUDIO_STREAM_ASSISTANT:
1586 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1587 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1588 break;
1589 case AUDIO_STREAM_REROUTING:
1590 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1591 // unknown content type
1592 break;
1593 case AUDIO_STREAM_CALL_ASSISTANT:
1594 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1595 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1596 break;
1597 default:
1598 break;
1599 }
1600 }
1601
Eric Laurent78b07302022-10-07 16:20:34 +02001602 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001603 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1604 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001605}
1606
Andy Hung8d31fd22023-06-26 19:20:57 -07001607void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001608 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001609 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001610 mTeePatches = mTeePatchesToUpdate.value();
1611 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1612 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001613 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001614 }
1615 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001616 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001617}
1618
Andy Hung16ed0da2023-07-14 11:45:38 -07001619void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001620 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1621 "%s, existing tee patches to update will be ignored", __func__);
1622 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1623}
1624
Vlad Popae8d99472022-06-30 16:02:48 +02001625// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001626void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001627 IAudioManager>& audioManager, mute_state_t muteState)
1628{
1629 if (mMuteState == muteState) {
1630 // mute state did not change, do nothing
1631 return;
1632 }
1633
1634 status_t result = UNKNOWN_ERROR;
1635 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1636 if (mMuteEventExtras == nullptr) {
1637 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1638 }
1639 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1640 static_cast<int>(muteState));
1641
1642 result = audioManager->portEvent(mPortId,
1643 PLAYER_UPDATE_MUTED,
1644 mMuteEventExtras);
1645 }
1646
1647 if (result == OK) {
1648 mMuteState = muteState;
1649 } else {
1650 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1651 __func__,
1652 id(),
1653 mPortId,
1654 result);
1655 }
1656}
1657
Andy Hung8d31fd22023-06-26 19:20:57 -07001658status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001659{
Andy Hung818e7a32016-02-16 18:08:07 -08001660 if (!isOffloaded() && !isDirect()) {
1661 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001662 }
Andy Hung87c693c2023-07-06 20:56:16 -07001663 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001664 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001665 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001666 }
Phil Burk6140c792015-03-19 14:30:21 -07001667
Andy Hung87c693c2023-07-06 20:56:16 -07001668 Mutex::Autolock _l(thread->mutex());
1669 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001670 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001671}
1672
Andy Hung8d31fd22023-06-26 19:20:57 -07001673status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001674{
Andy Hung87c693c2023-07-06 20:56:16 -07001675 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001676 if (thread == nullptr) {
1677 return DEAD_OBJECT;
1678 }
Eric Laurent81784c32012-11-19 14:55:58 -08001679
Andy Hung87c693c2023-07-06 20:56:16 -07001680 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001681 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001682 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001683 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001684 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001685
Eric Laurent6c796322019-04-09 14:13:17 -07001686 if (EffectId != 0 && status == NO_ERROR) {
1687 status = dstThread->attachAuxEffect(this, EffectId);
1688 if (status == NO_ERROR) {
1689 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001690 }
Eric Laurent6c796322019-04-09 14:13:17 -07001691 }
1692
1693 if (status != NO_ERROR && srcThread != nullptr) {
1694 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001695 }
1696 return status;
1697}
1698
Andy Hung8d31fd22023-06-26 19:20:57 -07001699void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001700{
1701 mAuxEffectId = EffectId;
1702 mAuxBuffer = buffer;
1703}
1704
Andy Hung59de4262021-06-14 10:53:54 -07001705// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001706bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001707 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001708{
Andy Hung818e7a32016-02-16 18:08:07 -08001709 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1710 // This assists in proper timestamp computation as well as wakelock management.
1711
Eric Laurent81784c32012-11-19 14:55:58 -08001712 // a track is considered presented when the total number of frames written to audio HAL
1713 // corresponds to the number of frames written when presentationComplete() is called for the
1714 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001715 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1716 // to detect when all frames have been played. In this case framesWritten isn't
1717 // useful because it doesn't always reflect whether there is data in the h/w
1718 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001719 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1720 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001721 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001722 if (mPresentationCompleteFrames == 0) {
1723 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001724 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001725 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1726 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001727 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001728 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001729
Andy Hungc54b1ff2016-02-23 14:07:07 -08001730 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001731 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001732 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001733 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1734 __func__, mId, (complete ? "complete" : "waiting"),
1735 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001736 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001737 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001738 && mAudioTrackServerProxy->isDrained();
1739 }
1740
1741 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001742 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001743 return true;
1744 }
1745 return false;
1746}
1747
Andy Hung59de4262021-06-14 10:53:54 -07001748// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001749bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001750{
1751 // For Offloaded or Direct tracks.
1752
1753 // For a direct track, we incorporated time based testing for presentationComplete.
1754
1755 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1756 // to detect when all frames have been played. In this case latencyMs isn't
1757 // useful because it doesn't always reflect whether there is data in the h/w
1758 // buffers, particularly if a track has been paused and resumed during draining
1759
1760 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1761 if (mPresentationCompleteTimeNs == 0) {
1762 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1763 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1764 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1765 }
1766
1767 bool complete;
1768 if (isOffloaded()) {
1769 complete = true;
1770 } else { // Direct
1771 complete = systemTime() >= mPresentationCompleteTimeNs;
1772 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1773 }
1774 if (complete) {
1775 notifyPresentationComplete();
1776 return true;
1777 }
1778 return false;
1779}
1780
Andy Hung8d31fd22023-06-26 19:20:57 -07001781void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001782{
1783 // This only triggers once. TODO: should we enforce this?
1784 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1785 mAudioTrackServerProxy->setStreamEndDone();
1786}
1787
Andy Hung8d31fd22023-06-26 19:20:57 -07001788void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001789{
Andy Hung068e08e2023-05-15 19:02:55 -07001790 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1791 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001792 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001793 (*it)->trigger();
1794 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001795 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001796 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001797 }
1798 }
1799}
1800
1801// implement VolumeBufferProvider interface
1802
Andy Hung8d31fd22023-06-26 19:20:57 -07001803gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001804{
1805 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1806 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001807 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1808 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1809 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001810 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001811 if (vl > GAIN_FLOAT_UNITY) {
1812 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001813 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001814 if (vr > GAIN_FLOAT_UNITY) {
1815 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001816 }
1817 // now apply the cached master volume and stream type volume;
1818 // this is trusted but lacks any synchronization or barrier so may be stale
1819 float v = mCachedVolume;
1820 vl *= v;
1821 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001822 // re-combine into packed minifloat
1823 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001824 // FIXME look at mute, pause, and stop flags
1825 return vlr;
1826}
1827
Andy Hung8d31fd22023-06-26 19:20:57 -07001828status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001829 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001830{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001831 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001832 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1833 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001834 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1835 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001836 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001837 event->cancel();
1838 return INVALID_OPERATION;
1839 }
1840 (void) TrackBase::setSyncEvent(event);
1841 return NO_ERROR;
1842}
1843
Andy Hung8d31fd22023-06-26 19:20:57 -07001844void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001845{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001846 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001847 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001848}
1849
Andy Hung8d31fd22023-06-26 19:20:57 -07001850void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001851{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001852 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001853 signalClientFlag(CBLK_DISABLED);
1854}
1855
Andy Hung8d31fd22023-06-26 19:20:57 -07001856void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001857{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001858 // FIXME should use proxy, and needs work
1859 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001860 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001861 android_atomic_release_store(0x40000000, &cblk->mFutex);
1862 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001863 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001864}
1865
Andy Hung8d31fd22023-06-26 19:20:57 -07001866void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001867{
Andy Hung87c693c2023-07-06 20:56:16 -07001868 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001869 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001870 auto* const t = thread->asIAfPlaybackThread().get();
1871 Mutex::Autolock _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001872 t->broadcast_l();
1873 }
1874}
1875
Andy Hung8d31fd22023-06-26 19:20:57 -07001876status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001877{
1878 status_t status = INVALID_OPERATION;
1879 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001880 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001881 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001882 auto* const t = thread->asIAfPlaybackThread().get();
1883 Mutex::Autolock _l(t->mutex());
1884 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001885 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1886 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1887 }
1888 }
1889 return status;
1890}
1891
Andy Hung8d31fd22023-06-26 19:20:57 -07001892status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001893{
1894 status_t status = INVALID_OPERATION;
1895 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001896 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001897 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001898 auto* const t = thread->asIAfPlaybackThread().get();
1899 Mutex::Autolock lock(t->mutex());
1900 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001901 if (status == NO_ERROR) {
1902 mDualMonoMode = mode;
1903 }
1904 }
1905 }
1906 return status;
1907}
1908
Andy Hung8d31fd22023-06-26 19:20:57 -07001909status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001910{
1911 status_t status = INVALID_OPERATION;
1912 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001913 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001914 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001915 auto* const t = thread->asIAfPlaybackThread().get();
1916 Mutex::Autolock lock(t->mutex());
1917 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001918 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1919 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1920 }
1921 }
1922 return status;
1923}
1924
Andy Hung8d31fd22023-06-26 19:20:57 -07001925status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001926{
1927 status_t status = INVALID_OPERATION;
1928 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001929 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001930 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001931 auto* const t = thread->asIAfPlaybackThread().get();
1932 Mutex::Autolock lock(t->mutex());
1933 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001934 if (status == NO_ERROR) {
1935 mAudioDescriptionMixLevel = leveldB;
1936 }
1937 }
1938 }
1939 return status;
1940}
1941
Andy Hung8d31fd22023-06-26 19:20:57 -07001942status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001943 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001944{
1945 status_t status = INVALID_OPERATION;
1946 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001947 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001948 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001949 auto* const t = thread->asIAfPlaybackThread().get();
1950 Mutex::Autolock lock(t->mutex());
1951 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001952 ALOGD_IF((status == NO_ERROR) &&
1953 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1954 "%s: playbackRate inconsistent", __func__);
1955 }
1956 }
1957 return status;
1958}
1959
Andy Hung8d31fd22023-06-26 19:20:57 -07001960status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001961 const audio_playback_rate_t& playbackRate)
1962{
1963 status_t status = INVALID_OPERATION;
1964 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001965 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001966 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001967 auto* const t = thread->asIAfPlaybackThread().get();
1968 Mutex::Autolock lock(t->mutex());
1969 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001970 if (status == NO_ERROR) {
1971 mPlaybackRateParameters = playbackRate;
1972 }
1973 }
1974 }
1975 return status;
1976}
1977
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001978//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001979bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07001980 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001981 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001982 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001983 /* Resume is pending if track was stopping before pause was called */
1984 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07001985 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001986 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001987 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001988
1989 return false;
1990}
1991
1992//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001993void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07001994 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001995 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07001996 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001997
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001998 // Other possibility of pending resume is stopping_1 state
1999 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002000 // drain being called.
2001 if (mState == STOPPING_1) {
2002 mResumeToStopping = false;
2003 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002004}
Andy Hunge10393e2015-06-12 13:59:33 -07002005
2006//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002007void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002008 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002009 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002010 // Make the kernel frametime available.
2011 const FrameTime ft{
2012 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2013 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2014 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2015 mKernelFrameTime.store(ft);
2016 if (!audio_is_linear_pcm(mFormat)) {
2017 return;
2018 }
2019
Andy Hung818e7a32016-02-16 18:08:07 -08002020 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002021 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002022
2023 // adjust server times and set drained state.
2024 //
2025 // Our timestamps are only updated when the track is on the Thread active list.
2026 // We need to ensure that tracks are not removed before full drain.
2027 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002028 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002029 bool checked = false;
2030 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2031 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2032 // Lookup the track frame corresponding to the sink frame position.
2033 if (local.mTimeNs[i] > 0) {
2034 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2035 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002036 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002037 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002038 checked = true;
2039 }
2040 }
Andy Hunge10393e2015-06-12 13:59:33 -07002041 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002042
Andy Hung93bb5732023-05-04 21:16:34 -07002043 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2044 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002045 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002046 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002047 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002048 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002049
2050 // Compute latency info.
2051 const bool useTrackTimestamp = !drained;
2052 const double latencyMs = useTrackTimestamp
2053 ? local.getOutputServerLatencyMs(sampleRate())
2054 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2055
2056 mServerLatencyFromTrack.store(useTrackTimestamp);
2057 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002058
Andy Hung62921122020-05-18 10:47:31 -07002059 if (mLogStartCountdown > 0
2060 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2061 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2062 {
2063 if (mLogStartCountdown > 1) {
2064 --mLogStartCountdown;
2065 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2066 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002067 // startup is the difference in times for the current timestamp and our start
2068 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002069 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002070 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002071 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2072 * 1e3 / mSampleRate;
2073 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2074 " localTime:%lld startTime:%lld"
2075 " localPosition:%lld startPosition:%lld",
2076 __func__, latencyMs, startUpMs,
2077 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002078 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002079 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002080 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002081 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002082 }
Andy Hung62921122020-05-18 10:47:31 -07002083 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002084 }
Andy Hunge10393e2015-06-12 13:59:33 -07002085}
2086
Andy Hung8d31fd22023-06-26 19:20:57 -07002087bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002088 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002089 if (thread != 0) {
2090 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87c693c2023-07-06 20:56:16 -07002091 Mutex::Autolock _l(thread->mutex());
2092 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002093 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002094 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002095 ALOGD("%s, haptic playback was %s for track %d",
2096 __func__, muted ? "muted" : "unmuted", mTrack->id());
2097 mTrack->setHapticPlaybackEnabled(!muted);
2098 return true;
jiabin57303cc2018-12-18 15:45:57 -08002099 }
2100 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002101 return false;
2102}
2103
Andy Hung8d31fd22023-06-26 19:20:57 -07002104binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002105 /*out*/ bool *ret) {
2106 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002107 return binder::Status::ok();
2108}
2109
Andy Hung8d31fd22023-06-26 19:20:57 -07002110binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002111 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002112 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002113 return binder::Status::ok();
2114}
2115
Eric Laurent81784c32012-11-19 14:55:58 -08002116// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002117#undef LOG_TAG
2118#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002119
Andy Hung8d31fd22023-06-26 19:20:57 -07002120/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002121sp<IAfOutputTrack> IAfOutputTrack::create(
2122 IAfPlaybackThread* playbackThread,
2123 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002124 uint32_t sampleRate,
2125 audio_format_t format,
2126 audio_channel_mask_t channelMask,
2127 size_t frameCount,
2128 const AttributionSourceState& attributionSource) {
2129 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002130 playbackThread,
2131 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002132 sampleRate,
2133 format,
2134 channelMask,
2135 frameCount,
2136 attributionSource);
2137}
2138
2139OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002140 IAfPlaybackThread* playbackThread,
2141 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002142 uint32_t sampleRate,
2143 audio_format_t format,
2144 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002145 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002146 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002147 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002148 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002149 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002150 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002151 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002152 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002153 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002154{
2155
2156 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002157 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002158 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002159 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002160 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002161 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002162 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002163 // since client and server are in the same process,
2164 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002165 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2166 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002167 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002168 mClientProxy->setSendLevel(0.0);
2169 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002170 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002171 ALOGW("%s(%d): Error creating output track on thread %d",
2172 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002173 }
2174}
2175
Andy Hung8d31fd22023-06-26 19:20:57 -07002176OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002177{
2178 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002179 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002180}
2181
Andy Hung8d31fd22023-06-26 19:20:57 -07002182status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002183 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002184{
2185 status_t status = Track::start(event, triggerSession);
2186 if (status != NO_ERROR) {
2187 return status;
2188 }
2189
2190 mActive = true;
2191 mRetryCount = 127;
2192 return status;
2193}
2194
Andy Hung8d31fd22023-06-26 19:20:57 -07002195void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002196{
2197 Track::stop();
2198 clearBufferQueue();
2199 mOutBuffer.frameCount = 0;
2200 mActive = false;
2201}
2202
Andy Hung8d31fd22023-06-26 19:20:57 -07002203ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002204{
Eric Laurent19952e12023-04-20 10:08:29 +02002205 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002206 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002207 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002208 // preload one silent buffer to trigger mixer on start()
2209 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2210 status_t status = mClientProxy->obtainBuffer(&buf);
2211 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2212 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2213 return 0;
2214 }
2215 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2216 mClientProxy->releaseBuffer(&buf);
2217
2218 (void) start();
2219
2220 // wait for HAL stream to start before sending actual audio. Doing this on each
2221 // OutputTrack makes that playback start on all output streams is synchronized.
2222 // If another OutputTrack has already started it can underrun but this is OK
2223 // as only silence has been played so far and the retry count is very high on
2224 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002225 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002226 if (!pt->waitForHalStart()) {
2227 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2228 stop();
2229 return 0;
2230 }
2231
2232 // enqueue the first buffer and exit so that other OutputTracks will also start before
2233 // write() is called again and this buffer actually consumed.
2234 Buffer firstBuffer;
2235 firstBuffer.frameCount = frames;
2236 firstBuffer.raw = data;
2237 queueBuffer(firstBuffer);
2238 return frames;
2239 } else {
2240 (void) start();
2241 }
2242 }
2243
Eric Laurent81784c32012-11-19 14:55:58 -08002244 Buffer *pInBuffer;
2245 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002246 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002247 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002248 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002249 while (waitTimeLeftMs) {
2250 // First write pending buffers, then new data
2251 if (mBufferQueue.size()) {
2252 pInBuffer = mBufferQueue.itemAt(0);
2253 } else {
2254 pInBuffer = &inBuffer;
2255 }
2256
2257 if (pInBuffer->frameCount == 0) {
2258 break;
2259 }
2260
2261 if (mOutBuffer.frameCount == 0) {
2262 mOutBuffer.frameCount = pInBuffer->frameCount;
2263 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002264 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002265 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002266 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2267 __func__, mId,
2268 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002269 break;
2270 }
2271 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2272 if (waitTimeLeftMs >= waitTimeMs) {
2273 waitTimeLeftMs -= waitTimeMs;
2274 } else {
2275 waitTimeLeftMs = 0;
2276 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002277 if (status == NOT_ENOUGH_DATA) {
2278 restartIfDisabled();
2279 continue;
2280 }
Eric Laurent81784c32012-11-19 14:55:58 -08002281 }
2282
2283 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2284 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002285 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002286 Proxy::Buffer buf;
2287 buf.mFrameCount = outFrames;
2288 buf.mRaw = NULL;
2289 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002290 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002291 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002292 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002293 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002294 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002295
2296 if (pInBuffer->frameCount == 0) {
2297 if (mBufferQueue.size()) {
2298 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002299 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002300 if (pInBuffer != &inBuffer) {
2301 delete pInBuffer;
2302 }
Andy Hung9d84af52018-09-12 18:03:44 -07002303 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2304 __func__, mId,
2305 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002306 } else {
2307 break;
2308 }
2309 }
2310 }
2311
2312 // If we could not write all frames, allocate a buffer and queue it for next time.
2313 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002314 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002315 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002316 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002317 }
2318 }
2319
Andy Hungc25b84a2015-01-14 19:04:10 -08002320 // Calling write() with a 0 length buffer means that no more data will be written:
2321 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2322 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2323 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002324 }
2325
Andy Hung1c86ebe2018-05-29 20:29:08 -07002326 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002327}
2328
Andy Hung8d31fd22023-06-26 19:20:57 -07002329void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002330
2331 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2332 Buffer *pInBuffer = new Buffer;
2333 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2334 pInBuffer->mBuffer = malloc(bufferSize);
2335 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2336 "%s: Unable to malloc size %zu", __func__, bufferSize);
2337 pInBuffer->frameCount = inBuffer.frameCount;
2338 pInBuffer->raw = pInBuffer->mBuffer;
2339 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2340 mBufferQueue.add(pInBuffer);
2341 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2342 (int)mThreadIoHandle, mBufferQueue.size());
2343 // audio data is consumed (stored locally); set frameCount to 0.
2344 inBuffer.frameCount = 0;
2345 } else {
2346 ALOGW("%s(%d): thread %d no more overflow buffers",
2347 __func__, mId, (int)mThreadIoHandle);
2348 // TODO: return error for this.
2349 }
2350}
2351
Andy Hung8d31fd22023-06-26 19:20:57 -07002352void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002353{
2354 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2355 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2356}
2357
Andy Hung8d31fd22023-06-26 19:20:57 -07002358void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002359 {
2360 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2361 mTrackMetadatas = metadatas;
2362 }
2363 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2364 setMetadataHasChanged();
2365}
2366
Andy Hung8d31fd22023-06-26 19:20:57 -07002367status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002368 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2369{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002370 ClientProxy::Buffer buf;
2371 buf.mFrameCount = buffer->frameCount;
2372 struct timespec timeout;
2373 timeout.tv_sec = waitTimeMs / 1000;
2374 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2375 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2376 buffer->frameCount = buf.mFrameCount;
2377 buffer->raw = buf.mRaw;
2378 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002379}
2380
Andy Hung8d31fd22023-06-26 19:20:57 -07002381void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002382{
2383 size_t size = mBufferQueue.size();
2384
2385 for (size_t i = 0; i < size; i++) {
2386 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002387 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002388 delete pBuffer;
2389 }
2390 mBufferQueue.clear();
2391}
2392
Andy Hung8d31fd22023-06-26 19:20:57 -07002393void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002394{
2395 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2396 if (mActive && (flags & CBLK_DISABLED)) {
2397 start();
2398 }
2399}
Eric Laurent81784c32012-11-19 14:55:58 -08002400
Andy Hung9d84af52018-09-12 18:03:44 -07002401// ----------------------------------------------------------------------------
2402#undef LOG_TAG
2403#define LOG_TAG "AF::PatchTrack"
2404
Andy Hung8d31fd22023-06-26 19:20:57 -07002405/* static */
2406sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002407 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002408 audio_stream_type_t streamType,
2409 uint32_t sampleRate,
2410 audio_channel_mask_t channelMask,
2411 audio_format_t format,
2412 size_t frameCount,
2413 void* buffer,
2414 size_t bufferSize,
2415 audio_output_flags_t flags,
2416 const Timeout& timeout,
2417 size_t frameCountToBeReady /** Default behaviour is to start
2418 * as soon as possible to have
2419 * the lowest possible latency
2420 * even if it might glitch. */)
2421{
2422 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002423 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002424 streamType,
2425 sampleRate,
2426 channelMask,
2427 format,
2428 frameCount,
2429 buffer,
2430 bufferSize,
2431 flags,
2432 timeout,
2433 frameCountToBeReady);
2434}
2435
Andy Hung87c693c2023-07-06 20:56:16 -07002436PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002437 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002438 uint32_t sampleRate,
2439 audio_channel_mask_t channelMask,
2440 audio_format_t format,
2441 size_t frameCount,
2442 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002443 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002444 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002445 const Timeout& timeout,
2446 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002447 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002448 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002449 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002450 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002451 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002452 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002453 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2454 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002455 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002456{
Andy Hung9d84af52018-09-12 18:03:44 -07002457 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2458 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002459 (int)mPeerTimeout.tv_sec,
2460 (int)(mPeerTimeout.tv_nsec / 1000000));
2461}
2462
Andy Hung8d31fd22023-06-26 19:20:57 -07002463PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002464{
Andy Hungabfab202019-03-07 19:45:54 -08002465 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002466}
2467
Andy Hung8d31fd22023-06-26 19:20:57 -07002468size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002469{
2470 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2471 return std::numeric_limits<size_t>::max();
2472 } else {
2473 return Track::framesReady();
2474 }
2475}
2476
Andy Hung8d31fd22023-06-26 19:20:57 -07002477status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002478 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002479{
2480 status_t status = Track::start(event, triggerSession);
2481 if (status != NO_ERROR) {
2482 return status;
2483 }
2484 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2485 return status;
2486}
2487
Eric Laurent83b88082014-06-20 18:31:16 -07002488// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002489status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002490 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002491{
Andy Hung9d84af52018-09-12 18:03:44 -07002492 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002493 Proxy::Buffer buf;
2494 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002495 if (ATRACE_ENABLED()) {
2496 std::string traceName("PTnReq");
2497 traceName += std::to_string(id());
2498 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2499 }
Eric Laurent83b88082014-06-20 18:31:16 -07002500 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002501 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002502 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002503 if (ATRACE_ENABLED()) {
2504 std::string traceName("PTnObt");
2505 traceName += std::to_string(id());
2506 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2507 }
Eric Laurent83b88082014-06-20 18:31:16 -07002508 if (buf.mFrameCount == 0) {
2509 return WOULD_BLOCK;
2510 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002511 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002512 return status;
2513}
2514
Andy Hung8d31fd22023-06-26 19:20:57 -07002515void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002516{
Andy Hung9d84af52018-09-12 18:03:44 -07002517 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002518 Proxy::Buffer buf;
2519 buf.mFrameCount = buffer->frameCount;
2520 buf.mRaw = buffer->raw;
2521 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002522 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002523}
2524
Andy Hung8d31fd22023-06-26 19:20:57 -07002525status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002526 const struct timespec *timeOut)
2527{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002528 status_t status = NO_ERROR;
2529 static const int32_t kMaxTries = 5;
2530 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002531 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002532 do {
2533 if (status == NOT_ENOUGH_DATA) {
2534 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002535 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002536 }
2537 status = mProxy->obtainBuffer(buffer, timeOut);
2538 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2539 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002540}
2541
Andy Hung8d31fd22023-06-26 19:20:57 -07002542void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002543{
2544 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002545 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002546
2547 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2548 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2549 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2550 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002551 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002552 && audio_is_linear_pcm(mFormat)
2553 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002554 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002555 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002556 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002557 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2558 / playbackThread->sampleRate();
2559 if (framesReady() < frameCount) {
2560 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002561 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002562 }
2563 }
2564 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002565}
2566
Andy Hung8d31fd22023-06-26 19:20:57 -07002567void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002568{
Eric Laurent83b88082014-06-20 18:31:16 -07002569 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002570 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002571 start();
2572 }
Eric Laurent83b88082014-06-20 18:31:16 -07002573}
2574
Eric Laurent81784c32012-11-19 14:55:58 -08002575// ----------------------------------------------------------------------------
2576// Record
2577// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002578
2579
Andy Hung9d84af52018-09-12 18:03:44 -07002580#undef LOG_TAG
2581#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002582
Andy Hunga5a7fc92023-06-23 19:27:19 -07002583class RecordHandle : public android::media::BnAudioRecord {
2584public:
Andy Hungd29af632023-06-23 19:27:19 -07002585 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002586 ~RecordHandle() override;
2587 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2588 int /*audio_session_t*/ triggerSession) final;
2589 binder::Status stop() final;
2590 binder::Status getActiveMicrophones(
2591 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2592 binder::Status setPreferredMicrophoneDirection(
2593 int /*audio_microphone_direction_t*/ direction) final;
2594 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2595 binder::Status shareAudioHistory(
2596 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2597
2598private:
Andy Hungd29af632023-06-23 19:27:19 -07002599 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002600
2601 // for use from destructor
2602 void stop_nonvirtual();
2603};
2604
2605/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002606sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2607 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002608 return sp<RecordHandle>::make(recordTrack);
2609}
2610
2611RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002612 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002613 : BnAudioRecord(),
2614 mRecordTrack(recordTrack)
2615{
Andy Hung225aef62022-12-06 16:33:20 -08002616 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002617}
2618
Andy Hunga5a7fc92023-06-23 19:27:19 -07002619RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002620 stop_nonvirtual();
2621 mRecordTrack->destroy();
2622}
2623
Andy Hunga5a7fc92023-06-23 19:27:19 -07002624binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002625 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002626 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002627 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002628 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002629}
2630
Andy Hunga5a7fc92023-06-23 19:27:19 -07002631binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002632 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002633 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002634}
2635
Andy Hunga5a7fc92023-06-23 19:27:19 -07002636void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002637 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002638 mRecordTrack->stop();
2639}
2640
Andy Hunga5a7fc92023-06-23 19:27:19 -07002641binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002642 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002643 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002644 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002645}
2646
Andy Hunga5a7fc92023-06-23 19:27:19 -07002647binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002648 int /*audio_microphone_direction_t*/ direction) {
2649 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002650 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002651 static_cast<audio_microphone_direction_t>(direction)));
2652}
2653
Andy Hunga5a7fc92023-06-23 19:27:19 -07002654binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002655 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002656 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002657}
2658
Andy Hunga5a7fc92023-06-23 19:27:19 -07002659binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002660 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2661 return binderStatusFromStatusT(
2662 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2663}
2664
Eric Laurent81784c32012-11-19 14:55:58 -08002665// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002666#undef LOG_TAG
2667#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002668
Andy Hung8d31fd22023-06-26 19:20:57 -07002669
Andy Hung99b1ba62023-07-14 11:00:08 -07002670/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002671sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002672 const sp<Client>& client,
2673 const audio_attributes_t& attr,
2674 uint32_t sampleRate,
2675 audio_format_t format,
2676 audio_channel_mask_t channelMask,
2677 size_t frameCount,
2678 void* buffer,
2679 size_t bufferSize,
2680 audio_session_t sessionId,
2681 pid_t creatorPid,
2682 const AttributionSourceState& attributionSource,
2683 audio_input_flags_t flags,
2684 track_type type,
2685 audio_port_handle_t portId,
2686 int32_t startFrames)
2687{
2688 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002689 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002690 client,
2691 attr,
2692 sampleRate,
2693 format,
2694 channelMask,
2695 frameCount,
2696 buffer,
2697 bufferSize,
2698 sessionId,
2699 creatorPid,
2700 attributionSource,
2701 flags,
2702 type,
2703 portId,
2704 startFrames);
2705}
2706
Glenn Kasten05997e22014-03-13 15:08:33 -07002707// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002708RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002709 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002710 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002711 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002712 uint32_t sampleRate,
2713 audio_format_t format,
2714 audio_channel_mask_t channelMask,
2715 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002716 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002717 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002718 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002719 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002720 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002721 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002722 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002723 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002724 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002725 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002726 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002727 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002728 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002729 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002730 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002731 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002732 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002733 type, portId,
2734 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002735 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002736 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002737 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002738 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002739 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002740 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002741{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002742 if (mCblk == NULL) {
2743 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002744 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002745
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002746 if (!isDirect()) {
2747 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002748 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002749 channelMask, format, sampleRate);
2750 // Check if the RecordBufferConverter construction was successful.
2751 // If not, don't continue with construction.
2752 //
2753 // NOTE: It would be extremely rare that the record track cannot be created
2754 // for the current device, but a pending or future device change would make
2755 // the record track configuration valid.
2756 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002757 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002758 return;
2759 }
Andy Hung97a893e2015-03-29 01:03:07 -07002760 }
2761
Andy Hung6ae58432016-02-16 18:32:24 -08002762 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002763 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002764
Andy Hung97a893e2015-03-29 01:03:07 -07002765 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002766
Eric Laurent05067782016-06-01 18:27:28 -07002767 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002768 ALOG_ASSERT(thread->fastTrackAvailable());
2769 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002770 } else {
2771 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002772 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002773 }
Andy Hung8946a282018-04-19 20:04:56 -07002774#ifdef TEE_SINK
2775 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2776 + "_" + std::to_string(mId)
2777 + "_R");
2778#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002779
2780 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002781 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002782}
2783
Andy Hung8d31fd22023-06-26 19:20:57 -07002784RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002785{
Andy Hung9d84af52018-09-12 18:03:44 -07002786 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002787 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002788 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002789}
2790
Andy Hung8d31fd22023-06-26 19:20:57 -07002791status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002792{
2793 status_t status = TrackBase::initCheck();
2794 if (status == NO_ERROR && mServerProxy == 0) {
2795 status = BAD_VALUE;
2796 }
2797 return status;
2798}
2799
Eric Laurent81784c32012-11-19 14:55:58 -08002800// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002801status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002802{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002803 ServerProxy::Buffer buf;
2804 buf.mFrameCount = buffer->frameCount;
2805 status_t status = mServerProxy->obtainBuffer(&buf);
2806 buffer->frameCount = buf.mFrameCount;
2807 buffer->raw = buf.mRaw;
2808 if (buf.mFrameCount == 0) {
2809 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002810 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002811 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002812 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002813}
2814
Andy Hung8d31fd22023-06-26 19:20:57 -07002815status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002816 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002817{
Andy Hung87c693c2023-07-06 20:56:16 -07002818 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002819 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002820 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002821 return recordThread->start(this, event, triggerSession);
2822 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002823 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2824 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002825 }
2826}
2827
Andy Hung8d31fd22023-06-26 19:20:57 -07002828void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002829{
Andy Hung87c693c2023-07-06 20:56:16 -07002830 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002831 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002832 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002833 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002834 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002835 }
2836 }
2837}
2838
Andy Hung8d31fd22023-06-26 19:20:57 -07002839void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002840{
Andy Hung8d31fd22023-06-26 19:20:57 -07002841 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002842 sp<RecordTrack> keep(this);
2843 {
Andy Hungce685402018-10-05 17:23:27 -07002844 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002845 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002846 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002847 Mutex::Autolock _l(thread->mutex());
2848 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002849 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002850 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002851 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002852 }
Andy Hungce685402018-10-05 17:23:27 -07002853 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2854 }
2855 // APM portid/client management done outside of lock.
2856 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2857 if (isExternalTrack()) {
2858 switch (priorState) {
2859 case ACTIVE: // invalidated while still active
2860 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2861 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2862 AudioSystem::stopInput(mPortId);
2863 break;
2864
2865 case STARTING_1: // invalidated/start-aborted and startInput not successful
2866 case PAUSED: // OK, not active
2867 case IDLE: // OK, not active
2868 break;
2869
2870 case STOPPED: // unexpected (destroyed)
2871 default:
2872 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2873 }
2874 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002875 }
2876 }
2877}
2878
Andy Hung8d31fd22023-06-26 19:20:57 -07002879void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002880{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002881 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002882 // FIXME should use proxy, and needs work
2883 audio_track_cblk_t* cblk = mCblk;
2884 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2885 android_atomic_release_store(0x40000000, &cblk->mFutex);
2886 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002887 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002888}
2889
Eric Laurent81784c32012-11-19 14:55:58 -08002890
Andy Hung8d31fd22023-06-26 19:20:57 -07002891void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002892{
Eric Laurent973db022018-11-20 14:54:31 -08002893 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002894 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002895 " Server FrmCnt FrmRdy Sil%s\n",
2896 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002897}
2898
Andy Hung8d31fd22023-06-26 19:20:57 -07002899void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002900{
Eric Laurent973db022018-11-20 14:54:31 -08002901 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002902 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002903 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002904 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002905 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002906 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002907 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002908 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002909 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002910 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002911 mCblk->mFlags,
2912
Eric Laurent81784c32012-11-19 14:55:58 -08002913 mFormat,
2914 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002915 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002916 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002917
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002918 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002919 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002920 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002921 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002922 );
Andy Hung000adb52018-06-01 15:43:26 -07002923 if (isServerLatencySupported()) {
2924 double latencyMs;
2925 bool fromTrack;
2926 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2927 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2928 // or 'k' if estimated from kernel (usually for debugging).
2929 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2930 } else {
2931 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2932 }
2933 }
2934 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002935}
2936
Andy Hung93bb5732023-05-04 21:16:34 -07002937// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002938void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002939 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002940{
Andy Hung93bb5732023-05-04 21:16:34 -07002941 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002942 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002943 if (threadBase != 0) {
2944 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2945 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07002946 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002947 }
Andy Hung93bb5732023-05-04 21:16:34 -07002948
2949 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002950}
2951
Andy Hung8d31fd22023-06-26 19:20:57 -07002952void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002953{
Andy Hung93bb5732023-05-04 21:16:34 -07002954 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002955}
2956
Andy Hung8d31fd22023-06-26 19:20:57 -07002957void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002958 int64_t trackFramesReleased, int64_t sourceFramesRead,
2959 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2960{
Andy Hung30282562018-08-08 18:27:03 -07002961 // Make the kernel frametime available.
2962 const FrameTime ft{
2963 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2964 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2965 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2966 mKernelFrameTime.store(ft);
2967 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002968 // Stream is direct, return provided timestamp with no conversion
2969 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002970 return;
2971 }
2972
Andy Hung3f0c9022016-01-15 17:49:46 -08002973 ExtendedTimestamp local = timestamp;
2974
2975 // Convert HAL frames to server-side track frames at track sample rate.
2976 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2977 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2978 if (local.mTimeNs[i] != 0) {
2979 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2980 const int64_t relativeTrackFrames = relativeServerFrames
2981 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2982 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2983 }
2984 }
Andy Hung6ae58432016-02-16 18:32:24 -08002985 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002986
2987 // Compute latency info.
2988 const bool useTrackTimestamp = true; // use track unless debugging.
2989 const double latencyMs = - (useTrackTimestamp
2990 ? local.getOutputServerLatencyMs(sampleRate())
2991 : timestamp.getOutputServerLatencyMs(halSampleRate));
2992
2993 mServerLatencyFromTrack.store(useTrackTimestamp);
2994 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08002995}
Eric Laurent83b88082014-06-20 18:31:16 -07002996
Andy Hung8d31fd22023-06-26 19:20:57 -07002997status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07002998 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08002999{
Andy Hung87c693c2023-07-06 20:56:16 -07003000 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003001 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003002 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003003 return recordThread->getActiveMicrophones(activeMicrophones);
3004 } else {
3005 return BAD_VALUE;
3006 }
3007}
3008
Andy Hung8d31fd22023-06-26 19:20:57 -07003009status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003010 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003011 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003012 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003013 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003014 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003015 } else {
3016 return BAD_VALUE;
3017 }
3018}
3019
Andy Hung8d31fd22023-06-26 19:20:57 -07003020status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003021 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003022 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003023 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003024 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003025 } else {
3026 return BAD_VALUE;
3027 }
3028}
3029
Andy Hung8d31fd22023-06-26 19:20:57 -07003030status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003031 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3032
3033 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3034 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3035 if (callingUid != mUid || callingPid != mCreatorPid) {
3036 return PERMISSION_DENIED;
3037 }
3038
Svet Ganov33761132021-05-13 22:51:08 +00003039 AttributionSourceState attributionSource{};
3040 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3041 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3042 attributionSource.token = sp<BBinder>::make();
3043 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003044 return PERMISSION_DENIED;
3045 }
3046
Andy Hung87c693c2023-07-06 20:56:16 -07003047 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003048 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003049 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003050 status_t status = recordThread->shareAudioHistory(
3051 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3052 if (status == NO_ERROR) {
3053 mSharedAudioPackageName = sharedAudioPackageName;
3054 }
3055 return status;
3056 } else {
3057 return BAD_VALUE;
3058 }
3059}
3060
Andy Hung8d31fd22023-06-26 19:20:57 -07003061void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003062{
3063
3064 // Do not forward PatchRecord metadata with unspecified audio source
3065 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3066 return;
3067 }
3068
3069 // No track is invalid as this is called after prepareTrack_l in the same critical section
3070 record_track_metadata_v7_t metadata;
3071 metadata.base = {
3072 .source = mAttr.source,
3073 .gain = 1, // capture tracks do not have volumes
3074 };
3075 metadata.channel_mask = mChannelMask;
3076 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3077
3078 *backInserter++ = metadata;
3079}
Eric Laurentec376dc2021-04-08 20:41:22 +02003080
Andy Hung9d84af52018-09-12 18:03:44 -07003081// ----------------------------------------------------------------------------
3082#undef LOG_TAG
3083#define LOG_TAG "AF::PatchRecord"
3084
Andy Hung8d31fd22023-06-26 19:20:57 -07003085/* static */
3086sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003087 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003088 uint32_t sampleRate,
3089 audio_channel_mask_t channelMask,
3090 audio_format_t format,
3091 size_t frameCount,
3092 void *buffer,
3093 size_t bufferSize,
3094 audio_input_flags_t flags,
3095 const Timeout& timeout,
3096 audio_source_t source)
3097{
3098 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003099 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003100 sampleRate,
3101 channelMask,
3102 format,
3103 frameCount,
3104 buffer,
3105 bufferSize,
3106 flags,
3107 timeout,
3108 source);
3109}
3110
Andy Hung87c693c2023-07-06 20:56:16 -07003111PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003112 uint32_t sampleRate,
3113 audio_channel_mask_t channelMask,
3114 audio_format_t format,
3115 size_t frameCount,
3116 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003117 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003118 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003119 const Timeout& timeout,
3120 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003121 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003122 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003123 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003124 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003125 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003126 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3127 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003128 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003129{
Andy Hung9d84af52018-09-12 18:03:44 -07003130 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3131 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003132 (int)mPeerTimeout.tv_sec,
3133 (int)(mPeerTimeout.tv_nsec / 1000000));
3134}
3135
Andy Hung8d31fd22023-06-26 19:20:57 -07003136PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003137{
Andy Hungabfab202019-03-07 19:45:54 -08003138 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003139}
3140
Mikhail Naganov8296c252019-09-25 14:59:54 -07003141static size_t writeFramesHelper(
3142 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3143{
3144 AudioBufferProvider::Buffer patchBuffer;
3145 patchBuffer.frameCount = frameCount;
3146 auto status = dest->getNextBuffer(&patchBuffer);
3147 if (status != NO_ERROR) {
3148 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3149 __func__, status, strerror(-status));
3150 return 0;
3151 }
3152 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3153 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3154 size_t framesWritten = patchBuffer.frameCount;
3155 dest->releaseBuffer(&patchBuffer);
3156 return framesWritten;
3157}
3158
3159// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003160size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003161 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3162{
3163 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3164 // On buffer wrap, the buffer frame count will be less than requested,
3165 // when this happens a second buffer needs to be used to write the leftover audio
3166 const size_t framesLeft = frameCount - framesWritten;
3167 if (framesWritten != 0 && framesLeft != 0) {
3168 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3169 framesLeft, frameSize);
3170 }
3171 return framesWritten;
3172}
3173
Eric Laurent83b88082014-06-20 18:31:16 -07003174// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003175status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003176 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003177{
Andy Hung9d84af52018-09-12 18:03:44 -07003178 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003179 Proxy::Buffer buf;
3180 buf.mFrameCount = buffer->frameCount;
3181 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3182 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003183 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003184 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003185 if (ATRACE_ENABLED()) {
3186 std::string traceName("PRnObt");
3187 traceName += std::to_string(id());
3188 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3189 }
Eric Laurent83b88082014-06-20 18:31:16 -07003190 if (buf.mFrameCount == 0) {
3191 return WOULD_BLOCK;
3192 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003193 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003194 return status;
3195}
3196
Andy Hung8d31fd22023-06-26 19:20:57 -07003197void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003198{
Andy Hung9d84af52018-09-12 18:03:44 -07003199 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003200 Proxy::Buffer buf;
3201 buf.mFrameCount = buffer->frameCount;
3202 buf.mRaw = buffer->raw;
3203 mPeerProxy->releaseBuffer(&buf);
3204 TrackBase::releaseBuffer(buffer);
3205}
3206
Andy Hung8d31fd22023-06-26 19:20:57 -07003207status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003208 const struct timespec *timeOut)
3209{
3210 return mProxy->obtainBuffer(buffer, timeOut);
3211}
3212
Andy Hung8d31fd22023-06-26 19:20:57 -07003213void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003214{
3215 mProxy->releaseBuffer(buffer);
3216}
3217
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003218#undef LOG_TAG
3219#define LOG_TAG "AF::PthrPatchRecord"
3220
3221static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3222{
3223 void *ptr = nullptr;
3224 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003225 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003226}
3227
Andy Hung8d31fd22023-06-26 19:20:57 -07003228/* static */
3229sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003230 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003231 uint32_t sampleRate,
3232 audio_channel_mask_t channelMask,
3233 audio_format_t format,
3234 size_t frameCount,
3235 audio_input_flags_t flags,
3236 audio_source_t source)
3237{
3238 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003239 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003240 sampleRate,
3241 channelMask,
3242 format,
3243 frameCount,
3244 flags,
3245 source);
3246}
3247
3248PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003249 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003250 uint32_t sampleRate,
3251 audio_channel_mask_t channelMask,
3252 audio_format_t format,
3253 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003254 audio_input_flags_t flags,
3255 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003256 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003257 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003258 mPatchRecordAudioBufferProvider(*this),
3259 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3260 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3261{
3262 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3263}
3264
Andy Hung8d31fd22023-06-26 19:20:57 -07003265sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003266 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003267{
3268 *thread = mThread.promote();
3269 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003270 auto* const recordThread = (*thread)->asIAfRecordThread().get();
3271 Mutex::Autolock _l(recordThread->mutex());
3272 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003273}
3274
3275// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003276status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003277 Proxy::Buffer* buffer, const struct timespec* timeOut)
3278{
3279 if (mUnconsumedFrames) {
3280 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3281 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3282 return PatchRecord::obtainBuffer(buffer, timeOut);
3283 }
3284
3285 // Otherwise, execute a read from HAL and write into the buffer.
3286 nsecs_t startTimeNs = 0;
3287 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3288 // Will need to correct timeOut by elapsed time.
3289 startTimeNs = systemTime();
3290 }
3291 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3292 buffer->mFrameCount = 0;
3293 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003294 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003295 sp<StreamInHalInterface> stream = obtainStream(&thread);
3296 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3297
3298 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003299 size_t bytesRead = 0;
3300 {
3301 ATRACE_NAME("read");
3302 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3303 if (result != NO_ERROR) goto stream_error;
3304 if (bytesRead == 0) return NO_ERROR;
3305 }
3306
3307 {
3308 std::lock_guard<std::mutex> lock(mReadLock);
3309 mReadBytes += bytesRead;
3310 mReadError = NO_ERROR;
3311 }
3312 mReadCV.notify_one();
3313 // writeFrames handles wraparound and should write all the provided frames.
3314 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3315 buffer->mFrameCount = writeFrames(
3316 &mPatchRecordAudioBufferProvider,
3317 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3318 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3319 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3320 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003321 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003322 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003323 // Correct the timeout by elapsed time.
3324 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003325 if (newTimeOutNs < 0) newTimeOutNs = 0;
3326 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3327 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003328 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003329 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003330 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003331
3332stream_error:
3333 stream->standby();
3334 {
3335 std::lock_guard<std::mutex> lock(mReadLock);
3336 mReadError = result;
3337 }
3338 mReadCV.notify_one();
3339 return result;
3340}
3341
Andy Hung8d31fd22023-06-26 19:20:57 -07003342void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003343{
3344 if (buffer->mFrameCount <= mUnconsumedFrames) {
3345 mUnconsumedFrames -= buffer->mFrameCount;
3346 } else {
3347 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3348 buffer->mFrameCount, mUnconsumedFrames);
3349 mUnconsumedFrames = 0;
3350 }
3351 PatchRecord::releaseBuffer(buffer);
3352}
3353
3354// AudioBufferProvider and Source methods are called on RecordThread
3355// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3356// and 'releaseBuffer' are stubbed out and ignore their input.
3357// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3358// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003359status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003360 void* buffer, size_t bytes, size_t* read)
3361{
3362 bytes = std::min(bytes, mFrameCount * mFrameSize);
3363 {
3364 std::unique_lock<std::mutex> lock(mReadLock);
3365 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3366 if (mReadError != NO_ERROR) {
3367 mLastReadFrames = 0;
3368 return mReadError;
3369 }
3370 *read = std::min(bytes, mReadBytes);
3371 mReadBytes -= *read;
3372 }
3373 mLastReadFrames = *read / mFrameSize;
3374 memset(buffer, 0, *read);
3375 return 0;
3376}
3377
Andy Hung8d31fd22023-06-26 19:20:57 -07003378status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003379 int64_t* frames, int64_t* time)
3380{
Andy Hung87c693c2023-07-06 20:56:16 -07003381 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003382 sp<StreamInHalInterface> stream = obtainStream(&thread);
3383 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3384}
3385
Andy Hung8d31fd22023-06-26 19:20:57 -07003386status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003387{
3388 // RecordThread issues 'standby' command in two major cases:
3389 // 1. Error on read--this case is handled in 'obtainBuffer'.
3390 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3391 // output, this can only happen when the software patch
3392 // is being torn down. In this case, the RecordThread
3393 // will terminate and close the HAL stream.
3394 return 0;
3395}
3396
3397// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003398status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003399 AudioBufferProvider::Buffer* buffer)
3400{
3401 buffer->frameCount = mLastReadFrames;
3402 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3403 return NO_ERROR;
3404}
3405
Andy Hung8d31fd22023-06-26 19:20:57 -07003406void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003407 AudioBufferProvider::Buffer* buffer)
3408{
3409 buffer->frameCount = 0;
3410 buffer->raw = nullptr;
3411}
3412
Andy Hung9d84af52018-09-12 18:03:44 -07003413// ----------------------------------------------------------------------------
3414#undef LOG_TAG
3415#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003416
Andy Hung8d31fd22023-06-26 19:20:57 -07003417/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003418sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003419 const audio_attributes_t& attr,
3420 uint32_t sampleRate,
3421 audio_format_t format,
3422 audio_channel_mask_t channelMask,
3423 audio_session_t sessionId,
3424 bool isOut,
3425 const android::content::AttributionSourceState& attributionSource,
3426 pid_t creatorPid,
3427 audio_port_handle_t portId)
3428{
3429 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003430 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003431 attr,
3432 sampleRate,
3433 format,
3434 channelMask,
3435 sessionId,
3436 isOut,
3437 attributionSource,
3438 creatorPid,
3439 portId);
3440}
3441
Andy Hung87c693c2023-07-06 20:56:16 -07003442MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003443 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003444 uint32_t sampleRate,
3445 audio_format_t format,
3446 audio_channel_mask_t channelMask,
3447 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003448 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003449 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003450 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003451 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003452 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003453 channelMask, (size_t)0 /* frameCount */,
3454 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003455 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003456 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003457 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003458 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003459 TYPE_DEFAULT, portId,
3460 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003461 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003462 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003463{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003464 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003465 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003466}
3467
Andy Hung8d31fd22023-06-26 19:20:57 -07003468MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003469{
3470}
3471
Andy Hung8d31fd22023-06-26 19:20:57 -07003472status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003473{
3474 return NO_ERROR;
3475}
3476
Andy Hung8d31fd22023-06-26 19:20:57 -07003477status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003478 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003479{
3480 return NO_ERROR;
3481}
3482
Andy Hung8d31fd22023-06-26 19:20:57 -07003483void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003484{
3485}
3486
3487// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003488status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003489{
3490 buffer->frameCount = 0;
3491 buffer->raw = nullptr;
3492 return INVALID_OPERATION;
3493}
3494
3495// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003496size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003497 return 0;
3498}
3499
Andy Hung8d31fd22023-06-26 19:20:57 -07003500int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003501{
3502 return 0;
3503}
3504
Andy Hung8d31fd22023-06-26 19:20:57 -07003505void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003506{
3507}
3508
Andy Hung8d31fd22023-06-26 19:20:57 -07003509void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003510{
3511 if (mMuteState == muteState) {
3512 // mute state did not change, do nothing
3513 return;
3514 }
3515
3516 status_t result = UNKNOWN_ERROR;
3517 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3518 if (mMuteEventExtras == nullptr) {
3519 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3520 }
3521 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3522 static_cast<int>(muteState));
3523
3524 result = audioManager->portEvent(mPortId,
3525 PLAYER_UPDATE_MUTED,
3526 mMuteEventExtras);
3527 }
3528
3529 if (result == OK) {
3530 mMuteState = muteState;
3531 } else {
3532 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3533 __func__,
3534 id(),
3535 mPortId,
3536 result);
3537 }
3538}
3539
Andy Hung8d31fd22023-06-26 19:20:57 -07003540void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003541{
Eric Laurent973db022018-11-20 14:54:31 -08003542 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003543 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003544}
3545
Andy Hung8d31fd22023-06-26 19:20:57 -07003546void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003547{
Eric Laurent973db022018-11-20 14:54:31 -08003548 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003549 mPid,
3550 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003551 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003552 mFormat,
3553 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003554 mSampleRate,
3555 mAttr.flags);
3556 if (isOut()) {
3557 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3558 } else {
3559 result.appendFormat("%6x", mAttr.source);
3560 }
3561 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003562}
3563
Glenn Kasten63238ef2015-03-02 15:50:29 -08003564} // namespace android