blob: e93046e61fdf0940209ae1c087af07ab9943db8c [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()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000571 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700572 uid);
573 return nullptr;
574 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800575 }
576 // stream type has been filtered by audio policy to indicate whether it can be muted
577 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700578 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700579 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800580 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700581 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
582 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
583 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
584 id, attr.flags);
585 return nullptr;
586 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700587 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700588}
589
Andy Hung87c693c2023-07-06 20:56:16 -0700590OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700591 const AttributionSourceState& attributionSource,
592 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700593 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700594 mHasOpPlayAudio(true),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700595 mUsage((int32_t)usage),
596 mId(id),
597 mUid(uid),
598 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
599 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800600
Andy Hung8d31fd22023-06-26 19:20:57 -0700601OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800602{
603 if (mOpCallback != 0) {
604 mAppOpsManager.stopWatchingMode(mOpCallback);
605 }
606 mOpCallback.clear();
607}
608
Andy Hung8d31fd22023-06-26 19:20:57 -0700609void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700610{
Vlad Popad5859592023-08-02 18:36:04 -0700611 // make sure not to broadcast the initial state since it is not needed and could
612 // cause a deadlock since this method can be called with the mThread->mLock held
613 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000614 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700615 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000616 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
617 } else {
618 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
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
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000629void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
630 const bool hasAppOps =
631 mPackageName.size() &&
632 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
633 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700634
635 bool shouldChange = !hasAppOps; // check if we need to update.
636 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000637 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
638 String8(mPackageName).string(), mUsage, hasAppOps ? "not " : "");
Vlad Popad5859592023-08-02 18:36:04 -0700639 if (doBroadcast) {
640 auto thread = mThread.promote();
641 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
642 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
643 Mutex::Autolock _l(thread->mutex());
644 thread->broadcast_l();
645 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700646 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800647 }
648}
649
Andy Hung8d31fd22023-06-26 19:20:57 -0700650OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800651 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
652{ }
653
Andy Hung8d31fd22023-06-26 19:20:57 -0700654void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800655 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800656 if (op != AppOpsManager::OP_PLAY_AUDIO) {
657 return;
658 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000659
660 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).string());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800661 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
662 if (monitor != NULL) {
Vlad Popad5859592023-08-02 18:36:04 -0700663 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800664 }
665}
666
Eric Laurent9066ad32019-05-20 14:40:10 -0700667// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700668void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700669 uid_t uid, Vector<String16>& packages)
670{
671 PermissionController permissionController;
672 permissionController.getPackagesForUid(uid, packages);
673}
674
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800675// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700676#undef LOG_TAG
677#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800678
Andy Hung8d31fd22023-06-26 19:20:57 -0700679/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700680sp<IAfTrack> IAfTrack::create(
681 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700682 const sp<Client>& client,
683 audio_stream_type_t streamType,
684 const audio_attributes_t& attr,
685 uint32_t sampleRate,
686 audio_format_t format,
687 audio_channel_mask_t channelMask,
688 size_t frameCount,
689 void *buffer,
690 size_t bufferSize,
691 const sp<IMemory>& sharedBuffer,
692 audio_session_t sessionId,
693 pid_t creatorPid,
694 const AttributionSourceState& attributionSource,
695 audio_output_flags_t flags,
696 track_type type,
697 audio_port_handle_t portId,
698 /** default behaviour is to start when there are as many frames
699 * ready as possible (aka. Buffer is full). */
700 size_t frameCountToBeReady,
701 float speed,
702 bool isSpatialized,
703 bool isBitPerfect) {
Andy Hung87c693c2023-07-06 20:56:16 -0700704 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700705 client,
706 streamType,
707 attr,
708 sampleRate,
709 format,
710 channelMask,
711 frameCount,
712 buffer,
713 bufferSize,
714 sharedBuffer,
715 sessionId,
716 creatorPid,
717 attributionSource,
718 flags,
719 type,
720 portId,
721 frameCountToBeReady,
722 speed,
723 isSpatialized,
724 isBitPerfect);
725}
726
Eric Laurent81784c32012-11-19 14:55:58 -0800727// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700728Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700729 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800730 const sp<Client>& client,
731 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700732 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800733 uint32_t sampleRate,
734 audio_format_t format,
735 audio_channel_mask_t channelMask,
736 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700737 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700738 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800739 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800740 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700741 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000742 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700743 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800744 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100745 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000746 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200747 float speed,
jiabinc658e452022-10-21 20:52:21 +0000748 bool isSpatialized,
749 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700750 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700751 // TODO: Using unsecurePointer() has some associated security pitfalls
752 // (see declaration for details).
753 // Either document why it is safe in this case or address the
754 // issue (e.g. by copying).
755 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700756 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700757 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000758 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700759 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800760 type,
761 portId,
762 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700763 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800764 // mRetryCount initialized later when needed
765 mSharedBuffer(sharedBuffer),
766 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700767 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800768 mAuxBuffer(NULL),
769 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700770 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700771 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700772 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700773 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700774 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800775 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800776 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700777 /* The track might not play immediately after being active, similarly as if its volume was 0.
778 * When the track starts playing, its volume will be computed. */
779 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800780 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700781 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000782 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200783 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000784 mIsSpatialized(isSpatialized),
785 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800786{
Eric Laurent83b88082014-06-20 18:31:16 -0700787 // client == 0 implies sharedBuffer == 0
788 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
789
Andy Hung9d84af52018-09-12 18:03:44 -0700790 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700791 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700792
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700793 if (mCblk == NULL) {
794 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800795 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700796
Svet Ganov33761132021-05-13 22:51:08 +0000797 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700798 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
799 ALOGE("%s(%d): no more tracks available", __func__, mId);
800 releaseCblk(); // this makes the track invalid.
801 return;
802 }
803
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700804 if (sharedBuffer == 0) {
805 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700806 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700807 } else {
808 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100809 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700810 }
811 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700812 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700813
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700814 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700815 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700816 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
817 // race with setSyncEvent(). However, if we call it, we cannot properly start
818 // static fast tracks (SoundPool) immediately after stopping.
819 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700820 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
821 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700822 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700823 // FIXME This is too eager. We allocate a fast track index before the
824 // fast track becomes active. Since fast tracks are a scarce resource,
825 // this means we are potentially denying other more important fast tracks from
826 // being created. It would be better to allocate the index dynamically.
827 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700828 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700829 }
Andy Hung8946a282018-04-19 20:04:56 -0700830
Dean Wheatley7b036912020-06-18 16:22:11 +1000831 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700832#ifdef TEE_SINK
833 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800834 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700835#endif
jiabin57303cc2018-12-18 15:45:57 -0800836
jiabineb3bda02020-06-30 14:07:03 -0700837 if (thread->supportsHapticPlayback()) {
838 // If the track is attached to haptic playback thread, it is potentially to have
839 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
840 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800841 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000842 std::string packageName = attributionSource.packageName.has_value() ?
843 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800844 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700845 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800846 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800847
848 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700849 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800850 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800851}
852
Andy Hung8d31fd22023-06-26 19:20:57 -0700853Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800854{
Andy Hung9d84af52018-09-12 18:03:44 -0700855 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700856
857 // The destructor would clear mSharedBuffer,
858 // but it will not push the decremented reference count,
859 // leaving the client's IMemory dangling indefinitely.
860 // This prevents that leak.
861 if (mSharedBuffer != 0) {
862 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700863 }
Eric Laurent81784c32012-11-19 14:55:58 -0800864}
865
Andy Hung8d31fd22023-06-26 19:20:57 -0700866status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700867{
868 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700869 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700870 status = NO_MEMORY;
871 }
872 return status;
873}
874
Andy Hung8d31fd22023-06-26 19:20:57 -0700875void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800876{
877 // NOTE: destroyTrack_l() can remove a strong reference to this Track
878 // by removing it from mTracks vector, so there is a risk that this Tracks's
879 // destructor is called. As the destructor needs to lock mLock,
880 // we must acquire a strong reference on this Track before locking mLock
881 // here so that the destructor is called only when exiting this function.
882 // On the other hand, as long as Track::destroy() is only called by
883 // TrackHandle destructor, the TrackHandle still holds a strong ref on
884 // this Track with its member mTrack.
885 sp<Track> keep(this);
886 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700887 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700888 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800889 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -0700890 Mutex::Autolock _l(thread->mutex());
891 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700892 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000893 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700894 }
895 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700896 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800897 }
898 }
899}
900
Andy Hung8d31fd22023-06-26 19:20:57 -0700901void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800902{
Eric Laurent973db022018-11-20 14:54:31 -0800903 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700904 " Format Chn mask SRate "
905 "ST Usg CT "
906 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000907 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700908 "%s\n",
909 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800910}
911
Andy Hung8d31fd22023-06-26 19:20:57 -0700912void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800913{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700914 char trackType;
915 switch (mType) {
916 case TYPE_DEFAULT:
917 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700918 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700919 trackType = 'S'; // static
920 } else {
921 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800922 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700923 break;
924 case TYPE_PATCH:
925 trackType = 'P';
926 break;
927 default:
928 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800929 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700930
931 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700932 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700933 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700934 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700935 }
936
Eric Laurent81784c32012-11-19 14:55:58 -0800937 char nowInUnderrun;
938 switch (mObservedUnderruns.mBitFields.mMostRecent) {
939 case UNDERRUN_FULL:
940 nowInUnderrun = ' ';
941 break;
942 case UNDERRUN_PARTIAL:
943 nowInUnderrun = '<';
944 break;
945 case UNDERRUN_EMPTY:
946 nowInUnderrun = '*';
947 break;
948 default:
949 nowInUnderrun = '?';
950 break;
951 }
Andy Hungda540db2017-04-20 14:06:17 -0700952
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700953 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700954 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700955 case FS_INVALID:
956 fillingStatus = 'I';
957 break;
958 case FS_FILLING:
959 fillingStatus = 'f';
960 break;
961 case FS_FILLED:
962 fillingStatus = 'F';
963 break;
964 case FS_ACTIVE:
965 fillingStatus = 'A';
966 break;
967 default:
968 fillingStatus = '?';
969 break;
970 }
971
972 // clip framesReadySafe to max representation in dump
973 const size_t framesReadySafe =
974 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
975
976 // obtain volumes
977 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
978 const std::pair<float /* volume */, bool /* active */> vsVolume =
979 mVolumeHandler->getLastVolume();
980
981 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
982 // as it may be reduced by the application.
983 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
984 // Check whether the buffer size has been modified by the app.
985 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
986 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
987 ? 'e' /* error */ : ' ' /* identical */;
988
Eric Laurent973db022018-11-20 14:54:31 -0800989 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700990 "%08X %08X %6u "
991 "%2u %3x %2x "
992 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000993 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800994 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700995 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700996 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -0800997 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -0800998 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700999 mCblk->mFlags,
1000
Eric Laurent81784c32012-11-19 14:55:58 -08001001 mFormat,
1002 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001003 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001004
1005 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001006 mAttr.usage,
1007 mAttr.content_type,
1008
1009 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001010 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1011 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001012 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1013 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001014
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001015 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001016 bufferSizeInFrames,
1017 modifiedBufferChar,
1018 framesReadySafe,
1019 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001020 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001021 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001022 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1023 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001024 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001025
1026 if (isServerLatencySupported()) {
1027 double latencyMs;
1028 bool fromTrack;
1029 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1030 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1031 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1032 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001033 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001034 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001035 }
1036 }
1037 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001038}
1039
Andy Hung8d31fd22023-06-26 19:20:57 -07001040uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001041 return mAudioTrackServerProxy->getSampleRate();
1042}
1043
Eric Laurent81784c32012-11-19 14:55:58 -08001044// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001045status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001046{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001047 ServerProxy::Buffer buf;
1048 size_t desiredFrames = buffer->frameCount;
1049 buf.mFrameCount = desiredFrames;
1050 status_t status = mServerProxy->obtainBuffer(&buf);
1051 buffer->frameCount = buf.mFrameCount;
1052 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001053 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001054 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001055 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001056 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001057 } else {
1058 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001059 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001060 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001061}
1062
Andy Hung8d31fd22023-06-26 19:20:57 -07001063void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001064{
1065 interceptBuffer(*buffer);
1066 TrackBase::releaseBuffer(buffer);
1067}
1068
1069// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001070void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001071 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001072 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001073 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001074 if (frameCount == 0) {
1075 return; // No audio to intercept.
1076 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1077 // does not allow 0 frame size request contrary to getNextBuffer
1078 }
1079 for (auto& teePatch : mTeePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001080 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001081 const size_t framesWritten = patchRecord->writeFrames(
1082 sourceBuffer.i8, frameCount, mFrameSize);
1083 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001084 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001085 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001086 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001087 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001088 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1089 using namespace std::chrono_literals;
1090 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001091 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001092 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001093}
1094
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001095// ExtendedAudioBufferProvider interface
1096
Andy Hung27876c02014-09-09 18:07:55 -07001097// framesReady() may return an approximation of the number of frames if called
1098// from a different thread than the one calling Proxy->obtainBuffer() and
1099// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1100// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001101size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001102 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1103 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1104 // The remainder of the buffer is not drained.
1105 return 0;
1106 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001107 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001108}
1109
Andy Hung8d31fd22023-06-26 19:20:57 -07001110int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001111{
1112 return mAudioTrackServerProxy->framesReleased();
1113}
1114
Andy Hung8d31fd22023-06-26 19:20:57 -07001115void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001116{
1117 // This call comes from a FastTrack and should be kept lockless.
1118 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001119 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001120
Andy Hung818e7a32016-02-16 18:08:07 -08001121 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001122
1123 // Compute latency.
1124 // TODO: Consider whether the server latency may be passed in by FastMixer
1125 // as a constant for all active FastTracks.
1126 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1127 mServerLatencyFromTrack.store(true);
1128 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001129}
1130
Eric Laurent81784c32012-11-19 14:55:58 -08001131// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001132bool Track::isReady() const {
1133 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001134 return true;
1135 }
1136
Eric Laurent16498512014-03-17 17:22:08 -07001137 if (isStopping()) {
1138 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001139 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001140 }
Eric Laurent81784c32012-11-19 14:55:58 -08001141 return true;
1142 }
1143
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001144 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001145 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1146 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1147 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1148 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001149
1150 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1151 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1152 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001153 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001154 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001155 return true;
1156 }
1157 return false;
1158}
1159
Andy Hung8d31fd22023-06-26 19:20:57 -07001160status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001161 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001162{
1163 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001164 ALOGV("%s(%d): calling pid %d session %d",
1165 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001166
Andy Hung87c693c2023-07-06 20:56:16 -07001167 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001168 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001169 if (isOffloaded()) {
Andy Hung583043b2023-07-17 17:05:00 -07001170 Mutex::Autolock _laf(thread->afThreadCallback()->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001171 Mutex::Autolock _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001172 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung583043b2023-07-17 17:05:00 -07001173 if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001174 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001175 invalidate();
1176 return PERMISSION_DENIED;
1177 }
1178 }
Andy Hung87c693c2023-07-06 20:56:16 -07001179 Mutex::Autolock _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001180 track_state state = mState;
1181 // here the track could be either new, or restarted
1182 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001183
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001184 // initial state-stopping. next state-pausing.
1185 // What if resume is called ?
1186
Zhou Song1ed46a22020-08-17 15:36:56 +08001187 if (state == FLUSHED) {
1188 // avoid underrun glitches when starting after flush
1189 reset();
1190 }
1191
kuowei.li576f1362021-05-11 18:02:32 +08001192 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1193 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001194 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001195 if (mResumeToStopping) {
1196 // happened we need to resume to STOPPING_1
1197 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001198 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1199 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001200 } else {
1201 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001202 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1203 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001204 }
Eric Laurent81784c32012-11-19 14:55:58 -08001205 } else {
1206 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001207 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1208 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001209 }
1210
Andy Hung87c693c2023-07-06 20:56:16 -07001211 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001212
1213 // states to reset position info for pcm tracks
1214 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001215 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1216 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001217
1218 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1219 // Start point of track -> sink frame map. If the HAL returns a
1220 // frame position smaller than the first written frame in
1221 // updateTrackFrameInfo, the timestamp can be interpolated
1222 // instead of using a larger value.
1223 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1224 playbackThread->framesWritten());
1225 }
Andy Hunge10393e2015-06-12 13:59:33 -07001226 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001227 if (isFastTrack()) {
1228 // refresh fast track underruns on start because that field is never cleared
1229 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1230 // after stop.
1231 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1232 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001233 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001234 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001235 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001236 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001237 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001238 mState = state;
1239 }
1240 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001241
Andy Hungb68f5eb2019-12-03 16:49:17 -08001242 // Audio timing metrics are computed a few mix cycles after starting.
1243 {
1244 mLogStartCountdown = LOG_START_COUNTDOWN;
1245 mLogStartTimeNs = systemTime();
1246 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001247 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1248 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001249 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001250 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001251
Andy Hung1d3556d2018-03-29 16:30:14 -07001252 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1253 // for streaming tracks, remove the buffer read stop limit.
1254 mAudioTrackServerProxy->start();
1255 }
1256
Eric Laurentbfb1b832013-01-07 09:53:42 -08001257 // track was already in the active list, not a problem
1258 if (status == ALREADY_EXISTS) {
1259 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001260 } else {
1261 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1262 // It is usually unsafe to access the server proxy from a binder thread.
1263 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1264 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1265 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001266 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001267 ServerProxy::Buffer buffer;
1268 buffer.mFrameCount = 1;
1269 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001270 }
jiabin7434e812023-06-27 18:22:35 +00001271 if (status == NO_ERROR) {
1272 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1273 }
Eric Laurent81784c32012-11-19 14:55:58 -08001274 } else {
1275 status = BAD_VALUE;
1276 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001277 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001278 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001279 const sp<IAudioManager> audioManager =
1280 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001281 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1282 std::unique_ptr<os::PersistableBundle> bundle =
1283 std::make_unique<os::PersistableBundle>();
1284 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1285 isSpatialized());
1286 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1287 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1288 status_t result = audioManager->portEvent(mPortId,
1289 PLAYER_UPDATE_FORMAT, bundle);
1290 if (result != OK) {
1291 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1292 __func__, mPortId, result);
1293 }
1294 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001295 }
Eric Laurent81784c32012-11-19 14:55:58 -08001296 return status;
1297}
1298
Andy Hung8d31fd22023-06-26 19:20:57 -07001299void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001300{
Andy Hungc0691382018-09-12 18:01:57 -07001301 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001302 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001303 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001304 Mutex::Autolock _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001305 track_state state = mState;
1306 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1307 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001308 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1309 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001310 reset();
1311 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001312 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001313 mState = STOPPED;
1314 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001315 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1316 // presentation is complete
1317 // For an offloaded track this starts a drain and state will
1318 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001319 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001320 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001321 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001322 }
Eric Laurent81784c32012-11-19 14:55:58 -08001323 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001324 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001325 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1326 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001327 }
jiabin7434e812023-06-27 18:22:35 +00001328 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001329 }
1330}
1331
Andy Hung8d31fd22023-06-26 19:20:57 -07001332void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001333{
Andy Hungc0691382018-09-12 18:01:57 -07001334 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001335 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001336 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001337 Mutex::Autolock _l(thread->mutex());
1338 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001339 switch (mState) {
1340 case STOPPING_1:
1341 case STOPPING_2:
1342 if (!isOffloaded()) {
1343 /* nothing to do if track is not offloaded */
1344 break;
1345 }
1346
1347 // Offloaded track was draining, we need to carry on draining when resumed
1348 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001349 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001350 case ACTIVE:
1351 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001352 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001353 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1354 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001355 if (isOffloadedOrDirect()) {
1356 mPauseHwPending = true;
1357 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001358 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001359 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001360
Eric Laurentbfb1b832013-01-07 09:53:42 -08001361 default:
1362 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001363 }
jiabin7434e812023-06-27 18:22:35 +00001364 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1365 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001366 }
1367}
1368
Andy Hung8d31fd22023-06-26 19:20:57 -07001369void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001370{
Andy Hungc0691382018-09-12 18:01:57 -07001371 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001372 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001373 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001374 Mutex::Autolock _l(thread->mutex());
1375 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001376
Phil Burk4bb650b2016-09-09 12:11:17 -07001377 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1378 // Otherwise the flush would not be done until the track is resumed.
1379 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001380 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001381 (void)mServerProxy->flushBufferIfNeeded();
1382 }
1383
Eric Laurentbfb1b832013-01-07 09:53:42 -08001384 if (isOffloaded()) {
1385 // If offloaded we allow flush during any state except terminated
1386 // and keep the track active to avoid problems if user is seeking
1387 // rapidly and underlying hardware has a significant delay handling
1388 // a pause
1389 if (isTerminated()) {
1390 return;
1391 }
1392
Andy Hung9d84af52018-09-12 18:03:44 -07001393 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001394 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001395
1396 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001397 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1398 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001399 mState = ACTIVE;
1400 }
1401
Haynes Mathew George7844f672014-01-15 12:32:55 -08001402 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001403 mResumeToStopping = false;
1404 } else {
1405 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1406 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1407 return;
1408 }
1409 // No point remaining in PAUSED state after a flush => go to
1410 // FLUSHED state
1411 mState = FLUSHED;
1412 // do not reset the track if it is still in the process of being stopped or paused.
1413 // this will be done by prepareTracks_l() when the track is stopped.
1414 // prepareTracks_l() will see mState == FLUSHED, then
1415 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001416 if (isDirect()) {
1417 mFlushHwPending = true;
1418 }
Andy Hung87c693c2023-07-06 20:56:16 -07001419 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001420 reset();
1421 }
Eric Laurent81784c32012-11-19 14:55:58 -08001422 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001423 // Prevent flush being lost if the track is flushed and then resumed
1424 // before mixer thread can run. This is important when offloading
1425 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001426 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001427 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1428 // new data
1429 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001430 }
1431}
1432
Haynes Mathew George7844f672014-01-15 12:32:55 -08001433// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001434void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001435{
Andy Hung920f6572022-10-06 12:09:49 -07001436 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001437 return;
Andy Hung920f6572022-10-06 12:09:49 -07001438 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001439
Phil Burk4bb650b2016-09-09 12:11:17 -07001440 // Clear the client ring buffer so that the app can prime the buffer while paused.
1441 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1442 mServerProxy->flushBufferIfNeeded();
1443
Haynes Mathew George7844f672014-01-15 12:32:55 -08001444 mFlushHwPending = false;
1445}
1446
Andy Hung8d31fd22023-06-26 19:20:57 -07001447void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001448{
1449 mPauseHwPending = false;
1450}
1451
Andy Hung8d31fd22023-06-26 19:20:57 -07001452void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001453{
1454 // Do not reset twice to avoid discarding data written just after a flush and before
1455 // the audioflinger thread detects the track is stopped.
1456 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001457 // Force underrun condition to avoid false underrun callback until first data is
1458 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001459 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001460 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001461 mResetDone = true;
1462 if (mState == FLUSHED) {
1463 mState = IDLE;
1464 }
1465 }
1466}
1467
Andy Hung8d31fd22023-06-26 19:20:57 -07001468status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001469{
Andy Hung87c693c2023-07-06 20:56:16 -07001470 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001471 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001472 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001473 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001474 } else if (thread->type() == IAfThreadBase::DIRECT
1475 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001476 return thread->setParameters(keyValuePairs);
1477 } else {
1478 return PERMISSION_DENIED;
1479 }
1480}
1481
Andy Hung8d31fd22023-06-26 19:20:57 -07001482status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001483 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001484 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001485 if (thread == 0) {
1486 ALOGE("thread is dead");
1487 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001488 } else if (thread->type() == IAfThreadBase::DIRECT
1489 || thread->type() == IAfThreadBase::OFFLOAD) {
1490 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001491 return directOutputThread->selectPresentation(presentationId, programId);
1492 }
1493 return INVALID_OPERATION;
1494}
1495
Andy Hung8d31fd22023-06-26 19:20:57 -07001496VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001497 const sp<VolumeShaper::Configuration>& configuration,
1498 const sp<VolumeShaper::Operation>& operation)
1499{
Andy Hung398ffa22022-12-13 19:19:53 -08001500 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001501
1502 if (isOffloadedOrDirect()) {
1503 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001504 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001505 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001506 Mutex::Autolock _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001507 thread->broadcast_l();
1508 }
1509 }
1510 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001511}
1512
Andy Hung8d31fd22023-06-26 19:20:57 -07001513sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001514{
1515 // Note: We don't check if Thread exists.
1516
1517 // mVolumeHandler is thread safe.
1518 return mVolumeHandler->getVolumeShaperState(id);
1519}
1520
Andy Hung8d31fd22023-06-26 19:20:57 -07001521void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001522{
jiabin76d94692022-12-15 21:51:21 +00001523 mFinalVolumeLeft = volumeLeft;
1524 mFinalVolumeRight = volumeRight;
1525 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001526 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1527 mFinalVolume = volume;
1528 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001529 mLogForceVolumeUpdate = true;
1530 }
1531 if (mLogForceVolumeUpdate) {
1532 mLogForceVolumeUpdate = false;
1533 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001534 }
1535}
1536
Andy Hung8d31fd22023-06-26 19:20:57 -07001537void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001538{
Eric Laurent49e39282022-06-24 18:42:45 +02001539 // Do not forward metadata for PatchTrack with unspecified stream type
1540 if (mStreamType == AUDIO_STREAM_PATCH) {
1541 return;
1542 }
1543
Eric Laurent94579172020-11-20 18:41:04 +01001544 playback_track_metadata_v7_t metadata;
1545 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001546 .usage = mAttr.usage,
1547 .content_type = mAttr.content_type,
1548 .gain = mFinalVolume,
1549 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001550
1551 // When attributes are undefined, derive default values from stream type.
1552 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1553 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1554 switch (mStreamType) {
1555 case AUDIO_STREAM_VOICE_CALL:
1556 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1557 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1558 break;
1559 case AUDIO_STREAM_SYSTEM:
1560 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1561 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1562 break;
1563 case AUDIO_STREAM_RING:
1564 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1565 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1566 break;
1567 case AUDIO_STREAM_MUSIC:
1568 metadata.base.usage = AUDIO_USAGE_MEDIA;
1569 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1570 break;
1571 case AUDIO_STREAM_ALARM:
1572 metadata.base.usage = AUDIO_USAGE_ALARM;
1573 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1574 break;
1575 case AUDIO_STREAM_NOTIFICATION:
1576 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1577 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1578 break;
1579 case AUDIO_STREAM_DTMF:
1580 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1581 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1582 break;
1583 case AUDIO_STREAM_ACCESSIBILITY:
1584 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1585 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1586 break;
1587 case AUDIO_STREAM_ASSISTANT:
1588 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1589 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1590 break;
1591 case AUDIO_STREAM_REROUTING:
1592 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1593 // unknown content type
1594 break;
1595 case AUDIO_STREAM_CALL_ASSISTANT:
1596 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1597 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1598 break;
1599 default:
1600 break;
1601 }
1602 }
1603
Eric Laurent78b07302022-10-07 16:20:34 +02001604 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001605 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1606 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001607}
1608
Andy Hung8d31fd22023-06-26 19:20:57 -07001609void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001610 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001611 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001612 mTeePatches = mTeePatchesToUpdate.value();
1613 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1614 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001615 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001616 }
1617 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001618 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001619}
1620
Andy Hung16ed0da2023-07-14 11:45:38 -07001621void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001622 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1623 "%s, existing tee patches to update will be ignored", __func__);
1624 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1625}
1626
Vlad Popae8d99472022-06-30 16:02:48 +02001627// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001628void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001629 IAudioManager>& audioManager, mute_state_t muteState)
1630{
1631 if (mMuteState == muteState) {
1632 // mute state did not change, do nothing
1633 return;
1634 }
1635
1636 status_t result = UNKNOWN_ERROR;
1637 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1638 if (mMuteEventExtras == nullptr) {
1639 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1640 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001641 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001642
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001643 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001644 }
1645
1646 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001647 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
1648 int(muteState), int(mMuteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001649 mMuteState = muteState;
1650 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001651 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1652 mPortId, result);
Vlad Popae8d99472022-06-30 16:02:48 +02001653 }
1654}
1655
Andy Hung8d31fd22023-06-26 19:20:57 -07001656status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001657{
Andy Hung818e7a32016-02-16 18:08:07 -08001658 if (!isOffloaded() && !isDirect()) {
1659 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001660 }
Andy Hung87c693c2023-07-06 20:56:16 -07001661 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001662 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001663 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001664 }
Phil Burk6140c792015-03-19 14:30:21 -07001665
Andy Hung87c693c2023-07-06 20:56:16 -07001666 Mutex::Autolock _l(thread->mutex());
1667 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001668 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001669}
1670
Andy Hung8d31fd22023-06-26 19:20:57 -07001671status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001672{
Andy Hung87c693c2023-07-06 20:56:16 -07001673 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001674 if (thread == nullptr) {
1675 return DEAD_OBJECT;
1676 }
Eric Laurent81784c32012-11-19 14:55:58 -08001677
Andy Hung87c693c2023-07-06 20:56:16 -07001678 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001679 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001680 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001681 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001682 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001683
Eric Laurent6c796322019-04-09 14:13:17 -07001684 if (EffectId != 0 && status == NO_ERROR) {
1685 status = dstThread->attachAuxEffect(this, EffectId);
1686 if (status == NO_ERROR) {
1687 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001688 }
Eric Laurent6c796322019-04-09 14:13:17 -07001689 }
1690
1691 if (status != NO_ERROR && srcThread != nullptr) {
1692 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001693 }
1694 return status;
1695}
1696
Andy Hung8d31fd22023-06-26 19:20:57 -07001697void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001698{
1699 mAuxEffectId = EffectId;
1700 mAuxBuffer = buffer;
1701}
1702
Andy Hung59de4262021-06-14 10:53:54 -07001703// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001704bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001705 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001706{
Andy Hung818e7a32016-02-16 18:08:07 -08001707 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1708 // This assists in proper timestamp computation as well as wakelock management.
1709
Eric Laurent81784c32012-11-19 14:55:58 -08001710 // a track is considered presented when the total number of frames written to audio HAL
1711 // corresponds to the number of frames written when presentationComplete() is called for the
1712 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001713 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1714 // to detect when all frames have been played. In this case framesWritten isn't
1715 // useful because it doesn't always reflect whether there is data in the h/w
1716 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001717 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1718 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001719 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001720 if (mPresentationCompleteFrames == 0) {
1721 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001722 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001723 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1724 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001725 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001726 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001727
Andy Hungc54b1ff2016-02-23 14:07:07 -08001728 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001729 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001730 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001731 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1732 __func__, mId, (complete ? "complete" : "waiting"),
1733 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001734 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001735 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001736 && mAudioTrackServerProxy->isDrained();
1737 }
1738
1739 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001740 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001741 return true;
1742 }
1743 return false;
1744}
1745
Andy Hung59de4262021-06-14 10:53:54 -07001746// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001747bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001748{
1749 // For Offloaded or Direct tracks.
1750
1751 // For a direct track, we incorporated time based testing for presentationComplete.
1752
1753 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1754 // to detect when all frames have been played. In this case latencyMs isn't
1755 // useful because it doesn't always reflect whether there is data in the h/w
1756 // buffers, particularly if a track has been paused and resumed during draining
1757
1758 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1759 if (mPresentationCompleteTimeNs == 0) {
1760 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1761 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1762 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1763 }
1764
1765 bool complete;
1766 if (isOffloaded()) {
1767 complete = true;
1768 } else { // Direct
1769 complete = systemTime() >= mPresentationCompleteTimeNs;
1770 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1771 }
1772 if (complete) {
1773 notifyPresentationComplete();
1774 return true;
1775 }
1776 return false;
1777}
1778
Andy Hung8d31fd22023-06-26 19:20:57 -07001779void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001780{
1781 // This only triggers once. TODO: should we enforce this?
1782 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1783 mAudioTrackServerProxy->setStreamEndDone();
1784}
1785
Andy Hung8d31fd22023-06-26 19:20:57 -07001786void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001787{
Andy Hung068e08e2023-05-15 19:02:55 -07001788 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1789 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001790 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001791 (*it)->trigger();
1792 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001793 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001794 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001795 }
1796 }
1797}
1798
1799// implement VolumeBufferProvider interface
1800
Andy Hung8d31fd22023-06-26 19:20:57 -07001801gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001802{
1803 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1804 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001805 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1806 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1807 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001808 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001809 if (vl > GAIN_FLOAT_UNITY) {
1810 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001811 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001812 if (vr > GAIN_FLOAT_UNITY) {
1813 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001814 }
1815 // now apply the cached master volume and stream type volume;
1816 // this is trusted but lacks any synchronization or barrier so may be stale
1817 float v = mCachedVolume;
1818 vl *= v;
1819 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001820 // re-combine into packed minifloat
1821 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001822 // FIXME look at mute, pause, and stop flags
1823 return vlr;
1824}
1825
Andy Hung8d31fd22023-06-26 19:20:57 -07001826status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001827 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001828{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001829 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001830 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1831 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001832 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1833 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001834 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001835 event->cancel();
1836 return INVALID_OPERATION;
1837 }
1838 (void) TrackBase::setSyncEvent(event);
1839 return NO_ERROR;
1840}
1841
Andy Hung8d31fd22023-06-26 19:20:57 -07001842void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001843{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001844 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001845 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001846}
1847
Andy Hung8d31fd22023-06-26 19:20:57 -07001848void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001849{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001850 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001851 signalClientFlag(CBLK_DISABLED);
1852}
1853
Andy Hung8d31fd22023-06-26 19:20:57 -07001854void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001855{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001856 // FIXME should use proxy, and needs work
1857 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001858 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001859 android_atomic_release_store(0x40000000, &cblk->mFutex);
1860 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001861 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001862}
1863
Andy Hung8d31fd22023-06-26 19:20:57 -07001864void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001865{
Andy Hung87c693c2023-07-06 20:56:16 -07001866 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001867 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001868 auto* const t = thread->asIAfPlaybackThread().get();
1869 Mutex::Autolock _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001870 t->broadcast_l();
1871 }
1872}
1873
Andy Hung8d31fd22023-06-26 19:20:57 -07001874status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001875{
1876 status_t status = INVALID_OPERATION;
1877 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001878 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001879 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001880 auto* const t = thread->asIAfPlaybackThread().get();
1881 Mutex::Autolock _l(t->mutex());
1882 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001883 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1884 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1885 }
1886 }
1887 return status;
1888}
1889
Andy Hung8d31fd22023-06-26 19:20:57 -07001890status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001891{
1892 status_t status = INVALID_OPERATION;
1893 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001894 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001895 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001896 auto* const t = thread->asIAfPlaybackThread().get();
1897 Mutex::Autolock lock(t->mutex());
1898 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001899 if (status == NO_ERROR) {
1900 mDualMonoMode = mode;
1901 }
1902 }
1903 }
1904 return status;
1905}
1906
Andy Hung8d31fd22023-06-26 19:20:57 -07001907status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001908{
1909 status_t status = INVALID_OPERATION;
1910 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001911 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001912 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001913 auto* const t = thread->asIAfPlaybackThread().get();
1914 Mutex::Autolock lock(t->mutex());
1915 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001916 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1917 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1918 }
1919 }
1920 return status;
1921}
1922
Andy Hung8d31fd22023-06-26 19:20:57 -07001923status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001924{
1925 status_t status = INVALID_OPERATION;
1926 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001927 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001928 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001929 auto* const t = thread->asIAfPlaybackThread().get();
1930 Mutex::Autolock lock(t->mutex());
1931 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932 if (status == NO_ERROR) {
1933 mAudioDescriptionMixLevel = leveldB;
1934 }
1935 }
1936 }
1937 return status;
1938}
1939
Andy Hung8d31fd22023-06-26 19:20:57 -07001940status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001941 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001942{
1943 status_t status = INVALID_OPERATION;
1944 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001945 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001946 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001947 auto* const t = thread->asIAfPlaybackThread().get();
1948 Mutex::Autolock lock(t->mutex());
1949 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001950 ALOGD_IF((status == NO_ERROR) &&
1951 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1952 "%s: playbackRate inconsistent", __func__);
1953 }
1954 }
1955 return status;
1956}
1957
Andy Hung8d31fd22023-06-26 19:20:57 -07001958status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001959 const audio_playback_rate_t& playbackRate)
1960{
1961 status_t status = INVALID_OPERATION;
1962 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001963 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001964 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001965 auto* const t = thread->asIAfPlaybackThread().get();
1966 Mutex::Autolock lock(t->mutex());
1967 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001968 if (status == NO_ERROR) {
1969 mPlaybackRateParameters = playbackRate;
1970 }
1971 }
1972 }
1973 return status;
1974}
1975
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001976//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001977bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07001978 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001979 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001980 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001981 /* Resume is pending if track was stopping before pause was called */
1982 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07001983 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001984 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001985 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001986
1987 return false;
1988}
1989
1990//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001991void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07001992 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001993 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07001994 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001995
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001996 // Other possibility of pending resume is stopping_1 state
1997 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001998 // drain being called.
1999 if (mState == STOPPING_1) {
2000 mResumeToStopping = false;
2001 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002002}
Andy Hunge10393e2015-06-12 13:59:33 -07002003
2004//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002005void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002006 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002007 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002008 // Make the kernel frametime available.
2009 const FrameTime ft{
2010 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2011 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2012 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2013 mKernelFrameTime.store(ft);
2014 if (!audio_is_linear_pcm(mFormat)) {
2015 return;
2016 }
2017
Andy Hung818e7a32016-02-16 18:08:07 -08002018 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002019 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002020
2021 // adjust server times and set drained state.
2022 //
2023 // Our timestamps are only updated when the track is on the Thread active list.
2024 // We need to ensure that tracks are not removed before full drain.
2025 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002026 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002027 bool checked = false;
2028 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2029 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2030 // Lookup the track frame corresponding to the sink frame position.
2031 if (local.mTimeNs[i] > 0) {
2032 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2033 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002034 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002035 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002036 checked = true;
2037 }
2038 }
Andy Hunge10393e2015-06-12 13:59:33 -07002039 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002040
Andy Hung93bb5732023-05-04 21:16:34 -07002041 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2042 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002043 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002044 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002045 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002046 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002047
2048 // Compute latency info.
2049 const bool useTrackTimestamp = !drained;
2050 const double latencyMs = useTrackTimestamp
2051 ? local.getOutputServerLatencyMs(sampleRate())
2052 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2053
2054 mServerLatencyFromTrack.store(useTrackTimestamp);
2055 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002056
Andy Hung62921122020-05-18 10:47:31 -07002057 if (mLogStartCountdown > 0
2058 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2059 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2060 {
2061 if (mLogStartCountdown > 1) {
2062 --mLogStartCountdown;
2063 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2064 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002065 // startup is the difference in times for the current timestamp and our start
2066 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002067 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002068 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002069 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2070 * 1e3 / mSampleRate;
2071 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2072 " localTime:%lld startTime:%lld"
2073 " localPosition:%lld startPosition:%lld",
2074 __func__, latencyMs, startUpMs,
2075 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002076 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002077 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002078 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002079 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002080 }
Andy Hung62921122020-05-18 10:47:31 -07002081 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002082 }
Andy Hunge10393e2015-06-12 13:59:33 -07002083}
2084
Andy Hung8d31fd22023-06-26 19:20:57 -07002085bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002086 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002087 if (thread != 0) {
2088 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87c693c2023-07-06 20:56:16 -07002089 Mutex::Autolock _l(thread->mutex());
2090 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002091 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002092 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002093 ALOGD("%s, haptic playback was %s for track %d",
2094 __func__, muted ? "muted" : "unmuted", mTrack->id());
2095 mTrack->setHapticPlaybackEnabled(!muted);
2096 return true;
jiabin57303cc2018-12-18 15:45:57 -08002097 }
2098 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002099 return false;
2100}
2101
Andy Hung8d31fd22023-06-26 19:20:57 -07002102binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002103 /*out*/ bool *ret) {
2104 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002105 return binder::Status::ok();
2106}
2107
Andy Hung8d31fd22023-06-26 19:20:57 -07002108binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002109 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002110 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002111 return binder::Status::ok();
2112}
2113
Eric Laurent81784c32012-11-19 14:55:58 -08002114// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002115#undef LOG_TAG
2116#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002117
Andy Hung8d31fd22023-06-26 19:20:57 -07002118/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002119sp<IAfOutputTrack> IAfOutputTrack::create(
2120 IAfPlaybackThread* playbackThread,
2121 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002122 uint32_t sampleRate,
2123 audio_format_t format,
2124 audio_channel_mask_t channelMask,
2125 size_t frameCount,
2126 const AttributionSourceState& attributionSource) {
2127 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002128 playbackThread,
2129 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002130 sampleRate,
2131 format,
2132 channelMask,
2133 frameCount,
2134 attributionSource);
2135}
2136
2137OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002138 IAfPlaybackThread* playbackThread,
2139 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002140 uint32_t sampleRate,
2141 audio_format_t format,
2142 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002143 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002144 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002145 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002146 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002147 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002148 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002149 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002150 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002151 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002152{
2153
2154 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002155 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002156 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002157 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002158 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002159 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002160 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002161 // since client and server are in the same process,
2162 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002163 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2164 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002165 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002166 mClientProxy->setSendLevel(0.0);
2167 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002168 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002169 ALOGW("%s(%d): Error creating output track on thread %d",
2170 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002171 }
2172}
2173
Andy Hung8d31fd22023-06-26 19:20:57 -07002174OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002175{
2176 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002177 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002178}
2179
Andy Hung8d31fd22023-06-26 19:20:57 -07002180status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002181 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002182{
2183 status_t status = Track::start(event, triggerSession);
2184 if (status != NO_ERROR) {
2185 return status;
2186 }
2187
2188 mActive = true;
2189 mRetryCount = 127;
2190 return status;
2191}
2192
Andy Hung8d31fd22023-06-26 19:20:57 -07002193void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002194{
2195 Track::stop();
2196 clearBufferQueue();
2197 mOutBuffer.frameCount = 0;
2198 mActive = false;
2199}
2200
Andy Hung8d31fd22023-06-26 19:20:57 -07002201ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002202{
Eric Laurent19952e12023-04-20 10:08:29 +02002203 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002204 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002205 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002206 // preload one silent buffer to trigger mixer on start()
2207 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2208 status_t status = mClientProxy->obtainBuffer(&buf);
2209 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2210 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2211 return 0;
2212 }
2213 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2214 mClientProxy->releaseBuffer(&buf);
2215
2216 (void) start();
2217
2218 // wait for HAL stream to start before sending actual audio. Doing this on each
2219 // OutputTrack makes that playback start on all output streams is synchronized.
2220 // If another OutputTrack has already started it can underrun but this is OK
2221 // as only silence has been played so far and the retry count is very high on
2222 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002223 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002224 if (!pt->waitForHalStart()) {
2225 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2226 stop();
2227 return 0;
2228 }
2229
2230 // enqueue the first buffer and exit so that other OutputTracks will also start before
2231 // write() is called again and this buffer actually consumed.
2232 Buffer firstBuffer;
2233 firstBuffer.frameCount = frames;
2234 firstBuffer.raw = data;
2235 queueBuffer(firstBuffer);
2236 return frames;
2237 } else {
2238 (void) start();
2239 }
2240 }
2241
Eric Laurent81784c32012-11-19 14:55:58 -08002242 Buffer *pInBuffer;
2243 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002244 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002245 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002246 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002247 while (waitTimeLeftMs) {
2248 // First write pending buffers, then new data
2249 if (mBufferQueue.size()) {
2250 pInBuffer = mBufferQueue.itemAt(0);
2251 } else {
2252 pInBuffer = &inBuffer;
2253 }
2254
2255 if (pInBuffer->frameCount == 0) {
2256 break;
2257 }
2258
2259 if (mOutBuffer.frameCount == 0) {
2260 mOutBuffer.frameCount = pInBuffer->frameCount;
2261 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002262 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002263 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002264 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2265 __func__, mId,
2266 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002267 break;
2268 }
2269 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2270 if (waitTimeLeftMs >= waitTimeMs) {
2271 waitTimeLeftMs -= waitTimeMs;
2272 } else {
2273 waitTimeLeftMs = 0;
2274 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002275 if (status == NOT_ENOUGH_DATA) {
2276 restartIfDisabled();
2277 continue;
2278 }
Eric Laurent81784c32012-11-19 14:55:58 -08002279 }
2280
2281 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2282 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002283 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002284 Proxy::Buffer buf;
2285 buf.mFrameCount = outFrames;
2286 buf.mRaw = NULL;
2287 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002288 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002289 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002290 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002291 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002292 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002293
2294 if (pInBuffer->frameCount == 0) {
2295 if (mBufferQueue.size()) {
2296 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002297 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002298 if (pInBuffer != &inBuffer) {
2299 delete pInBuffer;
2300 }
Andy Hung9d84af52018-09-12 18:03:44 -07002301 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2302 __func__, mId,
2303 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002304 } else {
2305 break;
2306 }
2307 }
2308 }
2309
2310 // If we could not write all frames, allocate a buffer and queue it for next time.
2311 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002312 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002313 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002314 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002315 }
2316 }
2317
Andy Hungc25b84a2015-01-14 19:04:10 -08002318 // Calling write() with a 0 length buffer means that no more data will be written:
2319 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2320 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2321 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002322 }
2323
Andy Hung1c86ebe2018-05-29 20:29:08 -07002324 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002325}
2326
Andy Hung8d31fd22023-06-26 19:20:57 -07002327void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002328
2329 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2330 Buffer *pInBuffer = new Buffer;
2331 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2332 pInBuffer->mBuffer = malloc(bufferSize);
2333 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2334 "%s: Unable to malloc size %zu", __func__, bufferSize);
2335 pInBuffer->frameCount = inBuffer.frameCount;
2336 pInBuffer->raw = pInBuffer->mBuffer;
2337 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2338 mBufferQueue.add(pInBuffer);
2339 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2340 (int)mThreadIoHandle, mBufferQueue.size());
2341 // audio data is consumed (stored locally); set frameCount to 0.
2342 inBuffer.frameCount = 0;
2343 } else {
2344 ALOGW("%s(%d): thread %d no more overflow buffers",
2345 __func__, mId, (int)mThreadIoHandle);
2346 // TODO: return error for this.
2347 }
2348}
2349
Andy Hung8d31fd22023-06-26 19:20:57 -07002350void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002351{
2352 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2353 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2354}
2355
Andy Hung8d31fd22023-06-26 19:20:57 -07002356void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002357 {
2358 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2359 mTrackMetadatas = metadatas;
2360 }
2361 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2362 setMetadataHasChanged();
2363}
2364
Andy Hung8d31fd22023-06-26 19:20:57 -07002365status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002366 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2367{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002368 ClientProxy::Buffer buf;
2369 buf.mFrameCount = buffer->frameCount;
2370 struct timespec timeout;
2371 timeout.tv_sec = waitTimeMs / 1000;
2372 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2373 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2374 buffer->frameCount = buf.mFrameCount;
2375 buffer->raw = buf.mRaw;
2376 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002377}
2378
Andy Hung8d31fd22023-06-26 19:20:57 -07002379void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002380{
2381 size_t size = mBufferQueue.size();
2382
2383 for (size_t i = 0; i < size; i++) {
2384 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002385 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002386 delete pBuffer;
2387 }
2388 mBufferQueue.clear();
2389}
2390
Andy Hung8d31fd22023-06-26 19:20:57 -07002391void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002392{
2393 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2394 if (mActive && (flags & CBLK_DISABLED)) {
2395 start();
2396 }
2397}
Eric Laurent81784c32012-11-19 14:55:58 -08002398
Andy Hung9d84af52018-09-12 18:03:44 -07002399// ----------------------------------------------------------------------------
2400#undef LOG_TAG
2401#define LOG_TAG "AF::PatchTrack"
2402
Andy Hung8d31fd22023-06-26 19:20:57 -07002403/* static */
2404sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002405 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002406 audio_stream_type_t streamType,
2407 uint32_t sampleRate,
2408 audio_channel_mask_t channelMask,
2409 audio_format_t format,
2410 size_t frameCount,
2411 void* buffer,
2412 size_t bufferSize,
2413 audio_output_flags_t flags,
2414 const Timeout& timeout,
2415 size_t frameCountToBeReady /** Default behaviour is to start
2416 * as soon as possible to have
2417 * the lowest possible latency
2418 * even if it might glitch. */)
2419{
2420 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002421 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002422 streamType,
2423 sampleRate,
2424 channelMask,
2425 format,
2426 frameCount,
2427 buffer,
2428 bufferSize,
2429 flags,
2430 timeout,
2431 frameCountToBeReady);
2432}
2433
Andy Hung87c693c2023-07-06 20:56:16 -07002434PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002435 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002436 uint32_t sampleRate,
2437 audio_channel_mask_t channelMask,
2438 audio_format_t format,
2439 size_t frameCount,
2440 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002441 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002442 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002443 const Timeout& timeout,
2444 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002445 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002446 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002447 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002448 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002449 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002450 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002451 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2452 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002453 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002454{
Andy Hung9d84af52018-09-12 18:03:44 -07002455 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2456 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002457 (int)mPeerTimeout.tv_sec,
2458 (int)(mPeerTimeout.tv_nsec / 1000000));
2459}
2460
Andy Hung8d31fd22023-06-26 19:20:57 -07002461PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002462{
Andy Hungabfab202019-03-07 19:45:54 -08002463 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002464}
2465
Andy Hung8d31fd22023-06-26 19:20:57 -07002466size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002467{
2468 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2469 return std::numeric_limits<size_t>::max();
2470 } else {
2471 return Track::framesReady();
2472 }
2473}
2474
Andy Hung8d31fd22023-06-26 19:20:57 -07002475status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002476 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002477{
2478 status_t status = Track::start(event, triggerSession);
2479 if (status != NO_ERROR) {
2480 return status;
2481 }
2482 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2483 return status;
2484}
2485
Eric Laurent83b88082014-06-20 18:31:16 -07002486// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002487status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002488 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002489{
Andy Hung9d84af52018-09-12 18:03:44 -07002490 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002491 Proxy::Buffer buf;
2492 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002493 if (ATRACE_ENABLED()) {
2494 std::string traceName("PTnReq");
2495 traceName += std::to_string(id());
2496 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2497 }
Eric Laurent83b88082014-06-20 18:31:16 -07002498 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002499 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002500 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002501 if (ATRACE_ENABLED()) {
2502 std::string traceName("PTnObt");
2503 traceName += std::to_string(id());
2504 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2505 }
Eric Laurent83b88082014-06-20 18:31:16 -07002506 if (buf.mFrameCount == 0) {
2507 return WOULD_BLOCK;
2508 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002509 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002510 return status;
2511}
2512
Andy Hung8d31fd22023-06-26 19:20:57 -07002513void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002514{
Andy Hung9d84af52018-09-12 18:03:44 -07002515 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002516 Proxy::Buffer buf;
2517 buf.mFrameCount = buffer->frameCount;
2518 buf.mRaw = buffer->raw;
2519 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002520 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002521}
2522
Andy Hung8d31fd22023-06-26 19:20:57 -07002523status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002524 const struct timespec *timeOut)
2525{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002526 status_t status = NO_ERROR;
2527 static const int32_t kMaxTries = 5;
2528 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002529 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002530 do {
2531 if (status == NOT_ENOUGH_DATA) {
2532 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002533 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002534 }
2535 status = mProxy->obtainBuffer(buffer, timeOut);
2536 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2537 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002538}
2539
Andy Hung8d31fd22023-06-26 19:20:57 -07002540void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002541{
2542 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002543 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002544
2545 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2546 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2547 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2548 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002549 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002550 && audio_is_linear_pcm(mFormat)
2551 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002552 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002553 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002554 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002555 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2556 / playbackThread->sampleRate();
2557 if (framesReady() < frameCount) {
2558 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002559 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002560 }
2561 }
2562 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002563}
2564
Andy Hung8d31fd22023-06-26 19:20:57 -07002565void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002566{
Eric Laurent83b88082014-06-20 18:31:16 -07002567 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002568 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002569 start();
2570 }
Eric Laurent83b88082014-06-20 18:31:16 -07002571}
2572
Eric Laurent81784c32012-11-19 14:55:58 -08002573// ----------------------------------------------------------------------------
2574// Record
2575// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002576
2577
Andy Hung9d84af52018-09-12 18:03:44 -07002578#undef LOG_TAG
2579#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002580
Andy Hunga5a7fc92023-06-23 19:27:19 -07002581class RecordHandle : public android::media::BnAudioRecord {
2582public:
Andy Hungd29af632023-06-23 19:27:19 -07002583 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002584 ~RecordHandle() override;
2585 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2586 int /*audio_session_t*/ triggerSession) final;
2587 binder::Status stop() final;
2588 binder::Status getActiveMicrophones(
2589 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2590 binder::Status setPreferredMicrophoneDirection(
2591 int /*audio_microphone_direction_t*/ direction) final;
2592 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2593 binder::Status shareAudioHistory(
2594 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2595
2596private:
Andy Hungd29af632023-06-23 19:27:19 -07002597 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002598
2599 // for use from destructor
2600 void stop_nonvirtual();
2601};
2602
2603/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002604sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2605 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002606 return sp<RecordHandle>::make(recordTrack);
2607}
2608
2609RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002610 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002611 : BnAudioRecord(),
2612 mRecordTrack(recordTrack)
2613{
Andy Hung225aef62022-12-06 16:33:20 -08002614 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002615}
2616
Andy Hunga5a7fc92023-06-23 19:27:19 -07002617RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002618 stop_nonvirtual();
2619 mRecordTrack->destroy();
2620}
2621
Andy Hunga5a7fc92023-06-23 19:27:19 -07002622binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002623 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002624 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002625 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002626 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002627}
2628
Andy Hunga5a7fc92023-06-23 19:27:19 -07002629binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002630 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002631 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002632}
2633
Andy Hunga5a7fc92023-06-23 19:27:19 -07002634void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002635 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002636 mRecordTrack->stop();
2637}
2638
Andy Hunga5a7fc92023-06-23 19:27:19 -07002639binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002640 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002641 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002642 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002643}
2644
Andy Hunga5a7fc92023-06-23 19:27:19 -07002645binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002646 int /*audio_microphone_direction_t*/ direction) {
2647 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002648 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002649 static_cast<audio_microphone_direction_t>(direction)));
2650}
2651
Andy Hunga5a7fc92023-06-23 19:27:19 -07002652binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002653 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002654 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002655}
2656
Andy Hunga5a7fc92023-06-23 19:27:19 -07002657binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002658 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2659 return binderStatusFromStatusT(
2660 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2661}
2662
Eric Laurent81784c32012-11-19 14:55:58 -08002663// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002664#undef LOG_TAG
2665#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002666
Andy Hung8d31fd22023-06-26 19:20:57 -07002667
Andy Hung99b1ba62023-07-14 11:00:08 -07002668/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002669sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002670 const sp<Client>& client,
2671 const audio_attributes_t& attr,
2672 uint32_t sampleRate,
2673 audio_format_t format,
2674 audio_channel_mask_t channelMask,
2675 size_t frameCount,
2676 void* buffer,
2677 size_t bufferSize,
2678 audio_session_t sessionId,
2679 pid_t creatorPid,
2680 const AttributionSourceState& attributionSource,
2681 audio_input_flags_t flags,
2682 track_type type,
2683 audio_port_handle_t portId,
2684 int32_t startFrames)
2685{
2686 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002687 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002688 client,
2689 attr,
2690 sampleRate,
2691 format,
2692 channelMask,
2693 frameCount,
2694 buffer,
2695 bufferSize,
2696 sessionId,
2697 creatorPid,
2698 attributionSource,
2699 flags,
2700 type,
2701 portId,
2702 startFrames);
2703}
2704
Glenn Kasten05997e22014-03-13 15:08:33 -07002705// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002706RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002707 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002708 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002709 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002710 uint32_t sampleRate,
2711 audio_format_t format,
2712 audio_channel_mask_t channelMask,
2713 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002714 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002715 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002716 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002717 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002718 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002719 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002720 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002721 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002722 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002723 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002724 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002725 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002726 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002727 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002728 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002729 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002730 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002731 type, portId,
2732 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002733 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002734 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002735 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002736 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002737 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002738 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002739{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002740 if (mCblk == NULL) {
2741 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002742 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002743
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002744 if (!isDirect()) {
2745 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002746 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002747 channelMask, format, sampleRate);
2748 // Check if the RecordBufferConverter construction was successful.
2749 // If not, don't continue with construction.
2750 //
2751 // NOTE: It would be extremely rare that the record track cannot be created
2752 // for the current device, but a pending or future device change would make
2753 // the record track configuration valid.
2754 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002755 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002756 return;
2757 }
Andy Hung97a893e2015-03-29 01:03:07 -07002758 }
2759
Andy Hung6ae58432016-02-16 18:32:24 -08002760 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002761 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002762
Andy Hung97a893e2015-03-29 01:03:07 -07002763 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002764
Eric Laurent05067782016-06-01 18:27:28 -07002765 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002766 ALOG_ASSERT(thread->fastTrackAvailable());
2767 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002768 } else {
2769 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002770 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002771 }
Andy Hung8946a282018-04-19 20:04:56 -07002772#ifdef TEE_SINK
2773 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2774 + "_" + std::to_string(mId)
2775 + "_R");
2776#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002777
2778 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002779 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002780}
2781
Andy Hung8d31fd22023-06-26 19:20:57 -07002782RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002783{
Andy Hung9d84af52018-09-12 18:03:44 -07002784 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002785 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002786 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002787}
2788
Andy Hung8d31fd22023-06-26 19:20:57 -07002789status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002790{
2791 status_t status = TrackBase::initCheck();
2792 if (status == NO_ERROR && mServerProxy == 0) {
2793 status = BAD_VALUE;
2794 }
2795 return status;
2796}
2797
Eric Laurent81784c32012-11-19 14:55:58 -08002798// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002799status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002800{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002801 ServerProxy::Buffer buf;
2802 buf.mFrameCount = buffer->frameCount;
2803 status_t status = mServerProxy->obtainBuffer(&buf);
2804 buffer->frameCount = buf.mFrameCount;
2805 buffer->raw = buf.mRaw;
2806 if (buf.mFrameCount == 0) {
2807 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002808 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002809 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002810 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002811}
2812
Andy Hung8d31fd22023-06-26 19:20:57 -07002813status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002814 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002815{
Andy Hung87c693c2023-07-06 20:56:16 -07002816 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002817 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002818 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002819 return recordThread->start(this, event, triggerSession);
2820 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002821 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2822 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002823 }
2824}
2825
Andy Hung8d31fd22023-06-26 19:20:57 -07002826void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002827{
Andy Hung87c693c2023-07-06 20:56:16 -07002828 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002829 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002830 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002831 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002832 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002833 }
2834 }
2835}
2836
Andy Hung8d31fd22023-06-26 19:20:57 -07002837void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002838{
Andy Hung8d31fd22023-06-26 19:20:57 -07002839 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002840 sp<RecordTrack> keep(this);
2841 {
Andy Hungce685402018-10-05 17:23:27 -07002842 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002843 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002844 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002845 Mutex::Autolock _l(thread->mutex());
2846 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002847 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002848 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002849 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002850 }
Andy Hungce685402018-10-05 17:23:27 -07002851 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2852 }
2853 // APM portid/client management done outside of lock.
2854 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2855 if (isExternalTrack()) {
2856 switch (priorState) {
2857 case ACTIVE: // invalidated while still active
2858 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2859 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2860 AudioSystem::stopInput(mPortId);
2861 break;
2862
2863 case STARTING_1: // invalidated/start-aborted and startInput not successful
2864 case PAUSED: // OK, not active
2865 case IDLE: // OK, not active
2866 break;
2867
2868 case STOPPED: // unexpected (destroyed)
2869 default:
2870 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2871 }
2872 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002873 }
2874 }
2875}
2876
Andy Hung8d31fd22023-06-26 19:20:57 -07002877void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002878{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002879 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002880 // FIXME should use proxy, and needs work
2881 audio_track_cblk_t* cblk = mCblk;
2882 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2883 android_atomic_release_store(0x40000000, &cblk->mFutex);
2884 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002885 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002886}
2887
Eric Laurent81784c32012-11-19 14:55:58 -08002888
Andy Hung8d31fd22023-06-26 19:20:57 -07002889void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002890{
Eric Laurent973db022018-11-20 14:54:31 -08002891 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002892 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002893 " Server FrmCnt FrmRdy Sil%s\n",
2894 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002895}
2896
Andy Hung8d31fd22023-06-26 19:20:57 -07002897void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002898{
Eric Laurent973db022018-11-20 14:54:31 -08002899 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002900 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002901 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002902 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002903 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002904 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002905 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002906 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002907 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002908 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002909 mCblk->mFlags,
2910
Eric Laurent81784c32012-11-19 14:55:58 -08002911 mFormat,
2912 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002913 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002914 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002915
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002916 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002917 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002918 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002919 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002920 );
Andy Hung000adb52018-06-01 15:43:26 -07002921 if (isServerLatencySupported()) {
2922 double latencyMs;
2923 bool fromTrack;
2924 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2925 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2926 // or 'k' if estimated from kernel (usually for debugging).
2927 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2928 } else {
2929 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2930 }
2931 }
2932 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002933}
2934
Andy Hung93bb5732023-05-04 21:16:34 -07002935// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002936void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002937 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002938{
Andy Hung93bb5732023-05-04 21:16:34 -07002939 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002940 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002941 if (threadBase != 0) {
2942 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2943 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07002944 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002945 }
Andy Hung93bb5732023-05-04 21:16:34 -07002946
2947 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002948}
2949
Andy Hung8d31fd22023-06-26 19:20:57 -07002950void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002951{
Andy Hung93bb5732023-05-04 21:16:34 -07002952 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002953}
2954
Andy Hung8d31fd22023-06-26 19:20:57 -07002955void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002956 int64_t trackFramesReleased, int64_t sourceFramesRead,
2957 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2958{
Andy Hung30282562018-08-08 18:27:03 -07002959 // Make the kernel frametime available.
2960 const FrameTime ft{
2961 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2962 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2963 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2964 mKernelFrameTime.store(ft);
2965 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002966 // Stream is direct, return provided timestamp with no conversion
2967 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002968 return;
2969 }
2970
Andy Hung3f0c9022016-01-15 17:49:46 -08002971 ExtendedTimestamp local = timestamp;
2972
2973 // Convert HAL frames to server-side track frames at track sample rate.
2974 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2975 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2976 if (local.mTimeNs[i] != 0) {
2977 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2978 const int64_t relativeTrackFrames = relativeServerFrames
2979 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2980 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2981 }
2982 }
Andy Hung6ae58432016-02-16 18:32:24 -08002983 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002984
2985 // Compute latency info.
2986 const bool useTrackTimestamp = true; // use track unless debugging.
2987 const double latencyMs = - (useTrackTimestamp
2988 ? local.getOutputServerLatencyMs(sampleRate())
2989 : timestamp.getOutputServerLatencyMs(halSampleRate));
2990
2991 mServerLatencyFromTrack.store(useTrackTimestamp);
2992 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08002993}
Eric Laurent83b88082014-06-20 18:31:16 -07002994
Andy Hung8d31fd22023-06-26 19:20:57 -07002995status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07002996 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08002997{
Andy Hung87c693c2023-07-06 20:56:16 -07002998 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08002999 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003000 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003001 return recordThread->getActiveMicrophones(activeMicrophones);
3002 } else {
3003 return BAD_VALUE;
3004 }
3005}
3006
Andy Hung8d31fd22023-06-26 19:20:57 -07003007status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003008 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003009 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003010 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003011 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003012 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003013 } else {
3014 return BAD_VALUE;
3015 }
3016}
3017
Andy Hung8d31fd22023-06-26 19:20:57 -07003018status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003019 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003020 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003021 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003022 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003023 } else {
3024 return BAD_VALUE;
3025 }
3026}
3027
Andy Hung8d31fd22023-06-26 19:20:57 -07003028status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003029 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3030
3031 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3032 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3033 if (callingUid != mUid || callingPid != mCreatorPid) {
3034 return PERMISSION_DENIED;
3035 }
3036
Svet Ganov33761132021-05-13 22:51:08 +00003037 AttributionSourceState attributionSource{};
3038 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3039 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3040 attributionSource.token = sp<BBinder>::make();
3041 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003042 return PERMISSION_DENIED;
3043 }
3044
Andy Hung87c693c2023-07-06 20:56:16 -07003045 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003046 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003047 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003048 status_t status = recordThread->shareAudioHistory(
3049 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3050 if (status == NO_ERROR) {
3051 mSharedAudioPackageName = sharedAudioPackageName;
3052 }
3053 return status;
3054 } else {
3055 return BAD_VALUE;
3056 }
3057}
3058
Andy Hung8d31fd22023-06-26 19:20:57 -07003059void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003060{
3061
3062 // Do not forward PatchRecord metadata with unspecified audio source
3063 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3064 return;
3065 }
3066
3067 // No track is invalid as this is called after prepareTrack_l in the same critical section
3068 record_track_metadata_v7_t metadata;
3069 metadata.base = {
3070 .source = mAttr.source,
3071 .gain = 1, // capture tracks do not have volumes
3072 };
3073 metadata.channel_mask = mChannelMask;
3074 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3075
3076 *backInserter++ = metadata;
3077}
Eric Laurentec376dc2021-04-08 20:41:22 +02003078
Andy Hung9d84af52018-09-12 18:03:44 -07003079// ----------------------------------------------------------------------------
3080#undef LOG_TAG
3081#define LOG_TAG "AF::PatchRecord"
3082
Andy Hung8d31fd22023-06-26 19:20:57 -07003083/* static */
3084sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003085 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003086 uint32_t sampleRate,
3087 audio_channel_mask_t channelMask,
3088 audio_format_t format,
3089 size_t frameCount,
3090 void *buffer,
3091 size_t bufferSize,
3092 audio_input_flags_t flags,
3093 const Timeout& timeout,
3094 audio_source_t source)
3095{
3096 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003097 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003098 sampleRate,
3099 channelMask,
3100 format,
3101 frameCount,
3102 buffer,
3103 bufferSize,
3104 flags,
3105 timeout,
3106 source);
3107}
3108
Andy Hung87c693c2023-07-06 20:56:16 -07003109PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003110 uint32_t sampleRate,
3111 audio_channel_mask_t channelMask,
3112 audio_format_t format,
3113 size_t frameCount,
3114 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003115 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003116 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003117 const Timeout& timeout,
3118 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003119 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003120 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003121 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003122 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003123 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003124 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3125 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003126 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003127{
Andy Hung9d84af52018-09-12 18:03:44 -07003128 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3129 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003130 (int)mPeerTimeout.tv_sec,
3131 (int)(mPeerTimeout.tv_nsec / 1000000));
3132}
3133
Andy Hung8d31fd22023-06-26 19:20:57 -07003134PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003135{
Andy Hungabfab202019-03-07 19:45:54 -08003136 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003137}
3138
Mikhail Naganov8296c252019-09-25 14:59:54 -07003139static size_t writeFramesHelper(
3140 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3141{
3142 AudioBufferProvider::Buffer patchBuffer;
3143 patchBuffer.frameCount = frameCount;
3144 auto status = dest->getNextBuffer(&patchBuffer);
3145 if (status != NO_ERROR) {
3146 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3147 __func__, status, strerror(-status));
3148 return 0;
3149 }
3150 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3151 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3152 size_t framesWritten = patchBuffer.frameCount;
3153 dest->releaseBuffer(&patchBuffer);
3154 return framesWritten;
3155}
3156
3157// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003158size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003159 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3160{
3161 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3162 // On buffer wrap, the buffer frame count will be less than requested,
3163 // when this happens a second buffer needs to be used to write the leftover audio
3164 const size_t framesLeft = frameCount - framesWritten;
3165 if (framesWritten != 0 && framesLeft != 0) {
3166 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3167 framesLeft, frameSize);
3168 }
3169 return framesWritten;
3170}
3171
Eric Laurent83b88082014-06-20 18:31:16 -07003172// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003173status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003174 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003175{
Andy Hung9d84af52018-09-12 18:03:44 -07003176 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003177 Proxy::Buffer buf;
3178 buf.mFrameCount = buffer->frameCount;
3179 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3180 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003181 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003182 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003183 if (ATRACE_ENABLED()) {
3184 std::string traceName("PRnObt");
3185 traceName += std::to_string(id());
3186 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3187 }
Eric Laurent83b88082014-06-20 18:31:16 -07003188 if (buf.mFrameCount == 0) {
3189 return WOULD_BLOCK;
3190 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003191 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003192 return status;
3193}
3194
Andy Hung8d31fd22023-06-26 19:20:57 -07003195void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003196{
Andy Hung9d84af52018-09-12 18:03:44 -07003197 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003198 Proxy::Buffer buf;
3199 buf.mFrameCount = buffer->frameCount;
3200 buf.mRaw = buffer->raw;
3201 mPeerProxy->releaseBuffer(&buf);
3202 TrackBase::releaseBuffer(buffer);
3203}
3204
Andy Hung8d31fd22023-06-26 19:20:57 -07003205status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003206 const struct timespec *timeOut)
3207{
3208 return mProxy->obtainBuffer(buffer, timeOut);
3209}
3210
Andy Hung8d31fd22023-06-26 19:20:57 -07003211void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003212{
3213 mProxy->releaseBuffer(buffer);
3214}
3215
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003216#undef LOG_TAG
3217#define LOG_TAG "AF::PthrPatchRecord"
3218
3219static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3220{
3221 void *ptr = nullptr;
3222 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003223 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003224}
3225
Andy Hung8d31fd22023-06-26 19:20:57 -07003226/* static */
3227sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003228 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003229 uint32_t sampleRate,
3230 audio_channel_mask_t channelMask,
3231 audio_format_t format,
3232 size_t frameCount,
3233 audio_input_flags_t flags,
3234 audio_source_t source)
3235{
3236 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003237 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003238 sampleRate,
3239 channelMask,
3240 format,
3241 frameCount,
3242 flags,
3243 source);
3244}
3245
3246PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003247 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003248 uint32_t sampleRate,
3249 audio_channel_mask_t channelMask,
3250 audio_format_t format,
3251 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003252 audio_input_flags_t flags,
3253 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003254 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003255 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003256 mPatchRecordAudioBufferProvider(*this),
3257 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3258 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3259{
3260 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3261}
3262
Andy Hung8d31fd22023-06-26 19:20:57 -07003263sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003264 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003265{
3266 *thread = mThread.promote();
3267 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003268 auto* const recordThread = (*thread)->asIAfRecordThread().get();
3269 Mutex::Autolock _l(recordThread->mutex());
3270 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003271}
3272
3273// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003274status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003275 Proxy::Buffer* buffer, const struct timespec* timeOut)
3276{
3277 if (mUnconsumedFrames) {
3278 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3279 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3280 return PatchRecord::obtainBuffer(buffer, timeOut);
3281 }
3282
3283 // Otherwise, execute a read from HAL and write into the buffer.
3284 nsecs_t startTimeNs = 0;
3285 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3286 // Will need to correct timeOut by elapsed time.
3287 startTimeNs = systemTime();
3288 }
3289 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3290 buffer->mFrameCount = 0;
3291 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003292 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003293 sp<StreamInHalInterface> stream = obtainStream(&thread);
3294 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3295
3296 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003297 size_t bytesRead = 0;
3298 {
3299 ATRACE_NAME("read");
3300 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3301 if (result != NO_ERROR) goto stream_error;
3302 if (bytesRead == 0) return NO_ERROR;
3303 }
3304
3305 {
3306 std::lock_guard<std::mutex> lock(mReadLock);
3307 mReadBytes += bytesRead;
3308 mReadError = NO_ERROR;
3309 }
3310 mReadCV.notify_one();
3311 // writeFrames handles wraparound and should write all the provided frames.
3312 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3313 buffer->mFrameCount = writeFrames(
3314 &mPatchRecordAudioBufferProvider,
3315 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3316 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3317 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3318 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003319 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003320 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003321 // Correct the timeout by elapsed time.
3322 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003323 if (newTimeOutNs < 0) newTimeOutNs = 0;
3324 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3325 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003326 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003327 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003328 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003329
3330stream_error:
3331 stream->standby();
3332 {
3333 std::lock_guard<std::mutex> lock(mReadLock);
3334 mReadError = result;
3335 }
3336 mReadCV.notify_one();
3337 return result;
3338}
3339
Andy Hung8d31fd22023-06-26 19:20:57 -07003340void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003341{
3342 if (buffer->mFrameCount <= mUnconsumedFrames) {
3343 mUnconsumedFrames -= buffer->mFrameCount;
3344 } else {
3345 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3346 buffer->mFrameCount, mUnconsumedFrames);
3347 mUnconsumedFrames = 0;
3348 }
3349 PatchRecord::releaseBuffer(buffer);
3350}
3351
3352// AudioBufferProvider and Source methods are called on RecordThread
3353// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3354// and 'releaseBuffer' are stubbed out and ignore their input.
3355// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3356// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003357status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003358 void* buffer, size_t bytes, size_t* read)
3359{
3360 bytes = std::min(bytes, mFrameCount * mFrameSize);
3361 {
3362 std::unique_lock<std::mutex> lock(mReadLock);
3363 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3364 if (mReadError != NO_ERROR) {
3365 mLastReadFrames = 0;
3366 return mReadError;
3367 }
3368 *read = std::min(bytes, mReadBytes);
3369 mReadBytes -= *read;
3370 }
3371 mLastReadFrames = *read / mFrameSize;
3372 memset(buffer, 0, *read);
3373 return 0;
3374}
3375
Andy Hung8d31fd22023-06-26 19:20:57 -07003376status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003377 int64_t* frames, int64_t* time)
3378{
Andy Hung87c693c2023-07-06 20:56:16 -07003379 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003380 sp<StreamInHalInterface> stream = obtainStream(&thread);
3381 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3382}
3383
Andy Hung8d31fd22023-06-26 19:20:57 -07003384status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003385{
3386 // RecordThread issues 'standby' command in two major cases:
3387 // 1. Error on read--this case is handled in 'obtainBuffer'.
3388 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3389 // output, this can only happen when the software patch
3390 // is being torn down. In this case, the RecordThread
3391 // will terminate and close the HAL stream.
3392 return 0;
3393}
3394
3395// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003396status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003397 AudioBufferProvider::Buffer* buffer)
3398{
3399 buffer->frameCount = mLastReadFrames;
3400 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3401 return NO_ERROR;
3402}
3403
Andy Hung8d31fd22023-06-26 19:20:57 -07003404void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003405 AudioBufferProvider::Buffer* buffer)
3406{
3407 buffer->frameCount = 0;
3408 buffer->raw = nullptr;
3409}
3410
Andy Hung9d84af52018-09-12 18:03:44 -07003411// ----------------------------------------------------------------------------
3412#undef LOG_TAG
3413#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003414
Andy Hung8d31fd22023-06-26 19:20:57 -07003415/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003416sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003417 const audio_attributes_t& attr,
3418 uint32_t sampleRate,
3419 audio_format_t format,
3420 audio_channel_mask_t channelMask,
3421 audio_session_t sessionId,
3422 bool isOut,
3423 const android::content::AttributionSourceState& attributionSource,
3424 pid_t creatorPid,
3425 audio_port_handle_t portId)
3426{
3427 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003428 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003429 attr,
3430 sampleRate,
3431 format,
3432 channelMask,
3433 sessionId,
3434 isOut,
3435 attributionSource,
3436 creatorPid,
3437 portId);
3438}
3439
Andy Hung87c693c2023-07-06 20:56:16 -07003440MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003441 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003442 uint32_t sampleRate,
3443 audio_format_t format,
3444 audio_channel_mask_t channelMask,
3445 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003446 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003447 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003448 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003449 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003450 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003451 channelMask, (size_t)0 /* frameCount */,
3452 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003453 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003454 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003455 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003456 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003457 TYPE_DEFAULT, portId,
3458 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003459 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003460 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003461{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003462 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003463 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003464}
3465
Andy Hung8d31fd22023-06-26 19:20:57 -07003466MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003467{
3468}
3469
Andy Hung8d31fd22023-06-26 19:20:57 -07003470status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003471{
3472 return NO_ERROR;
3473}
3474
Andy Hung8d31fd22023-06-26 19:20:57 -07003475status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003476 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003477{
3478 return NO_ERROR;
3479}
3480
Andy Hung8d31fd22023-06-26 19:20:57 -07003481void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003482{
3483}
3484
3485// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003486status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003487{
3488 buffer->frameCount = 0;
3489 buffer->raw = nullptr;
3490 return INVALID_OPERATION;
3491}
3492
3493// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003494size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003495 return 0;
3496}
3497
Andy Hung8d31fd22023-06-26 19:20:57 -07003498int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003499{
3500 return 0;
3501}
3502
Andy Hung8d31fd22023-06-26 19:20:57 -07003503void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003504{
3505}
3506
Andy Hung8d31fd22023-06-26 19:20:57 -07003507void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003508{
3509 if (mMuteState == muteState) {
3510 // mute state did not change, do nothing
3511 return;
3512 }
3513
3514 status_t result = UNKNOWN_ERROR;
3515 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3516 if (mMuteEventExtras == nullptr) {
3517 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3518 }
3519 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3520 static_cast<int>(muteState));
3521
3522 result = audioManager->portEvent(mPortId,
3523 PLAYER_UPDATE_MUTED,
3524 mMuteEventExtras);
3525 }
3526
3527 if (result == OK) {
3528 mMuteState = muteState;
3529 } else {
3530 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3531 __func__,
3532 id(),
3533 mPortId,
3534 result);
3535 }
3536}
3537
Andy Hung8d31fd22023-06-26 19:20:57 -07003538void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003539{
Eric Laurent973db022018-11-20 14:54:31 -08003540 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003541 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003542}
3543
Andy Hung8d31fd22023-06-26 19:20:57 -07003544void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003545{
Eric Laurent973db022018-11-20 14:54:31 -08003546 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003547 mPid,
3548 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003549 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003550 mFormat,
3551 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003552 mSampleRate,
3553 mAttr.flags);
3554 if (isOut()) {
3555 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3556 } else {
3557 result.appendFormat("%6x", mAttr.source);
3558 }
3559 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003560}
3561
Glenn Kasten63238ef2015-03-02 15:50:29 -08003562} // namespace android