blob: d279af1ac3cef3cc36c93bd9d4225140f7ca129f [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Eric Laurent81784c32012-11-19 14:55:58 -080018#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070020#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080021
Andy Hung0f725b42023-07-19 11:40:07 -070022#include "MmapTracks.h"
23#include "PlaybackTracks.h"
24#include "RecordTracks.h"
25
26#include "Client.h"
27#include "IAfEffect.h"
28#include "IAfThread.h"
29#include "ResamplerBufferProvider.h"
30
31#include <audio_utils/minifloat.h>
32#include <media/AudioValidator.h>
33#include <media/RecordBufferConverter.h>
34#include <media/nbaio/Pipe.h>
35#include <media/nbaio/PipeReader.h>
36#include <mediautils/ServiceUtilities.h>
37#include <mediautils/SharedMemoryAllocator.h>
38#include <private/media/AudioTrackShared.h>
Eric Laurent81784c32012-11-19 14:55:58 -080039#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070040#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080041
Andy Hung0f725b42023-07-19 11:40:07 -070042#include <linux/futex.h>
43#include <math.h>
44#include <sys/syscall.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080045
Eric Laurent81784c32012-11-19 14:55:58 -080046// ----------------------------------------------------------------------------
47
48// Note: the following macro is used for extremely verbose logging message. In
49// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
50// 0; but one side effect of this is to turn all LOGV's as well. Some messages
51// are so verbose that we want to suppress them even when we have ALOG_ASSERT
52// turned on. Do not uncomment the #def below unless you really know what you
53// are doing and want to see all of the extremely verbose messages.
54//#define VERY_VERY_VERBOSE_LOGGING
55#ifdef VERY_VERY_VERBOSE_LOGGING
56#define ALOGVV ALOGV
57#else
58#define ALOGVV(a...) do { } while(0)
59#endif
60
Kuowei Lid4adbdb2020-08-13 14:44:25 +080061// TODO: Remove when this is put into AidlConversionUtil.h
62#define VALUE_OR_RETURN_BINDER_STATUS(x) \
63 ({ \
64 auto _tmp = (x); \
65 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
66 std::move(_tmp.value()); \
67 })
68
Eric Laurent81784c32012-11-19 14:55:58 -080069namespace android {
70
Kuowei Lid4adbdb2020-08-13 14:44:25 +080071using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080072using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000073using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070074using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080075// ----------------------------------------------------------------------------
76// TrackBase
77// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070078#undef LOG_TAG
79#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080080
Glenn Kastenda6ef132013-01-10 12:31:01 -080081static volatile int32_t nextTrackId = 55;
82
Eric Laurent81784c32012-11-19 14:55:58 -080083// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung87c693c2023-07-06 20:56:16 -070085 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080086 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070087 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080088 uint32_t sampleRate,
89 audio_format_t format,
90 audio_channel_mask_t channelMask,
91 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070092 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070093 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080094 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070095 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080096 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070097 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070098 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080099 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800100 audio_port_handle_t portId,
101 std::string metricsId)
Andy Hungd29af632023-06-23 19:27:19 -0700102 :
Eric Laurent81784c32012-11-19 14:55:58 -0800103 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700104 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800105 mClient(client),
106 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700107 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800108 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700109 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800110 mSampleRate(sampleRate),
111 mFormat(format),
112 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700113 mChannelCount(isOut ?
114 audio_channel_count_from_out_mask(channelMask) :
115 audio_channel_count_from_in_mask(channelMask)),
Dean Wheatleyd883e302023-10-20 06:11:43 +1100116 mFrameSize(audio_bytes_per_frame(mChannelCount, format)),
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung8d31fd22023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung8d31fd22023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung954b9712023-08-28 18:36:53 -0700279 audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung8d31fd22023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung8d31fd22023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung8d31fd22023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700318 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700325 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
326 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung8d31fd22023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hunga5a7fc92023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hungd29af632023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hungd29af632023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hungd29af632023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hung225aef62022-12-06 16:33:20 -0800391 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800392}
393
Andy Hunga5a7fc92023-06-23 19:27:19 -0700394TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800395 // just stop the track on deletion, associated resources
396 // will be freed from the main thread once all pending buffers have
397 // been played. Unless it's not in the active track list, in which
398 // case we free everything now...
399 mTrack->destroy();
400}
401
Andy Hunga5a7fc92023-06-23 19:27:19 -0700402Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800403 std::optional<media::SharedFileRegion>* _aidl_return) {
404 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
405 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800406}
407
Andy Hunga5a7fc92023-06-23 19:27:19 -0700408Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800409 *_aidl_return = mTrack->start();
410 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800411}
412
Andy Hunga5a7fc92023-06-23 19:27:19 -0700413Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800414 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800415 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800416}
417
Andy Hunga5a7fc92023-06-23 19:27:19 -0700418Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800419 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800420 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800421}
422
Andy Hunga5a7fc92023-06-23 19:27:19 -0700423Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800424 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800425 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800426}
427
Andy Hunga5a7fc92023-06-23 19:27:19 -0700428Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800429 int32_t* _aidl_return) {
430 *_aidl_return = mTrack->attachAuxEffect(effectId);
431 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800432}
433
Andy Hunga5a7fc92023-06-23 19:27:19 -0700434Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800435 int32_t* _aidl_return) {
436 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
437 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700438}
439
Andy Hunga5a7fc92023-06-23 19:27:19 -0700440Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800441 int32_t* _aidl_return) {
442 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
443 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800444}
445
Andy Hunga5a7fc92023-06-23 19:27:19 -0700446Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800447 int32_t* _aidl_return) {
448 AudioTimestamp legacy;
449 *_aidl_return = mTrack->getTimestamp(legacy);
450 if (*_aidl_return != OK) {
451 return Status::ok();
452 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000453
454 // restrict position modulo INT_MAX to avoid integer sanitization abort
455 legacy.mPosition &= INT_MAX;
456
Andy Hung973638a2020-12-08 20:47:45 -0800457 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800458 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800459}
460
Andy Hunga5a7fc92023-06-23 19:27:19 -0700461Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800462 mTrack->signal();
463 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800464}
465
Andy Hunga5a7fc92023-06-23 19:27:19 -0700466Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800467 const media::VolumeShaperConfiguration& configuration,
468 const media::VolumeShaperOperation& operation,
469 int32_t* _aidl_return) {
470 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
471 *_aidl_return = conf->readFromParcelable(configuration);
472 if (*_aidl_return != OK) {
473 return Status::ok();
474 }
475
476 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
477 *_aidl_return = op->readFromParcelable(operation);
478 if (*_aidl_return != OK) {
479 return Status::ok();
480 }
481
482 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
483 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700484}
485
Andy Hunga5a7fc92023-06-23 19:27:19 -0700486Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800487 int32_t id,
488 std::optional<media::VolumeShaperState>* _aidl_return) {
489 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
490 if (legacy == nullptr) {
491 _aidl_return->reset();
492 return Status::ok();
493 }
494 media::VolumeShaperState aidl;
495 legacy->writeToParcelable(&aidl);
496 *_aidl_return = aidl;
497 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800498}
499
Andy Hunga5a7fc92023-06-23 19:27:19 -0700500Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000501 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800502{
503 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
504 const status_t status = mTrack->getDualMonoMode(&mode)
505 ?: AudioValidator::validateDualMonoMode(mode);
506 if (status == OK) {
507 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
508 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
509 }
510 return binderStatusFromStatusT(status);
511}
512
Andy Hunga5a7fc92023-06-23 19:27:19 -0700513Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000514 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800515{
516 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
517 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
518 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
519 ?: mTrack->setDualMonoMode(localMonoMode));
520}
521
Andy Hunga5a7fc92023-06-23 19:27:19 -0700522Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800523{
524 float leveldB = -std::numeric_limits<float>::infinity();
525 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
526 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
527 if (status == OK) *_aidl_return = leveldB;
528 return binderStatusFromStatusT(status);
529}
530
Andy Hunga5a7fc92023-06-23 19:27:19 -0700531Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800532{
533 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
534 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
535}
536
Andy Hunga5a7fc92023-06-23 19:27:19 -0700537Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000538 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800539{
540 audio_playback_rate_t localPlaybackRate{};
541 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
542 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
543 if (status == NO_ERROR) {
544 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
545 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
546 }
547 return binderStatusFromStatusT(status);
548}
549
Andy Hunga5a7fc92023-06-23 19:27:19 -0700550Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000551 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800552{
553 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
554 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
555 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
556 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
557}
558
Eric Laurent81784c32012-11-19 14:55:58 -0800559// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800560// AppOp for audio playback
561// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700562
563// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700564sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700565 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000566 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700567 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800568{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700569 Vector<String16> packages;
570 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000571 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700572 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700573 if (packages.isEmpty()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000574 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700575 uid);
576 return nullptr;
577 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800578 }
579 // stream type has been filtered by audio policy to indicate whether it can be muted
580 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700581 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700582 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800583 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700584 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
585 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
586 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
587 id, attr.flags);
588 return nullptr;
589 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700590 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700591}
592
Andy Hung87c693c2023-07-06 20:56:16 -0700593OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700594 const AttributionSourceState& attributionSource,
595 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700596 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700597 mHasOpPlayAudio(true),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700598 mUsage((int32_t)usage),
599 mId(id),
600 mUid(uid),
601 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
602 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800603
Andy Hung8d31fd22023-06-26 19:20:57 -0700604OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800605{
606 if (mOpCallback != 0) {
607 mAppOpsManager.stopWatchingMode(mOpCallback);
608 }
609 mOpCallback.clear();
610}
611
Andy Hung8d31fd22023-06-26 19:20:57 -0700612void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700613{
Vlad Popad5859592023-08-02 18:36:04 -0700614 // make sure not to broadcast the initial state since it is not needed and could
615 // cause a deadlock since this method can be called with the mThread->mLock held
616 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000617 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700618 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000619 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
620 } else {
621 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700622 }
623}
624
Andy Hung8d31fd22023-06-26 19:20:57 -0700625bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800626 return mHasOpPlayAudio.load();
627}
628
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700629// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800630// - not called from constructor due to check on UID,
631// - not called from PlayAudioOpCallback because the callback is not installed in this case
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000632void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
633 const bool hasAppOps =
634 mPackageName.size() &&
635 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
636 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700637
638 bool shouldChange = !hasAppOps; // check if we need to update.
639 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000640 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000641 String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
Vlad Popad5859592023-08-02 18:36:04 -0700642 if (doBroadcast) {
643 auto thread = mThread.promote();
644 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
645 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hungc5007f82023-08-29 14:26:09 -0700646 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad5859592023-08-02 18:36:04 -0700647 thread->broadcast_l();
648 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700649 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800650 }
651}
652
Andy Hung8d31fd22023-06-26 19:20:57 -0700653OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800654 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
655{ }
656
Andy Hung8d31fd22023-06-26 19:20:57 -0700657void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800658 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800659 if (op != AppOpsManager::OP_PLAY_AUDIO) {
660 return;
661 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000662
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000663 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800664 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
665 if (monitor != NULL) {
Vlad Popad5859592023-08-02 18:36:04 -0700666 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800667 }
668}
669
Eric Laurent9066ad32019-05-20 14:40:10 -0700670// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700671void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700672 uid_t uid, Vector<String16>& packages)
673{
674 PermissionController permissionController;
675 permissionController.getPackagesForUid(uid, packages);
676}
677
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800678// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700679#undef LOG_TAG
680#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800681
Andy Hung8d31fd22023-06-26 19:20:57 -0700682/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700683sp<IAfTrack> IAfTrack::create(
684 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700685 const sp<Client>& client,
686 audio_stream_type_t streamType,
687 const audio_attributes_t& attr,
688 uint32_t sampleRate,
689 audio_format_t format,
690 audio_channel_mask_t channelMask,
691 size_t frameCount,
692 void *buffer,
693 size_t bufferSize,
694 const sp<IMemory>& sharedBuffer,
695 audio_session_t sessionId,
696 pid_t creatorPid,
697 const AttributionSourceState& attributionSource,
698 audio_output_flags_t flags,
699 track_type type,
700 audio_port_handle_t portId,
701 /** default behaviour is to start when there are as many frames
702 * ready as possible (aka. Buffer is full). */
703 size_t frameCountToBeReady,
704 float speed,
705 bool isSpatialized,
706 bool isBitPerfect) {
Andy Hung87c693c2023-07-06 20:56:16 -0700707 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700708 client,
709 streamType,
710 attr,
711 sampleRate,
712 format,
713 channelMask,
714 frameCount,
715 buffer,
716 bufferSize,
717 sharedBuffer,
718 sessionId,
719 creatorPid,
720 attributionSource,
721 flags,
722 type,
723 portId,
724 frameCountToBeReady,
725 speed,
726 isSpatialized,
727 isBitPerfect);
728}
729
Eric Laurent81784c32012-11-19 14:55:58 -0800730// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700731Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700732 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800733 const sp<Client>& client,
734 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700735 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800736 uint32_t sampleRate,
737 audio_format_t format,
738 audio_channel_mask_t channelMask,
739 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700740 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700741 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800742 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800743 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700744 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000745 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700746 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800747 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100748 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000749 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200750 float speed,
jiabinc658e452022-10-21 20:52:21 +0000751 bool isSpatialized,
752 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700753 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700754 // TODO: Using unsecurePointer() has some associated security pitfalls
755 // (see declaration for details).
756 // Either document why it is safe in this case or address the
757 // issue (e.g. by copying).
758 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700759 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700760 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000761 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700762 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800763 type,
764 portId,
765 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700766 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800767 // mRetryCount initialized later when needed
768 mSharedBuffer(sharedBuffer),
769 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700770 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800771 mAuxBuffer(NULL),
772 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700773 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700774 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700775 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700776 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700777 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800778 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800779 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700780 /* The track might not play immediately after being active, similarly as if its volume was 0.
781 * When the track starts playing, its volume will be computed. */
782 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800783 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700784 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000785 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200786 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000787 mIsSpatialized(isSpatialized),
788 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800789{
Eric Laurent83b88082014-06-20 18:31:16 -0700790 // client == 0 implies sharedBuffer == 0
791 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
792
Andy Hung9d84af52018-09-12 18:03:44 -0700793 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700794 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700795
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700796 if (mCblk == NULL) {
797 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800798 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700799
Svet Ganov33761132021-05-13 22:51:08 +0000800 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700801 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
802 ALOGE("%s(%d): no more tracks available", __func__, mId);
803 releaseCblk(); // this makes the track invalid.
804 return;
805 }
806
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700807 if (sharedBuffer == 0) {
808 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700809 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700810 } else {
811 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100812 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700813 }
814 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700815 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700816
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700817 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700818 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700819 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
820 // race with setSyncEvent(). However, if we call it, we cannot properly start
821 // static fast tracks (SoundPool) immediately after stopping.
822 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700823 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
824 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700825 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700826 // FIXME This is too eager. We allocate a fast track index before the
827 // fast track becomes active. Since fast tracks are a scarce resource,
828 // this means we are potentially denying other more important fast tracks from
829 // being created. It would be better to allocate the index dynamically.
830 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700831 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700832 }
Andy Hung8946a282018-04-19 20:04:56 -0700833
Dean Wheatley7b036912020-06-18 16:22:11 +1000834 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700835#ifdef TEE_SINK
836 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800837 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700838#endif
jiabin57303cc2018-12-18 15:45:57 -0800839
jiabineb3bda02020-06-30 14:07:03 -0700840 if (thread->supportsHapticPlayback()) {
841 // If the track is attached to haptic playback thread, it is potentially to have
842 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
843 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800844 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000845 std::string packageName = attributionSource.packageName.has_value() ?
846 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800847 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700848 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800849 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800850
851 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700852 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800853 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800854}
855
Andy Hung8d31fd22023-06-26 19:20:57 -0700856Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800857{
Andy Hung9d84af52018-09-12 18:03:44 -0700858 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700859
860 // The destructor would clear mSharedBuffer,
861 // but it will not push the decremented reference count,
862 // leaving the client's IMemory dangling indefinitely.
863 // This prevents that leak.
864 if (mSharedBuffer != 0) {
865 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700866 }
Eric Laurent81784c32012-11-19 14:55:58 -0800867}
868
Andy Hung8d31fd22023-06-26 19:20:57 -0700869status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700870{
871 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700872 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700873 status = NO_MEMORY;
874 }
875 return status;
876}
877
Andy Hung8d31fd22023-06-26 19:20:57 -0700878void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800879{
880 // NOTE: destroyTrack_l() can remove a strong reference to this Track
881 // by removing it from mTracks vector, so there is a risk that this Tracks's
882 // destructor is called. As the destructor needs to lock mLock,
883 // we must acquire a strong reference on this Track before locking mLock
884 // here so that the destructor is called only when exiting this function.
885 // On the other hand, as long as Track::destroy() is only called by
886 // TrackHandle destructor, the TrackHandle still holds a strong ref on
887 // this Track with its member mTrack.
888 sp<Track> keep(this);
889 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700890 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700891 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800892 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -0800893 audio_utils::unique_lock ul(thread->mutex());
894 thread->waitWhileThreadBusy_l(ul);
895
Andy Hung87c693c2023-07-06 20:56:16 -0700896 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700897 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000898 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700899 }
900 if (isExternalTrack() && !wasActive) {
Andy Hung6c498e92023-12-05 17:28:17 -0800901 // If the track is not active, the TrackHandle is responsible for
902 // releasing the port id, not the ThreadBase::threadLoop().
903 // At this point, there is no concurrency issue as the track is going away.
Eric Laurentd7fe0862018-07-14 16:48:01 -0700904 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800905 }
906 }
907}
908
Andy Hung8d31fd22023-06-26 19:20:57 -0700909void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800910{
Eric Laurent973db022018-11-20 14:54:31 -0800911 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700912 " Format Chn mask SRate "
913 "ST Usg CT "
914 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000915 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700916 "%s\n",
917 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800918}
919
Andy Hung8d31fd22023-06-26 19:20:57 -0700920void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800921{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700922 char trackType;
923 switch (mType) {
924 case TYPE_DEFAULT:
925 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700926 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700927 trackType = 'S'; // static
928 } else {
929 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800930 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700931 break;
932 case TYPE_PATCH:
933 trackType = 'P';
934 break;
935 default:
936 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800937 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700938
939 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700940 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700941 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700942 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700943 }
944
Eric Laurent81784c32012-11-19 14:55:58 -0800945 char nowInUnderrun;
946 switch (mObservedUnderruns.mBitFields.mMostRecent) {
947 case UNDERRUN_FULL:
948 nowInUnderrun = ' ';
949 break;
950 case UNDERRUN_PARTIAL:
951 nowInUnderrun = '<';
952 break;
953 case UNDERRUN_EMPTY:
954 nowInUnderrun = '*';
955 break;
956 default:
957 nowInUnderrun = '?';
958 break;
959 }
Andy Hungda540db2017-04-20 14:06:17 -0700960
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700961 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700962 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700963 case FS_INVALID:
964 fillingStatus = 'I';
965 break;
966 case FS_FILLING:
967 fillingStatus = 'f';
968 break;
969 case FS_FILLED:
970 fillingStatus = 'F';
971 break;
972 case FS_ACTIVE:
973 fillingStatus = 'A';
974 break;
975 default:
976 fillingStatus = '?';
977 break;
978 }
979
980 // clip framesReadySafe to max representation in dump
981 const size_t framesReadySafe =
982 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
983
984 // obtain volumes
985 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
986 const std::pair<float /* volume */, bool /* active */> vsVolume =
987 mVolumeHandler->getLastVolume();
988
989 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
990 // as it may be reduced by the application.
991 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
992 // Check whether the buffer size has been modified by the app.
993 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
994 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
995 ? 'e' /* error */ : ' ' /* identical */;
996
Eric Laurent973db022018-11-20 14:54:31 -0800997 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700998 "%08X %08X %6u "
999 "%2u %3x %2x "
1000 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +00001001 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -08001002 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001003 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001004 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001005 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001006 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001007 mCblk->mFlags,
1008
Eric Laurent81784c32012-11-19 14:55:58 -08001009 mFormat,
1010 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001011 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001012
1013 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001014 mAttr.usage,
1015 mAttr.content_type,
1016
1017 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001018 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1019 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001020 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1021 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001022
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001023 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001024 bufferSizeInFrames,
1025 modifiedBufferChar,
1026 framesReadySafe,
1027 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001028 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001029 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001030 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1031 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001032 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001033
1034 if (isServerLatencySupported()) {
1035 double latencyMs;
1036 bool fromTrack;
1037 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1038 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1039 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1040 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001041 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001042 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001043 }
1044 }
1045 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001046}
1047
Andy Hung8d31fd22023-06-26 19:20:57 -07001048uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001049 return mAudioTrackServerProxy->getSampleRate();
1050}
1051
Eric Laurent81784c32012-11-19 14:55:58 -08001052// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001053status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001054{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001055 ServerProxy::Buffer buf;
1056 size_t desiredFrames = buffer->frameCount;
1057 buf.mFrameCount = desiredFrames;
1058 status_t status = mServerProxy->obtainBuffer(&buf);
1059 buffer->frameCount = buf.mFrameCount;
1060 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001061 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001062 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001063 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001064 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001065 } else {
1066 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001067 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001068 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001069}
1070
Andy Hung8d31fd22023-06-26 19:20:57 -07001071void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001072{
1073 interceptBuffer(*buffer);
1074 TrackBase::releaseBuffer(buffer);
1075}
1076
1077// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001078void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001079 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001080 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001081 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001082 if (frameCount == 0) {
1083 return; // No audio to intercept.
1084 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1085 // does not allow 0 frame size request contrary to getNextBuffer
1086 }
1087 for (auto& teePatch : mTeePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001088 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001089 const size_t framesWritten = patchRecord->writeFrames(
1090 sourceBuffer.i8, frameCount, mFrameSize);
1091 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001092 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001093 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001094 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001095 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001096 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1097 using namespace std::chrono_literals;
1098 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001099 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001100 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001101}
1102
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001103// ExtendedAudioBufferProvider interface
1104
Andy Hung27876c02014-09-09 18:07:55 -07001105// framesReady() may return an approximation of the number of frames if called
1106// from a different thread than the one calling Proxy->obtainBuffer() and
1107// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1108// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001109size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001110 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1111 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1112 // The remainder of the buffer is not drained.
1113 return 0;
1114 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001115 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001116}
1117
Andy Hung8d31fd22023-06-26 19:20:57 -07001118int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001119{
1120 return mAudioTrackServerProxy->framesReleased();
1121}
1122
Andy Hung8d31fd22023-06-26 19:20:57 -07001123void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001124{
1125 // This call comes from a FastTrack and should be kept lockless.
1126 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001127 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001128
Andy Hung818e7a32016-02-16 18:08:07 -08001129 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001130
1131 // Compute latency.
1132 // TODO: Consider whether the server latency may be passed in by FastMixer
1133 // as a constant for all active FastTracks.
1134 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1135 mServerLatencyFromTrack.store(true);
1136 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001137}
1138
Eric Laurent81784c32012-11-19 14:55:58 -08001139// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001140bool Track::isReady() const {
1141 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001142 return true;
1143 }
1144
Eric Laurent16498512014-03-17 17:22:08 -07001145 if (isStopping()) {
1146 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001147 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001148 }
Eric Laurent81784c32012-11-19 14:55:58 -08001149 return true;
1150 }
1151
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001152 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001153 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1154 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1155 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1156 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001157
1158 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1159 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1160 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001161 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001162 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001163 return true;
1164 }
1165 return false;
1166}
1167
Andy Hung8d31fd22023-06-26 19:20:57 -07001168status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001169 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001170{
1171 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001172 ALOGV("%s(%d): calling pid %d session %d",
1173 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001174
Andy Hung87c693c2023-07-06 20:56:16 -07001175 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001176 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001177 if (isOffloaded()) {
Andy Hung954b9712023-08-28 18:36:53 -07001178 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hungab65b182023-09-06 19:41:47 -07001179 const bool nonOffloadableGlobalEffectEnabled =
1180 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hungc5007f82023-08-29 14:26:09 -07001181 audio_utils::lock_guard _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001182 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hungab65b182023-09-06 19:41:47 -07001183 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001184 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001185 invalidate();
1186 return PERMISSION_DENIED;
1187 }
1188 }
Andy Hung6c498e92023-12-05 17:28:17 -08001189 audio_utils::unique_lock ul(thread->mutex());
1190 thread->waitWhileThreadBusy_l(ul);
1191
Eric Laurent81784c32012-11-19 14:55:58 -08001192 track_state state = mState;
1193 // here the track could be either new, or restarted
1194 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001195
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001196 // initial state-stopping. next state-pausing.
1197 // What if resume is called ?
1198
Zhou Song1ed46a22020-08-17 15:36:56 +08001199 if (state == FLUSHED) {
1200 // avoid underrun glitches when starting after flush
1201 reset();
1202 }
1203
kuowei.li576f1362021-05-11 18:02:32 +08001204 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1205 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001206 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001207 if (mResumeToStopping) {
1208 // happened we need to resume to STOPPING_1
1209 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001210 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1211 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001212 } else {
1213 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001214 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1215 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001216 }
Eric Laurent81784c32012-11-19 14:55:58 -08001217 } else {
1218 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001219 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1220 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001221 }
1222
Andy Hung87c693c2023-07-06 20:56:16 -07001223 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001224
1225 // states to reset position info for pcm tracks
1226 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001227 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1228 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001229
1230 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1231 // Start point of track -> sink frame map. If the HAL returns a
1232 // frame position smaller than the first written frame in
1233 // updateTrackFrameInfo, the timestamp can be interpolated
1234 // instead of using a larger value.
1235 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1236 playbackThread->framesWritten());
1237 }
Andy Hunge10393e2015-06-12 13:59:33 -07001238 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001239 if (isFastTrack()) {
1240 // refresh fast track underruns on start because that field is never cleared
1241 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1242 // after stop.
1243 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1244 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001245 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001246 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001247 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001248 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001249 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001250 mState = state;
1251 }
1252 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001253
Andy Hungb68f5eb2019-12-03 16:49:17 -08001254 // Audio timing metrics are computed a few mix cycles after starting.
1255 {
1256 mLogStartCountdown = LOG_START_COUNTDOWN;
1257 mLogStartTimeNs = systemTime();
1258 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001259 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1260 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001261 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001262 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001263
Andy Hung1d3556d2018-03-29 16:30:14 -07001264 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1265 // for streaming tracks, remove the buffer read stop limit.
1266 mAudioTrackServerProxy->start();
1267 }
1268
Eric Laurentbfb1b832013-01-07 09:53:42 -08001269 // track was already in the active list, not a problem
1270 if (status == ALREADY_EXISTS) {
1271 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001272 } else {
1273 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1274 // It is usually unsafe to access the server proxy from a binder thread.
1275 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1276 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1277 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001278 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001279 ServerProxy::Buffer buffer;
1280 buffer.mFrameCount = 1;
1281 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001282 }
jiabin7434e812023-06-27 18:22:35 +00001283 if (status == NO_ERROR) {
1284 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1285 }
Eric Laurent81784c32012-11-19 14:55:58 -08001286 } else {
1287 status = BAD_VALUE;
1288 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001289 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001290 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001291 const sp<IAudioManager> audioManager =
1292 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001293 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1294 std::unique_ptr<os::PersistableBundle> bundle =
1295 std::make_unique<os::PersistableBundle>();
1296 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1297 isSpatialized());
1298 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1299 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1300 status_t result = audioManager->portEvent(mPortId,
1301 PLAYER_UPDATE_FORMAT, bundle);
1302 if (result != OK) {
1303 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1304 __func__, mPortId, result);
1305 }
1306 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001307 }
Eric Laurent81784c32012-11-19 14:55:58 -08001308 return status;
1309}
1310
Andy Hung8d31fd22023-06-26 19:20:57 -07001311void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001312{
Andy Hungc0691382018-09-12 18:01:57 -07001313 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001314 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001315 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001316 audio_utils::unique_lock ul(thread->mutex());
1317 thread->waitWhileThreadBusy_l(ul);
1318
Eric Laurent81784c32012-11-19 14:55:58 -08001319 track_state state = mState;
1320 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1321 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001322 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1323 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001324 reset();
1325 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001326 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1327 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1328 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001329 mState = STOPPED;
1330 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001331 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1332 // presentation is complete
1333 // For an offloaded track this starts a drain and state will
1334 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001335 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001336 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001337 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001338 }
Eric Laurent81784c32012-11-19 14:55:58 -08001339 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001340 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001341 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1342 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001343 }
jiabin7434e812023-06-27 18:22:35 +00001344 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001345 }
1346}
1347
Andy Hung8d31fd22023-06-26 19:20:57 -07001348void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001349{
Andy Hungc0691382018-09-12 18:01:57 -07001350 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001351 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001352 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001353 audio_utils::unique_lock ul(thread->mutex());
1354 thread->waitWhileThreadBusy_l(ul);
1355
Andy Hung87c693c2023-07-06 20:56:16 -07001356 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001357 switch (mState) {
1358 case STOPPING_1:
1359 case STOPPING_2:
1360 if (!isOffloaded()) {
1361 /* nothing to do if track is not offloaded */
1362 break;
1363 }
1364
1365 // Offloaded track was draining, we need to carry on draining when resumed
1366 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001367 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001368 case ACTIVE:
1369 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001370 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001371 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1372 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001373 if (isOffloadedOrDirect()) {
1374 mPauseHwPending = true;
1375 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001376 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001377 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001378
Eric Laurentbfb1b832013-01-07 09:53:42 -08001379 default:
1380 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001381 }
jiabin7434e812023-06-27 18:22:35 +00001382 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1383 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001384 }
1385}
1386
Andy Hung8d31fd22023-06-26 19:20:57 -07001387void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001388{
Andy Hungc0691382018-09-12 18:01:57 -07001389 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001390 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001391 if (thread != 0) {
Andy Hung6c498e92023-12-05 17:28:17 -08001392 audio_utils::unique_lock ul(thread->mutex());
1393 thread->waitWhileThreadBusy_l(ul);
1394
Andy Hung87c693c2023-07-06 20:56:16 -07001395 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001396
Phil Burk4bb650b2016-09-09 12:11:17 -07001397 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1398 // Otherwise the flush would not be done until the track is resumed.
1399 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001400 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001401 (void)mServerProxy->flushBufferIfNeeded();
1402 }
1403
Eric Laurentbfb1b832013-01-07 09:53:42 -08001404 if (isOffloaded()) {
1405 // If offloaded we allow flush during any state except terminated
1406 // and keep the track active to avoid problems if user is seeking
1407 // rapidly and underlying hardware has a significant delay handling
1408 // a pause
1409 if (isTerminated()) {
1410 return;
1411 }
1412
Andy Hung9d84af52018-09-12 18:03:44 -07001413 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001414 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001415
1416 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001417 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1418 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001419 mState = ACTIVE;
1420 }
1421
Haynes Mathew George7844f672014-01-15 12:32:55 -08001422 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001423 mResumeToStopping = false;
1424 } else {
1425 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1426 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1427 return;
1428 }
1429 // No point remaining in PAUSED state after a flush => go to
1430 // FLUSHED state
1431 mState = FLUSHED;
1432 // do not reset the track if it is still in the process of being stopped or paused.
1433 // this will be done by prepareTracks_l() when the track is stopped.
1434 // prepareTracks_l() will see mState == FLUSHED, then
1435 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001436 if (isDirect()) {
1437 mFlushHwPending = true;
1438 }
Andy Hung87c693c2023-07-06 20:56:16 -07001439 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001440 reset();
1441 }
Eric Laurent81784c32012-11-19 14:55:58 -08001442 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001443 // Prevent flush being lost if the track is flushed and then resumed
1444 // before mixer thread can run. This is important when offloading
1445 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001446 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001447 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1448 // new data
1449 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001450 }
1451}
1452
Haynes Mathew George7844f672014-01-15 12:32:55 -08001453// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001454void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001455{
Andy Hung920f6572022-10-06 12:09:49 -07001456 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001457 return;
Andy Hung920f6572022-10-06 12:09:49 -07001458 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001459
Phil Burk4bb650b2016-09-09 12:11:17 -07001460 // Clear the client ring buffer so that the app can prime the buffer while paused.
1461 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1462 mServerProxy->flushBufferIfNeeded();
1463
Haynes Mathew George7844f672014-01-15 12:32:55 -08001464 mFlushHwPending = false;
1465}
1466
Andy Hung8d31fd22023-06-26 19:20:57 -07001467void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001468{
1469 mPauseHwPending = false;
1470}
1471
Andy Hung8d31fd22023-06-26 19:20:57 -07001472void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001473{
1474 // Do not reset twice to avoid discarding data written just after a flush and before
1475 // the audioflinger thread detects the track is stopped.
1476 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001477 // Force underrun condition to avoid false underrun callback until first data is
1478 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001479 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001480 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001481 mResetDone = true;
1482 if (mState == FLUSHED) {
1483 mState = IDLE;
1484 }
1485 }
1486}
1487
Andy Hung8d31fd22023-06-26 19:20:57 -07001488status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001489{
Andy Hung87c693c2023-07-06 20:56:16 -07001490 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001491 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001492 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001493 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001494 } else if (thread->type() == IAfThreadBase::DIRECT
1495 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001496 return thread->setParameters(keyValuePairs);
1497 } else {
1498 return PERMISSION_DENIED;
1499 }
1500}
1501
Andy Hung8d31fd22023-06-26 19:20:57 -07001502status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001503 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001504 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001505 if (thread == 0) {
1506 ALOGE("thread is dead");
1507 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001508 } else if (thread->type() == IAfThreadBase::DIRECT
1509 || thread->type() == IAfThreadBase::OFFLOAD) {
1510 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001511 return directOutputThread->selectPresentation(presentationId, programId);
1512 }
1513 return INVALID_OPERATION;
1514}
1515
Andy Hung8d31fd22023-06-26 19:20:57 -07001516VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001517 const sp<VolumeShaper::Configuration>& configuration,
1518 const sp<VolumeShaper::Operation>& operation)
1519{
Andy Hung398ffa22022-12-13 19:19:53 -08001520 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001521
1522 if (isOffloadedOrDirect()) {
1523 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001524 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001525 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001526 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001527 thread->broadcast_l();
1528 }
1529 }
1530 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001531}
1532
Andy Hung8d31fd22023-06-26 19:20:57 -07001533sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001534{
1535 // Note: We don't check if Thread exists.
1536
1537 // mVolumeHandler is thread safe.
1538 return mVolumeHandler->getVolumeShaperState(id);
1539}
1540
Andy Hung8d31fd22023-06-26 19:20:57 -07001541void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001542{
jiabin76d94692022-12-15 21:51:21 +00001543 mFinalVolumeLeft = volumeLeft;
1544 mFinalVolumeRight = volumeRight;
1545 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001546 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1547 mFinalVolume = volume;
1548 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001549 mLogForceVolumeUpdate = true;
1550 }
1551 if (mLogForceVolumeUpdate) {
1552 mLogForceVolumeUpdate = false;
1553 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001554 }
1555}
1556
Andy Hung8d31fd22023-06-26 19:20:57 -07001557void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001558{
Eric Laurent49e39282022-06-24 18:42:45 +02001559 // Do not forward metadata for PatchTrack with unspecified stream type
1560 if (mStreamType == AUDIO_STREAM_PATCH) {
1561 return;
1562 }
1563
Eric Laurent94579172020-11-20 18:41:04 +01001564 playback_track_metadata_v7_t metadata;
1565 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001566 .usage = mAttr.usage,
1567 .content_type = mAttr.content_type,
1568 .gain = mFinalVolume,
1569 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001570
1571 // When attributes are undefined, derive default values from stream type.
1572 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1573 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1574 switch (mStreamType) {
1575 case AUDIO_STREAM_VOICE_CALL:
1576 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1577 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1578 break;
1579 case AUDIO_STREAM_SYSTEM:
1580 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1581 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1582 break;
1583 case AUDIO_STREAM_RING:
1584 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1585 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1586 break;
1587 case AUDIO_STREAM_MUSIC:
1588 metadata.base.usage = AUDIO_USAGE_MEDIA;
1589 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1590 break;
1591 case AUDIO_STREAM_ALARM:
1592 metadata.base.usage = AUDIO_USAGE_ALARM;
1593 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1594 break;
1595 case AUDIO_STREAM_NOTIFICATION:
1596 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1597 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1598 break;
1599 case AUDIO_STREAM_DTMF:
1600 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1601 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1602 break;
1603 case AUDIO_STREAM_ACCESSIBILITY:
1604 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1605 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1606 break;
1607 case AUDIO_STREAM_ASSISTANT:
1608 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1609 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1610 break;
1611 case AUDIO_STREAM_REROUTING:
1612 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1613 // unknown content type
1614 break;
1615 case AUDIO_STREAM_CALL_ASSISTANT:
1616 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1617 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1618 break;
1619 default:
1620 break;
1621 }
1622 }
1623
Eric Laurent78b07302022-10-07 16:20:34 +02001624 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001625 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1626 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001627}
1628
Andy Hung8d31fd22023-06-26 19:20:57 -07001629void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001630 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001631 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001632 mTeePatches = mTeePatchesToUpdate.value();
1633 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1634 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001635 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001636 }
1637 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001638 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001639}
1640
Andy Hung16ed0da2023-07-14 11:45:38 -07001641void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001642 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1643 "%s, existing tee patches to update will be ignored", __func__);
1644 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1645}
1646
Vlad Popae8d99472022-06-30 16:02:48 +02001647// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001648void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001649 IAudioManager>& audioManager, mute_state_t muteState)
1650{
1651 if (mMuteState == muteState) {
1652 // mute state did not change, do nothing
1653 return;
1654 }
1655
1656 status_t result = UNKNOWN_ERROR;
1657 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1658 if (mMuteEventExtras == nullptr) {
1659 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1660 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001661 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001662
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001663 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001664 }
1665
1666 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001667 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
1668 int(muteState), int(mMuteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001669 mMuteState = muteState;
1670 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001671 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1672 mPortId, result);
Vlad Popae8d99472022-06-30 16:02:48 +02001673 }
1674}
1675
Andy Hung8d31fd22023-06-26 19:20:57 -07001676status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001677{
Andy Hung818e7a32016-02-16 18:08:07 -08001678 if (!isOffloaded() && !isDirect()) {
1679 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001680 }
Andy Hung87c693c2023-07-06 20:56:16 -07001681 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001682 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001683 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001684 }
Phil Burk6140c792015-03-19 14:30:21 -07001685
Andy Hungc5007f82023-08-29 14:26:09 -07001686 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001687 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001688 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001689}
1690
Andy Hung8d31fd22023-06-26 19:20:57 -07001691status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001692{
Andy Hung87c693c2023-07-06 20:56:16 -07001693 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001694 if (thread == nullptr) {
1695 return DEAD_OBJECT;
1696 }
Eric Laurent81784c32012-11-19 14:55:58 -08001697
Andy Hung87c693c2023-07-06 20:56:16 -07001698 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001699 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001700 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001701 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001702 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001703
Eric Laurent6c796322019-04-09 14:13:17 -07001704 if (EffectId != 0 && status == NO_ERROR) {
1705 status = dstThread->attachAuxEffect(this, EffectId);
1706 if (status == NO_ERROR) {
1707 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001708 }
Eric Laurent6c796322019-04-09 14:13:17 -07001709 }
1710
1711 if (status != NO_ERROR && srcThread != nullptr) {
1712 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001713 }
1714 return status;
1715}
1716
Andy Hung8d31fd22023-06-26 19:20:57 -07001717void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001718{
1719 mAuxEffectId = EffectId;
1720 mAuxBuffer = buffer;
1721}
1722
Andy Hung59de4262021-06-14 10:53:54 -07001723// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001724bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001725 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001726{
Andy Hung818e7a32016-02-16 18:08:07 -08001727 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1728 // This assists in proper timestamp computation as well as wakelock management.
1729
Eric Laurent81784c32012-11-19 14:55:58 -08001730 // a track is considered presented when the total number of frames written to audio HAL
1731 // corresponds to the number of frames written when presentationComplete() is called for the
1732 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001733 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1734 // to detect when all frames have been played. In this case framesWritten isn't
1735 // useful because it doesn't always reflect whether there is data in the h/w
1736 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001737 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1738 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001739 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001740 if (mPresentationCompleteFrames == 0) {
1741 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001742 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001743 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1744 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001745 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001746 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001747
Andy Hungc54b1ff2016-02-23 14:07:07 -08001748 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001749 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001750 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001751 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1752 __func__, mId, (complete ? "complete" : "waiting"),
1753 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001754 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001755 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001756 && mAudioTrackServerProxy->isDrained();
1757 }
1758
1759 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001760 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001761 return true;
1762 }
1763 return false;
1764}
1765
Andy Hung59de4262021-06-14 10:53:54 -07001766// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001767bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001768{
1769 // For Offloaded or Direct tracks.
1770
1771 // For a direct track, we incorporated time based testing for presentationComplete.
1772
1773 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1774 // to detect when all frames have been played. In this case latencyMs isn't
1775 // useful because it doesn't always reflect whether there is data in the h/w
1776 // buffers, particularly if a track has been paused and resumed during draining
1777
1778 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1779 if (mPresentationCompleteTimeNs == 0) {
1780 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1781 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1782 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1783 }
1784
1785 bool complete;
1786 if (isOffloaded()) {
1787 complete = true;
1788 } else { // Direct
1789 complete = systemTime() >= mPresentationCompleteTimeNs;
1790 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1791 }
1792 if (complete) {
1793 notifyPresentationComplete();
1794 return true;
1795 }
1796 return false;
1797}
1798
Andy Hung8d31fd22023-06-26 19:20:57 -07001799void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001800{
1801 // This only triggers once. TODO: should we enforce this?
1802 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1803 mAudioTrackServerProxy->setStreamEndDone();
1804}
1805
Andy Hung8d31fd22023-06-26 19:20:57 -07001806void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001807{
Andy Hung068e08e2023-05-15 19:02:55 -07001808 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1809 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001810 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001811 (*it)->trigger();
1812 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001813 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001814 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001815 }
1816 }
1817}
1818
1819// implement VolumeBufferProvider interface
1820
Andy Hung8d31fd22023-06-26 19:20:57 -07001821gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001822{
1823 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1824 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001825 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1826 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1827 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001828 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001829 if (vl > GAIN_FLOAT_UNITY) {
1830 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001831 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001832 if (vr > GAIN_FLOAT_UNITY) {
1833 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001834 }
1835 // now apply the cached master volume and stream type volume;
1836 // this is trusted but lacks any synchronization or barrier so may be stale
1837 float v = mCachedVolume;
1838 vl *= v;
1839 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001840 // re-combine into packed minifloat
1841 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001842 // FIXME look at mute, pause, and stop flags
1843 return vlr;
1844}
1845
Andy Hung8d31fd22023-06-26 19:20:57 -07001846status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001847 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001848{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001849 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001850 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1851 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001852 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1853 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001854 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001855 event->cancel();
1856 return INVALID_OPERATION;
1857 }
1858 (void) TrackBase::setSyncEvent(event);
1859 return NO_ERROR;
1860}
1861
Andy Hung8d31fd22023-06-26 19:20:57 -07001862void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001863{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001864 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001865 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001866}
1867
Andy Hung8d31fd22023-06-26 19:20:57 -07001868void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001869{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001870 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001871 signalClientFlag(CBLK_DISABLED);
1872}
1873
Andy Hung8d31fd22023-06-26 19:20:57 -07001874void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001875{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001876 // FIXME should use proxy, and needs work
1877 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001878 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001879 android_atomic_release_store(0x40000000, &cblk->mFutex);
1880 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001881 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001882}
1883
Andy Hung8d31fd22023-06-26 19:20:57 -07001884void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001885{
Andy Hung87c693c2023-07-06 20:56:16 -07001886 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001887 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001888 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001889 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001890 t->broadcast_l();
1891 }
1892}
1893
Andy Hung8d31fd22023-06-26 19:20:57 -07001894status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001895{
1896 status_t status = INVALID_OPERATION;
1897 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001898 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001899 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001900 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001901 audio_utils::lock_guard _l(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001902 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001903 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1904 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1905 }
1906 }
1907 return status;
1908}
1909
Andy Hung8d31fd22023-06-26 19:20:57 -07001910status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001911{
1912 status_t status = INVALID_OPERATION;
1913 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001914 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001915 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001916 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001917 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001918 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001919 if (status == NO_ERROR) {
1920 mDualMonoMode = mode;
1921 }
1922 }
1923 }
1924 return status;
1925}
1926
Andy Hung8d31fd22023-06-26 19:20:57 -07001927status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001928{
1929 status_t status = INVALID_OPERATION;
1930 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001931 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001933 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001934 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001935 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001936 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1937 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1938 }
1939 }
1940 return status;
1941}
1942
Andy Hung8d31fd22023-06-26 19:20:57 -07001943status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001944{
1945 status_t status = INVALID_OPERATION;
1946 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001947 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001948 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001949 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001950 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001951 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001952 if (status == NO_ERROR) {
1953 mAudioDescriptionMixLevel = leveldB;
1954 }
1955 }
1956 }
1957 return status;
1958}
1959
Andy Hung8d31fd22023-06-26 19:20:57 -07001960status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001961 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001962{
1963 status_t status = INVALID_OPERATION;
1964 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001965 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001966 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001967 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001968 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001969 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001970 ALOGD_IF((status == NO_ERROR) &&
1971 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1972 "%s: playbackRate inconsistent", __func__);
1973 }
1974 }
1975 return status;
1976}
1977
Andy Hung8d31fd22023-06-26 19:20:57 -07001978status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001979 const audio_playback_rate_t& playbackRate)
1980{
1981 status_t status = INVALID_OPERATION;
1982 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001983 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001984 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001985 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001986 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001987 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001988 if (status == NO_ERROR) {
1989 mPlaybackRateParameters = playbackRate;
1990 }
1991 }
1992 }
1993 return status;
1994}
1995
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001996//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001997bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07001998 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001999 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002000 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002001 /* Resume is pending if track was stopping before pause was called */
2002 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07002003 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002004 return true;
Andy Hung920f6572022-10-06 12:09:49 -07002005 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002006
2007 return false;
2008}
2009
2010//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002011void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07002012 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002013 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07002014 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002015
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002016 // Other possibility of pending resume is stopping_1 state
2017 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002018 // drain being called.
2019 if (mState == STOPPING_1) {
2020 mResumeToStopping = false;
2021 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002022}
Andy Hunge10393e2015-06-12 13:59:33 -07002023
2024//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002025void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002026 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002027 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002028 // Make the kernel frametime available.
2029 const FrameTime ft{
2030 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2031 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2032 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2033 mKernelFrameTime.store(ft);
2034 if (!audio_is_linear_pcm(mFormat)) {
2035 return;
2036 }
2037
Andy Hung818e7a32016-02-16 18:08:07 -08002038 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002039 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002040
2041 // adjust server times and set drained state.
2042 //
2043 // Our timestamps are only updated when the track is on the Thread active list.
2044 // We need to ensure that tracks are not removed before full drain.
2045 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002046 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002047 bool checked = false;
2048 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2049 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2050 // Lookup the track frame corresponding to the sink frame position.
2051 if (local.mTimeNs[i] > 0) {
2052 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2053 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002054 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002055 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002056 checked = true;
2057 }
2058 }
Andy Hunge10393e2015-06-12 13:59:33 -07002059 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002060
Andy Hung93bb5732023-05-04 21:16:34 -07002061 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2062 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002063 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002064 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002065 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002066 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002067
2068 // Compute latency info.
2069 const bool useTrackTimestamp = !drained;
2070 const double latencyMs = useTrackTimestamp
2071 ? local.getOutputServerLatencyMs(sampleRate())
2072 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2073
2074 mServerLatencyFromTrack.store(useTrackTimestamp);
2075 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002076
Andy Hung62921122020-05-18 10:47:31 -07002077 if (mLogStartCountdown > 0
2078 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2079 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2080 {
2081 if (mLogStartCountdown > 1) {
2082 --mLogStartCountdown;
2083 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2084 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002085 // startup is the difference in times for the current timestamp and our start
2086 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002087 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002088 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002089 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2090 * 1e3 / mSampleRate;
2091 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2092 " localTime:%lld startTime:%lld"
2093 " localPosition:%lld startPosition:%lld",
2094 __func__, latencyMs, startUpMs,
2095 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002096 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002097 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002098 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002099 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002100 }
Andy Hung62921122020-05-18 10:47:31 -07002101 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002102 }
Andy Hunge10393e2015-06-12 13:59:33 -07002103}
2104
Andy Hung8d31fd22023-06-26 19:20:57 -07002105bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002106 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002107 if (thread != 0) {
2108 // Lock for updating mHapticPlaybackEnabled.
Andy Hungc5007f82023-08-29 14:26:09 -07002109 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002110 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002111 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002112 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002113 ALOGD("%s, haptic playback was %s for track %d",
2114 __func__, muted ? "muted" : "unmuted", mTrack->id());
2115 mTrack->setHapticPlaybackEnabled(!muted);
2116 return true;
jiabin57303cc2018-12-18 15:45:57 -08002117 }
2118 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002119 return false;
2120}
2121
Andy Hung8d31fd22023-06-26 19:20:57 -07002122binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002123 /*out*/ bool *ret) {
2124 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002125 return binder::Status::ok();
2126}
2127
Andy Hung8d31fd22023-06-26 19:20:57 -07002128binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002129 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002130 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002131 return binder::Status::ok();
2132}
2133
Eric Laurent81784c32012-11-19 14:55:58 -08002134// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002135#undef LOG_TAG
2136#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002137
Andy Hung8d31fd22023-06-26 19:20:57 -07002138/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002139sp<IAfOutputTrack> IAfOutputTrack::create(
2140 IAfPlaybackThread* playbackThread,
2141 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002142 uint32_t sampleRate,
2143 audio_format_t format,
2144 audio_channel_mask_t channelMask,
2145 size_t frameCount,
2146 const AttributionSourceState& attributionSource) {
2147 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002148 playbackThread,
2149 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002150 sampleRate,
2151 format,
2152 channelMask,
2153 frameCount,
2154 attributionSource);
2155}
2156
2157OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002158 IAfPlaybackThread* playbackThread,
2159 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002160 uint32_t sampleRate,
2161 audio_format_t format,
2162 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002163 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002164 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002165 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002166 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002167 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002168 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002169 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002170 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002171 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002172{
2173
2174 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002175 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002176 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002177 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002178 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002179 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002180 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002181 // since client and server are in the same process,
2182 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002183 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2184 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002185 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002186 mClientProxy->setSendLevel(0.0);
2187 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002188 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002189 ALOGW("%s(%d): Error creating output track on thread %d",
2190 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002191 }
2192}
2193
Andy Hung8d31fd22023-06-26 19:20:57 -07002194OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002195{
2196 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002197 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002198}
2199
Andy Hung8d31fd22023-06-26 19:20:57 -07002200status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002201 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002202{
2203 status_t status = Track::start(event, triggerSession);
2204 if (status != NO_ERROR) {
2205 return status;
2206 }
2207
2208 mActive = true;
2209 mRetryCount = 127;
2210 return status;
2211}
2212
Andy Hung8d31fd22023-06-26 19:20:57 -07002213void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002214{
2215 Track::stop();
2216 clearBufferQueue();
2217 mOutBuffer.frameCount = 0;
2218 mActive = false;
2219}
2220
Andy Hung8d31fd22023-06-26 19:20:57 -07002221ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002222{
Eric Laurent19952e12023-04-20 10:08:29 +02002223 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002224 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002225 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002226 // preload one silent buffer to trigger mixer on start()
2227 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2228 status_t status = mClientProxy->obtainBuffer(&buf);
2229 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2230 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2231 return 0;
2232 }
2233 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2234 mClientProxy->releaseBuffer(&buf);
2235
2236 (void) start();
2237
2238 // wait for HAL stream to start before sending actual audio. Doing this on each
2239 // OutputTrack makes that playback start on all output streams is synchronized.
2240 // If another OutputTrack has already started it can underrun but this is OK
2241 // as only silence has been played so far and the retry count is very high on
2242 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002243 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002244 if (!pt->waitForHalStart()) {
2245 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2246 stop();
2247 return 0;
2248 }
2249
2250 // enqueue the first buffer and exit so that other OutputTracks will also start before
2251 // write() is called again and this buffer actually consumed.
2252 Buffer firstBuffer;
2253 firstBuffer.frameCount = frames;
2254 firstBuffer.raw = data;
2255 queueBuffer(firstBuffer);
2256 return frames;
2257 } else {
2258 (void) start();
2259 }
2260 }
2261
Eric Laurent81784c32012-11-19 14:55:58 -08002262 Buffer *pInBuffer;
2263 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002264 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002265 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002266 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002267 while (waitTimeLeftMs) {
2268 // First write pending buffers, then new data
2269 if (mBufferQueue.size()) {
2270 pInBuffer = mBufferQueue.itemAt(0);
2271 } else {
2272 pInBuffer = &inBuffer;
2273 }
2274
2275 if (pInBuffer->frameCount == 0) {
2276 break;
2277 }
2278
2279 if (mOutBuffer.frameCount == 0) {
2280 mOutBuffer.frameCount = pInBuffer->frameCount;
2281 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002282 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002283 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002284 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2285 __func__, mId,
2286 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002287 break;
2288 }
2289 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2290 if (waitTimeLeftMs >= waitTimeMs) {
2291 waitTimeLeftMs -= waitTimeMs;
2292 } else {
2293 waitTimeLeftMs = 0;
2294 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002295 if (status == NOT_ENOUGH_DATA) {
2296 restartIfDisabled();
2297 continue;
2298 }
Eric Laurent81784c32012-11-19 14:55:58 -08002299 }
2300
2301 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2302 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002303 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002304 Proxy::Buffer buf;
2305 buf.mFrameCount = outFrames;
2306 buf.mRaw = NULL;
2307 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002308 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002309 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002310 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002311 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002312 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002313
2314 if (pInBuffer->frameCount == 0) {
2315 if (mBufferQueue.size()) {
2316 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002317 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002318 if (pInBuffer != &inBuffer) {
2319 delete pInBuffer;
2320 }
Andy Hung9d84af52018-09-12 18:03:44 -07002321 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2322 __func__, mId,
2323 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002324 } else {
2325 break;
2326 }
2327 }
2328 }
2329
2330 // If we could not write all frames, allocate a buffer and queue it for next time.
2331 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002332 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002333 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002334 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002335 }
2336 }
2337
Andy Hungc25b84a2015-01-14 19:04:10 -08002338 // Calling write() with a 0 length buffer means that no more data will be written:
2339 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2340 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2341 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002342 }
2343
Andy Hung1c86ebe2018-05-29 20:29:08 -07002344 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002345}
2346
Andy Hung8d31fd22023-06-26 19:20:57 -07002347void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002348
2349 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2350 Buffer *pInBuffer = new Buffer;
2351 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2352 pInBuffer->mBuffer = malloc(bufferSize);
2353 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2354 "%s: Unable to malloc size %zu", __func__, bufferSize);
2355 pInBuffer->frameCount = inBuffer.frameCount;
2356 pInBuffer->raw = pInBuffer->mBuffer;
2357 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2358 mBufferQueue.add(pInBuffer);
2359 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2360 (int)mThreadIoHandle, mBufferQueue.size());
2361 // audio data is consumed (stored locally); set frameCount to 0.
2362 inBuffer.frameCount = 0;
2363 } else {
2364 ALOGW("%s(%d): thread %d no more overflow buffers",
2365 __func__, mId, (int)mThreadIoHandle);
2366 // TODO: return error for this.
2367 }
2368}
2369
Andy Hung8d31fd22023-06-26 19:20:57 -07002370void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002371{
Andy Hungc5007f82023-08-29 14:26:09 -07002372 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002373 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2374}
2375
Andy Hung8d31fd22023-06-26 19:20:57 -07002376void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002377 {
Andy Hungc5007f82023-08-29 14:26:09 -07002378 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002379 mTrackMetadatas = metadatas;
2380 }
2381 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2382 setMetadataHasChanged();
2383}
2384
Andy Hung8d31fd22023-06-26 19:20:57 -07002385status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002386 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2387{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002388 ClientProxy::Buffer buf;
2389 buf.mFrameCount = buffer->frameCount;
2390 struct timespec timeout;
2391 timeout.tv_sec = waitTimeMs / 1000;
2392 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2393 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2394 buffer->frameCount = buf.mFrameCount;
2395 buffer->raw = buf.mRaw;
2396 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002397}
2398
Andy Hung8d31fd22023-06-26 19:20:57 -07002399void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002400{
2401 size_t size = mBufferQueue.size();
2402
2403 for (size_t i = 0; i < size; i++) {
2404 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002405 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002406 delete pBuffer;
2407 }
2408 mBufferQueue.clear();
2409}
2410
Andy Hung8d31fd22023-06-26 19:20:57 -07002411void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002412{
2413 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2414 if (mActive && (flags & CBLK_DISABLED)) {
2415 start();
2416 }
2417}
Eric Laurent81784c32012-11-19 14:55:58 -08002418
Andy Hung9d84af52018-09-12 18:03:44 -07002419// ----------------------------------------------------------------------------
2420#undef LOG_TAG
2421#define LOG_TAG "AF::PatchTrack"
2422
Andy Hung8d31fd22023-06-26 19:20:57 -07002423/* static */
2424sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002425 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002426 audio_stream_type_t streamType,
2427 uint32_t sampleRate,
2428 audio_channel_mask_t channelMask,
2429 audio_format_t format,
2430 size_t frameCount,
2431 void* buffer,
2432 size_t bufferSize,
2433 audio_output_flags_t flags,
2434 const Timeout& timeout,
2435 size_t frameCountToBeReady /** Default behaviour is to start
2436 * as soon as possible to have
2437 * the lowest possible latency
2438 * even if it might glitch. */)
2439{
2440 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002441 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002442 streamType,
2443 sampleRate,
2444 channelMask,
2445 format,
2446 frameCount,
2447 buffer,
2448 bufferSize,
2449 flags,
2450 timeout,
2451 frameCountToBeReady);
2452}
2453
Andy Hung87c693c2023-07-06 20:56:16 -07002454PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002455 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002456 uint32_t sampleRate,
2457 audio_channel_mask_t channelMask,
2458 audio_format_t format,
2459 size_t frameCount,
2460 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002461 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002462 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002463 const Timeout& timeout,
2464 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002465 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002466 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002467 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002468 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002469 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002470 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002471 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2472 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002473 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002474{
Andy Hung9d84af52018-09-12 18:03:44 -07002475 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2476 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002477 (int)mPeerTimeout.tv_sec,
2478 (int)(mPeerTimeout.tv_nsec / 1000000));
2479}
2480
Andy Hung8d31fd22023-06-26 19:20:57 -07002481PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002482{
Andy Hungabfab202019-03-07 19:45:54 -08002483 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002484}
2485
Andy Hung8d31fd22023-06-26 19:20:57 -07002486size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002487{
2488 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2489 return std::numeric_limits<size_t>::max();
2490 } else {
2491 return Track::framesReady();
2492 }
2493}
2494
Andy Hung8d31fd22023-06-26 19:20:57 -07002495status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002496 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002497{
2498 status_t status = Track::start(event, triggerSession);
2499 if (status != NO_ERROR) {
2500 return status;
2501 }
2502 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2503 return status;
2504}
2505
Eric Laurent83b88082014-06-20 18:31:16 -07002506// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002507status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002508 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002509{
Andy Hung9d84af52018-09-12 18:03:44 -07002510 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002511 Proxy::Buffer buf;
2512 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002513 if (ATRACE_ENABLED()) {
2514 std::string traceName("PTnReq");
2515 traceName += std::to_string(id());
2516 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2517 }
Eric Laurent83b88082014-06-20 18:31:16 -07002518 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002519 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002520 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002521 if (ATRACE_ENABLED()) {
2522 std::string traceName("PTnObt");
2523 traceName += std::to_string(id());
2524 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2525 }
Eric Laurent83b88082014-06-20 18:31:16 -07002526 if (buf.mFrameCount == 0) {
2527 return WOULD_BLOCK;
2528 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002529 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002530 return status;
2531}
2532
Andy Hung8d31fd22023-06-26 19:20:57 -07002533void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002534{
Andy Hung9d84af52018-09-12 18:03:44 -07002535 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002536 Proxy::Buffer buf;
2537 buf.mFrameCount = buffer->frameCount;
2538 buf.mRaw = buffer->raw;
2539 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002540 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002541}
2542
Andy Hung8d31fd22023-06-26 19:20:57 -07002543status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002544 const struct timespec *timeOut)
2545{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002546 status_t status = NO_ERROR;
2547 static const int32_t kMaxTries = 5;
2548 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002549 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002550 do {
2551 if (status == NOT_ENOUGH_DATA) {
2552 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002553 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002554 }
2555 status = mProxy->obtainBuffer(buffer, timeOut);
2556 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2557 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002558}
2559
Andy Hung8d31fd22023-06-26 19:20:57 -07002560void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002561{
2562 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002563 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002564
2565 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2566 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2567 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2568 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002569 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002570 && audio_is_linear_pcm(mFormat)
2571 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002572 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002573 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002574 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002575 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2576 / playbackThread->sampleRate();
2577 if (framesReady() < frameCount) {
2578 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002579 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002580 }
2581 }
2582 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002583}
2584
Andy Hung8d31fd22023-06-26 19:20:57 -07002585void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002586{
Eric Laurent83b88082014-06-20 18:31:16 -07002587 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002588 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002589 start();
2590 }
Eric Laurent83b88082014-06-20 18:31:16 -07002591}
2592
Eric Laurent81784c32012-11-19 14:55:58 -08002593// ----------------------------------------------------------------------------
2594// Record
2595// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002596
2597
Andy Hung9d84af52018-09-12 18:03:44 -07002598#undef LOG_TAG
2599#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002600
Andy Hunga5a7fc92023-06-23 19:27:19 -07002601class RecordHandle : public android::media::BnAudioRecord {
2602public:
Andy Hungd29af632023-06-23 19:27:19 -07002603 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002604 ~RecordHandle() override;
2605 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2606 int /*audio_session_t*/ triggerSession) final;
2607 binder::Status stop() final;
2608 binder::Status getActiveMicrophones(
2609 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2610 binder::Status setPreferredMicrophoneDirection(
2611 int /*audio_microphone_direction_t*/ direction) final;
2612 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2613 binder::Status shareAudioHistory(
2614 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2615
2616private:
Andy Hungd29af632023-06-23 19:27:19 -07002617 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002618
2619 // for use from destructor
2620 void stop_nonvirtual();
2621};
2622
2623/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002624sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2625 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002626 return sp<RecordHandle>::make(recordTrack);
2627}
2628
2629RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002630 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002631 : BnAudioRecord(),
2632 mRecordTrack(recordTrack)
2633{
Andy Hung225aef62022-12-06 16:33:20 -08002634 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002635}
2636
Andy Hunga5a7fc92023-06-23 19:27:19 -07002637RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002638 stop_nonvirtual();
2639 mRecordTrack->destroy();
2640}
2641
Andy Hunga5a7fc92023-06-23 19:27:19 -07002642binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002643 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002644 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002645 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002646 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002647}
2648
Andy Hunga5a7fc92023-06-23 19:27:19 -07002649binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002650 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002651 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002652}
2653
Andy Hunga5a7fc92023-06-23 19:27:19 -07002654void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002655 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002656 mRecordTrack->stop();
2657}
2658
Andy Hunga5a7fc92023-06-23 19:27:19 -07002659binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002660 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002661 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002662 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002663}
2664
Andy Hunga5a7fc92023-06-23 19:27:19 -07002665binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002666 int /*audio_microphone_direction_t*/ direction) {
2667 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002668 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002669 static_cast<audio_microphone_direction_t>(direction)));
2670}
2671
Andy Hunga5a7fc92023-06-23 19:27:19 -07002672binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002673 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002674 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002675}
2676
Andy Hunga5a7fc92023-06-23 19:27:19 -07002677binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002678 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2679 return binderStatusFromStatusT(
2680 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2681}
2682
Eric Laurent81784c32012-11-19 14:55:58 -08002683// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002684#undef LOG_TAG
2685#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002686
Andy Hung8d31fd22023-06-26 19:20:57 -07002687
Andy Hung99b1ba62023-07-14 11:00:08 -07002688/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002689sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002690 const sp<Client>& client,
2691 const audio_attributes_t& attr,
2692 uint32_t sampleRate,
2693 audio_format_t format,
2694 audio_channel_mask_t channelMask,
2695 size_t frameCount,
2696 void* buffer,
2697 size_t bufferSize,
2698 audio_session_t sessionId,
2699 pid_t creatorPid,
2700 const AttributionSourceState& attributionSource,
2701 audio_input_flags_t flags,
2702 track_type type,
2703 audio_port_handle_t portId,
2704 int32_t startFrames)
2705{
2706 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002707 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002708 client,
2709 attr,
2710 sampleRate,
2711 format,
2712 channelMask,
2713 frameCount,
2714 buffer,
2715 bufferSize,
2716 sessionId,
2717 creatorPid,
2718 attributionSource,
2719 flags,
2720 type,
2721 portId,
2722 startFrames);
2723}
2724
Glenn Kasten05997e22014-03-13 15:08:33 -07002725// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002726RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002727 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002728 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002729 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002730 uint32_t sampleRate,
2731 audio_format_t format,
2732 audio_channel_mask_t channelMask,
2733 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002734 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002735 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002736 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002737 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002738 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002739 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002740 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002741 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002742 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002743 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002744 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002745 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002746 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002747 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002748 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002749 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002750 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002751 type, portId,
2752 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002753 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002754 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002755 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002756 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002757 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002758 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002759{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002760 if (mCblk == NULL) {
2761 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002762 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002763
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002764 if (!isDirect()) {
2765 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002766 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002767 channelMask, format, sampleRate);
2768 // Check if the RecordBufferConverter construction was successful.
2769 // If not, don't continue with construction.
2770 //
2771 // NOTE: It would be extremely rare that the record track cannot be created
2772 // for the current device, but a pending or future device change would make
2773 // the record track configuration valid.
2774 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002775 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002776 return;
2777 }
Andy Hung97a893e2015-03-29 01:03:07 -07002778 }
2779
Andy Hung6ae58432016-02-16 18:32:24 -08002780 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002781 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002782
Andy Hung97a893e2015-03-29 01:03:07 -07002783 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002784
Eric Laurent05067782016-06-01 18:27:28 -07002785 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002786 ALOG_ASSERT(thread->fastTrackAvailable());
2787 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002788 } else {
2789 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002790 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002791 }
Andy Hung8946a282018-04-19 20:04:56 -07002792#ifdef TEE_SINK
2793 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2794 + "_" + std::to_string(mId)
2795 + "_R");
2796#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002797
2798 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002799 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002800}
2801
Andy Hung8d31fd22023-06-26 19:20:57 -07002802RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002803{
Andy Hung9d84af52018-09-12 18:03:44 -07002804 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002805 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002806 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002807}
2808
Andy Hung8d31fd22023-06-26 19:20:57 -07002809status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002810{
2811 status_t status = TrackBase::initCheck();
2812 if (status == NO_ERROR && mServerProxy == 0) {
2813 status = BAD_VALUE;
2814 }
2815 return status;
2816}
2817
Eric Laurent81784c32012-11-19 14:55:58 -08002818// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002819status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002820{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002821 ServerProxy::Buffer buf;
2822 buf.mFrameCount = buffer->frameCount;
2823 status_t status = mServerProxy->obtainBuffer(&buf);
2824 buffer->frameCount = buf.mFrameCount;
2825 buffer->raw = buf.mRaw;
2826 if (buf.mFrameCount == 0) {
2827 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002828 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002829 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002830 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002831}
2832
Andy Hung8d31fd22023-06-26 19:20:57 -07002833status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002834 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002835{
Andy Hung87c693c2023-07-06 20:56:16 -07002836 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002837 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002838 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002839 return recordThread->start(this, event, triggerSession);
2840 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002841 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2842 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002843 }
2844}
2845
Andy Hung8d31fd22023-06-26 19:20:57 -07002846void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002847{
Andy Hung87c693c2023-07-06 20:56:16 -07002848 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002849 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002850 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002851 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002852 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002853 }
2854 }
2855}
2856
Andy Hung8d31fd22023-06-26 19:20:57 -07002857void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002858{
Andy Hung8d31fd22023-06-26 19:20:57 -07002859 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002860 sp<RecordTrack> keep(this);
2861 {
Andy Hungce685402018-10-05 17:23:27 -07002862 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002863 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002864 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07002865 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002866 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002867 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002868 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002869 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002870 }
Andy Hungce685402018-10-05 17:23:27 -07002871 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2872 }
2873 // APM portid/client management done outside of lock.
2874 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2875 if (isExternalTrack()) {
2876 switch (priorState) {
2877 case ACTIVE: // invalidated while still active
2878 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2879 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2880 AudioSystem::stopInput(mPortId);
2881 break;
2882
2883 case STARTING_1: // invalidated/start-aborted and startInput not successful
2884 case PAUSED: // OK, not active
2885 case IDLE: // OK, not active
2886 break;
2887
2888 case STOPPED: // unexpected (destroyed)
2889 default:
2890 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2891 }
2892 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002893 }
2894 }
2895}
2896
Andy Hung8d31fd22023-06-26 19:20:57 -07002897void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002898{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002899 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002900 // FIXME should use proxy, and needs work
2901 audio_track_cblk_t* cblk = mCblk;
2902 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2903 android_atomic_release_store(0x40000000, &cblk->mFutex);
2904 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002905 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002906}
2907
Eric Laurent81784c32012-11-19 14:55:58 -08002908
Andy Hung8d31fd22023-06-26 19:20:57 -07002909void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002910{
Eric Laurent973db022018-11-20 14:54:31 -08002911 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002912 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002913 " Server FrmCnt FrmRdy Sil%s\n",
2914 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002915}
2916
Andy Hung8d31fd22023-06-26 19:20:57 -07002917void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002918{
Eric Laurent973db022018-11-20 14:54:31 -08002919 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002920 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002921 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002922 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002923 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002924 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002925 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002926 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002927 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002928 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002929 mCblk->mFlags,
2930
Eric Laurent81784c32012-11-19 14:55:58 -08002931 mFormat,
2932 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002933 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002934 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002935
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002936 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002937 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002938 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002939 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002940 );
Andy Hung000adb52018-06-01 15:43:26 -07002941 if (isServerLatencySupported()) {
2942 double latencyMs;
2943 bool fromTrack;
2944 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2945 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2946 // or 'k' if estimated from kernel (usually for debugging).
2947 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2948 } else {
2949 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2950 }
2951 }
2952 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002953}
2954
Andy Hung93bb5732023-05-04 21:16:34 -07002955// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002956void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002957 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002958{
Andy Hung93bb5732023-05-04 21:16:34 -07002959 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002960 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002961 if (threadBase != 0) {
2962 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2963 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07002964 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002965 }
Andy Hung93bb5732023-05-04 21:16:34 -07002966
2967 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002968}
2969
Andy Hung8d31fd22023-06-26 19:20:57 -07002970void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002971{
Andy Hung93bb5732023-05-04 21:16:34 -07002972 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002973}
2974
Andy Hung8d31fd22023-06-26 19:20:57 -07002975void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002976 int64_t trackFramesReleased, int64_t sourceFramesRead,
2977 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2978{
Andy Hung30282562018-08-08 18:27:03 -07002979 // Make the kernel frametime available.
2980 const FrameTime ft{
2981 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2982 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2983 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2984 mKernelFrameTime.store(ft);
2985 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002986 // Stream is direct, return provided timestamp with no conversion
2987 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002988 return;
2989 }
2990
Andy Hung3f0c9022016-01-15 17:49:46 -08002991 ExtendedTimestamp local = timestamp;
2992
2993 // Convert HAL frames to server-side track frames at track sample rate.
2994 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2995 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2996 if (local.mTimeNs[i] != 0) {
2997 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2998 const int64_t relativeTrackFrames = relativeServerFrames
2999 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3000 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3001 }
3002 }
Andy Hung6ae58432016-02-16 18:32:24 -08003003 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003004
3005 // Compute latency info.
3006 const bool useTrackTimestamp = true; // use track unless debugging.
3007 const double latencyMs = - (useTrackTimestamp
3008 ? local.getOutputServerLatencyMs(sampleRate())
3009 : timestamp.getOutputServerLatencyMs(halSampleRate));
3010
3011 mServerLatencyFromTrack.store(useTrackTimestamp);
3012 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003013}
Eric Laurent83b88082014-06-20 18:31:16 -07003014
Andy Hung8d31fd22023-06-26 19:20:57 -07003015status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07003016 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003017{
Andy Hung87c693c2023-07-06 20:56:16 -07003018 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003019 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003020 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003021 return recordThread->getActiveMicrophones(activeMicrophones);
3022 } else {
3023 return BAD_VALUE;
3024 }
3025}
3026
Andy Hung8d31fd22023-06-26 19:20:57 -07003027status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003028 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003029 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003030 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003031 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003032 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003033 } else {
3034 return BAD_VALUE;
3035 }
3036}
3037
Andy Hung8d31fd22023-06-26 19:20:57 -07003038status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003039 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003040 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003041 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003042 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003043 } else {
3044 return BAD_VALUE;
3045 }
3046}
3047
Andy Hung8d31fd22023-06-26 19:20:57 -07003048status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003049 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3050
3051 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3052 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3053 if (callingUid != mUid || callingPid != mCreatorPid) {
3054 return PERMISSION_DENIED;
3055 }
3056
Svet Ganov33761132021-05-13 22:51:08 +00003057 AttributionSourceState attributionSource{};
3058 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3059 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3060 attributionSource.token = sp<BBinder>::make();
3061 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003062 return PERMISSION_DENIED;
3063 }
3064
Andy Hung87c693c2023-07-06 20:56:16 -07003065 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003066 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003067 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003068 status_t status = recordThread->shareAudioHistory(
3069 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3070 if (status == NO_ERROR) {
3071 mSharedAudioPackageName = sharedAudioPackageName;
3072 }
3073 return status;
3074 } else {
3075 return BAD_VALUE;
3076 }
3077}
3078
Andy Hung8d31fd22023-06-26 19:20:57 -07003079void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003080{
3081
3082 // Do not forward PatchRecord metadata with unspecified audio source
3083 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3084 return;
3085 }
3086
3087 // No track is invalid as this is called after prepareTrack_l in the same critical section
3088 record_track_metadata_v7_t metadata;
3089 metadata.base = {
3090 .source = mAttr.source,
3091 .gain = 1, // capture tracks do not have volumes
3092 };
3093 metadata.channel_mask = mChannelMask;
3094 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3095
3096 *backInserter++ = metadata;
3097}
Eric Laurentec376dc2021-04-08 20:41:22 +02003098
Andy Hung9d84af52018-09-12 18:03:44 -07003099// ----------------------------------------------------------------------------
3100#undef LOG_TAG
3101#define LOG_TAG "AF::PatchRecord"
3102
Andy Hung8d31fd22023-06-26 19:20:57 -07003103/* static */
3104sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003105 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003106 uint32_t sampleRate,
3107 audio_channel_mask_t channelMask,
3108 audio_format_t format,
3109 size_t frameCount,
3110 void *buffer,
3111 size_t bufferSize,
3112 audio_input_flags_t flags,
3113 const Timeout& timeout,
3114 audio_source_t source)
3115{
3116 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003117 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003118 sampleRate,
3119 channelMask,
3120 format,
3121 frameCount,
3122 buffer,
3123 bufferSize,
3124 flags,
3125 timeout,
3126 source);
3127}
3128
Andy Hung87c693c2023-07-06 20:56:16 -07003129PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003130 uint32_t sampleRate,
3131 audio_channel_mask_t channelMask,
3132 audio_format_t format,
3133 size_t frameCount,
3134 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003135 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003136 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003137 const Timeout& timeout,
3138 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003139 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003140 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003141 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003142 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003143 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003144 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3145 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003146 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003147{
Andy Hung9d84af52018-09-12 18:03:44 -07003148 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3149 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003150 (int)mPeerTimeout.tv_sec,
3151 (int)(mPeerTimeout.tv_nsec / 1000000));
3152}
3153
Andy Hung8d31fd22023-06-26 19:20:57 -07003154PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003155{
Andy Hungabfab202019-03-07 19:45:54 -08003156 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003157}
3158
Mikhail Naganov8296c252019-09-25 14:59:54 -07003159static size_t writeFramesHelper(
3160 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3161{
3162 AudioBufferProvider::Buffer patchBuffer;
3163 patchBuffer.frameCount = frameCount;
3164 auto status = dest->getNextBuffer(&patchBuffer);
3165 if (status != NO_ERROR) {
3166 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3167 __func__, status, strerror(-status));
3168 return 0;
3169 }
3170 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3171 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3172 size_t framesWritten = patchBuffer.frameCount;
3173 dest->releaseBuffer(&patchBuffer);
3174 return framesWritten;
3175}
3176
3177// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003178size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003179 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3180{
3181 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3182 // On buffer wrap, the buffer frame count will be less than requested,
3183 // when this happens a second buffer needs to be used to write the leftover audio
3184 const size_t framesLeft = frameCount - framesWritten;
3185 if (framesWritten != 0 && framesLeft != 0) {
3186 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3187 framesLeft, frameSize);
3188 }
3189 return framesWritten;
3190}
3191
Eric Laurent83b88082014-06-20 18:31:16 -07003192// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003193status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003194 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003195{
Andy Hung9d84af52018-09-12 18:03:44 -07003196 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003197 Proxy::Buffer buf;
3198 buf.mFrameCount = buffer->frameCount;
3199 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3200 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003201 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003202 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003203 if (ATRACE_ENABLED()) {
3204 std::string traceName("PRnObt");
3205 traceName += std::to_string(id());
3206 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3207 }
Eric Laurent83b88082014-06-20 18:31:16 -07003208 if (buf.mFrameCount == 0) {
3209 return WOULD_BLOCK;
3210 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003211 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003212 return status;
3213}
3214
Andy Hung8d31fd22023-06-26 19:20:57 -07003215void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003216{
Andy Hung9d84af52018-09-12 18:03:44 -07003217 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003218 Proxy::Buffer buf;
3219 buf.mFrameCount = buffer->frameCount;
3220 buf.mRaw = buffer->raw;
3221 mPeerProxy->releaseBuffer(&buf);
3222 TrackBase::releaseBuffer(buffer);
3223}
3224
Andy Hung8d31fd22023-06-26 19:20:57 -07003225status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003226 const struct timespec *timeOut)
3227{
3228 return mProxy->obtainBuffer(buffer, timeOut);
3229}
3230
Andy Hung8d31fd22023-06-26 19:20:57 -07003231void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003232{
3233 mProxy->releaseBuffer(buffer);
3234}
3235
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003236#undef LOG_TAG
3237#define LOG_TAG "AF::PthrPatchRecord"
3238
3239static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3240{
3241 void *ptr = nullptr;
3242 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003243 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003244}
3245
Andy Hung8d31fd22023-06-26 19:20:57 -07003246/* static */
3247sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003248 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003249 uint32_t sampleRate,
3250 audio_channel_mask_t channelMask,
3251 audio_format_t format,
3252 size_t frameCount,
3253 audio_input_flags_t flags,
3254 audio_source_t source)
3255{
3256 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003257 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003258 sampleRate,
3259 channelMask,
3260 format,
3261 frameCount,
3262 flags,
3263 source);
3264}
3265
3266PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003267 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003268 uint32_t sampleRate,
3269 audio_channel_mask_t channelMask,
3270 audio_format_t format,
3271 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003272 audio_input_flags_t flags,
3273 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003274 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003275 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003276 mPatchRecordAudioBufferProvider(*this),
3277 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3278 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3279{
3280 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3281}
3282
Andy Hung8d31fd22023-06-26 19:20:57 -07003283sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003284 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003285{
3286 *thread = mThread.promote();
3287 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003288 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07003289 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07003290 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003291}
3292
3293// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003294status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003295 Proxy::Buffer* buffer, const struct timespec* timeOut)
3296{
3297 if (mUnconsumedFrames) {
3298 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3299 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3300 return PatchRecord::obtainBuffer(buffer, timeOut);
3301 }
3302
3303 // Otherwise, execute a read from HAL and write into the buffer.
3304 nsecs_t startTimeNs = 0;
3305 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3306 // Will need to correct timeOut by elapsed time.
3307 startTimeNs = systemTime();
3308 }
3309 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3310 buffer->mFrameCount = 0;
3311 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003312 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003313 sp<StreamInHalInterface> stream = obtainStream(&thread);
3314 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3315
3316 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003317 size_t bytesRead = 0;
3318 {
3319 ATRACE_NAME("read");
3320 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3321 if (result != NO_ERROR) goto stream_error;
3322 if (bytesRead == 0) return NO_ERROR;
3323 }
3324
3325 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003326 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003327 mReadBytes += bytesRead;
3328 mReadError = NO_ERROR;
3329 }
3330 mReadCV.notify_one();
3331 // writeFrames handles wraparound and should write all the provided frames.
3332 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3333 buffer->mFrameCount = writeFrames(
3334 &mPatchRecordAudioBufferProvider,
3335 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3336 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3337 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3338 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003339 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003340 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003341 // Correct the timeout by elapsed time.
3342 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003343 if (newTimeOutNs < 0) newTimeOutNs = 0;
3344 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3345 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003346 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003347 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003348 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003349
3350stream_error:
3351 stream->standby();
3352 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003353 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003354 mReadError = result;
3355 }
3356 mReadCV.notify_one();
3357 return result;
3358}
3359
Andy Hung8d31fd22023-06-26 19:20:57 -07003360void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003361{
3362 if (buffer->mFrameCount <= mUnconsumedFrames) {
3363 mUnconsumedFrames -= buffer->mFrameCount;
3364 } else {
3365 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3366 buffer->mFrameCount, mUnconsumedFrames);
3367 mUnconsumedFrames = 0;
3368 }
3369 PatchRecord::releaseBuffer(buffer);
3370}
3371
3372// AudioBufferProvider and Source methods are called on RecordThread
3373// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3374// and 'releaseBuffer' are stubbed out and ignore their input.
3375// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3376// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003377status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003378 void* buffer, size_t bytes, size_t* read)
3379{
3380 bytes = std::min(bytes, mFrameCount * mFrameSize);
3381 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003382 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003383 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3384 if (mReadError != NO_ERROR) {
3385 mLastReadFrames = 0;
3386 return mReadError;
3387 }
3388 *read = std::min(bytes, mReadBytes);
3389 mReadBytes -= *read;
3390 }
3391 mLastReadFrames = *read / mFrameSize;
3392 memset(buffer, 0, *read);
3393 return 0;
3394}
3395
Andy Hung8d31fd22023-06-26 19:20:57 -07003396status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003397 int64_t* frames, int64_t* time)
3398{
Andy Hung87c693c2023-07-06 20:56:16 -07003399 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003400 sp<StreamInHalInterface> stream = obtainStream(&thread);
3401 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3402}
3403
Andy Hung8d31fd22023-06-26 19:20:57 -07003404status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003405{
3406 // RecordThread issues 'standby' command in two major cases:
3407 // 1. Error on read--this case is handled in 'obtainBuffer'.
3408 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3409 // output, this can only happen when the software patch
3410 // is being torn down. In this case, the RecordThread
3411 // will terminate and close the HAL stream.
3412 return 0;
3413}
3414
3415// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003416status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003417 AudioBufferProvider::Buffer* buffer)
3418{
3419 buffer->frameCount = mLastReadFrames;
3420 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3421 return NO_ERROR;
3422}
3423
Andy Hung8d31fd22023-06-26 19:20:57 -07003424void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003425 AudioBufferProvider::Buffer* buffer)
3426{
3427 buffer->frameCount = 0;
3428 buffer->raw = nullptr;
3429}
3430
Andy Hung9d84af52018-09-12 18:03:44 -07003431// ----------------------------------------------------------------------------
3432#undef LOG_TAG
3433#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003434
Andy Hung8d31fd22023-06-26 19:20:57 -07003435/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003436sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003437 const audio_attributes_t& attr,
3438 uint32_t sampleRate,
3439 audio_format_t format,
3440 audio_channel_mask_t channelMask,
3441 audio_session_t sessionId,
3442 bool isOut,
3443 const android::content::AttributionSourceState& attributionSource,
3444 pid_t creatorPid,
3445 audio_port_handle_t portId)
3446{
3447 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003448 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003449 attr,
3450 sampleRate,
3451 format,
3452 channelMask,
3453 sessionId,
3454 isOut,
3455 attributionSource,
3456 creatorPid,
3457 portId);
3458}
3459
Andy Hung87c693c2023-07-06 20:56:16 -07003460MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003461 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003462 uint32_t sampleRate,
3463 audio_format_t format,
3464 audio_channel_mask_t channelMask,
3465 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003466 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003467 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003468 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003469 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003470 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003471 channelMask, (size_t)0 /* frameCount */,
3472 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003473 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003474 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003475 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003476 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003477 TYPE_DEFAULT, portId,
3478 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003479 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003480 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003481{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003482 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003483 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003484}
3485
Andy Hung8d31fd22023-06-26 19:20:57 -07003486MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003487{
3488}
3489
Andy Hung8d31fd22023-06-26 19:20:57 -07003490status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003491{
3492 return NO_ERROR;
3493}
3494
Andy Hung8d31fd22023-06-26 19:20:57 -07003495status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003496 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003497{
3498 return NO_ERROR;
3499}
3500
Andy Hung8d31fd22023-06-26 19:20:57 -07003501void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003502{
3503}
3504
3505// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003506status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003507{
3508 buffer->frameCount = 0;
3509 buffer->raw = nullptr;
3510 return INVALID_OPERATION;
3511}
3512
3513// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003514size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003515 return 0;
3516}
3517
Andy Hung8d31fd22023-06-26 19:20:57 -07003518int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003519{
3520 return 0;
3521}
3522
Andy Hung8d31fd22023-06-26 19:20:57 -07003523void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003524{
3525}
3526
Andy Hung8d31fd22023-06-26 19:20:57 -07003527void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003528{
3529 if (mMuteState == muteState) {
3530 // mute state did not change, do nothing
3531 return;
3532 }
3533
3534 status_t result = UNKNOWN_ERROR;
3535 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3536 if (mMuteEventExtras == nullptr) {
3537 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3538 }
3539 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3540 static_cast<int>(muteState));
3541
3542 result = audioManager->portEvent(mPortId,
3543 PLAYER_UPDATE_MUTED,
3544 mMuteEventExtras);
3545 }
3546
3547 if (result == OK) {
3548 mMuteState = muteState;
3549 } else {
3550 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3551 __func__,
3552 id(),
3553 mPortId,
3554 result);
3555 }
3556}
3557
Andy Hung8d31fd22023-06-26 19:20:57 -07003558void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003559{
Eric Laurent973db022018-11-20 14:54:31 -08003560 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003561 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003562}
3563
Andy Hung8d31fd22023-06-26 19:20:57 -07003564void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003565{
Eric Laurent973db022018-11-20 14:54:31 -08003566 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003567 mPid,
3568 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003569 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003570 mFormat,
3571 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003572 mSampleRate,
3573 mAttr.flags);
3574 if (isOut()) {
3575 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3576 } else {
3577 result.appendFormat("%6x", mAttr.source);
3578 }
3579 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003580}
3581
Glenn Kasten63238ef2015-03-02 15:50:29 -08003582} // namespace android