blob: f18e69b7e720bf24c09b6a330ca62a44c5ff68d9 [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Eric Laurent81784c32012-11-19 14:55:58 -080018#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070020#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080021
Andy Hungce240472023-07-19 11:40:07 -070022#include "MmapTracks.h"
23#include "PlaybackTracks.h"
24#include "RecordTracks.h"
25
26#include "Client.h"
27#include "IAfEffect.h"
28#include "IAfThread.h"
29#include "ResamplerBufferProvider.h"
30
31#include <audio_utils/minifloat.h>
32#include <media/AudioValidator.h>
33#include <media/RecordBufferConverter.h>
34#include <media/nbaio/Pipe.h>
35#include <media/nbaio/PipeReader.h>
36#include <mediautils/ServiceUtilities.h>
37#include <mediautils/SharedMemoryAllocator.h>
38#include <private/media/AudioTrackShared.h>
Eric Laurent81784c32012-11-19 14:55:58 -080039#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070040#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080041
Andy Hungce240472023-07-19 11:40:07 -070042#include <linux/futex.h>
43#include <math.h>
44#include <sys/syscall.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080045
Eric Laurent81784c32012-11-19 14:55:58 -080046// ----------------------------------------------------------------------------
47
48// Note: the following macro is used for extremely verbose logging message. In
49// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
50// 0; but one side effect of this is to turn all LOGV's as well. Some messages
51// are so verbose that we want to suppress them even when we have ALOG_ASSERT
52// turned on. Do not uncomment the #def below unless you really know what you
53// are doing and want to see all of the extremely verbose messages.
54//#define VERY_VERY_VERBOSE_LOGGING
55#ifdef VERY_VERY_VERBOSE_LOGGING
56#define ALOGVV ALOGV
57#else
58#define ALOGVV(a...) do { } while(0)
59#endif
60
Kuowei Lid4adbdb2020-08-13 14:44:25 +080061// TODO: Remove when this is put into AidlConversionUtil.h
62#define VALUE_OR_RETURN_BINDER_STATUS(x) \
63 ({ \
64 auto _tmp = (x); \
65 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
66 std::move(_tmp.value()); \
67 })
68
Eric Laurent81784c32012-11-19 14:55:58 -080069namespace android {
70
Kuowei Lid4adbdb2020-08-13 14:44:25 +080071using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080072using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000073using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070074using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080075// ----------------------------------------------------------------------------
76// TrackBase
77// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070078#undef LOG_TAG
79#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080080
Glenn Kastenda6ef132013-01-10 12:31:01 -080081static volatile int32_t nextTrackId = 55;
82
Eric Laurent81784c32012-11-19 14:55:58 -080083// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung44f27182023-07-06 20:56:16 -070085 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080086 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070087 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080088 uint32_t sampleRate,
89 audio_format_t format,
90 audio_channel_mask_t channelMask,
91 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070092 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070093 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080094 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070095 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080096 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070097 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070098 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080099 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800100 audio_port_handle_t portId,
101 std::string metricsId)
Andy Hung02a6c4e2023-06-23 19:27:19 -0700102 :
Eric Laurent81784c32012-11-19 14:55:58 -0800103 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700104 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800105 mClient(client),
106 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700107 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800108 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700109 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800110 mSampleRate(sampleRate),
111 mFormat(format),
112 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700113 mChannelCount(isOut ?
114 audio_channel_count_from_out_mask(channelMask) :
115 audio_channel_count_from_in_mask(channelMask)),
Dean Wheatleyd883e302023-10-20 06:11:43 +1100116 mFrameSize(audio_bytes_per_frame(mChannelCount, format)),
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung3ff4b552023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung3ff4b552023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung2ac52f12023-08-28 18:36:53 -0700279 audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung3ff4b552023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung3ff4b552023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung3ff4b552023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung837229a2023-07-14 16:57:01 -0700318 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
Andy Hung837229a2023-07-14 16:57:01 -0700325 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
326 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung3ff4b552023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hungaaa18282023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hungaaa18282023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hungaaa18282023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hungaaa18282023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hung02a6c4e2023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hung225aef62022-12-06 16:33:20 -0800391 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800392}
393
Andy Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-06-23 19:27:19 -0700500Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-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 Hungaaa18282023-06-23 19:27:19 -0700513Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-06-23 19:27:19 -0700537Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-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 Hungaaa18282023-06-23 19:27:19 -0700550Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-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 Hung3ff4b552023-06-26 19:20:57 -0700564sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung44f27182023-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 Popa103be862023-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 Popa103be862023-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 Hung44f27182023-07-06 20:56:16 -0700593OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
594 const AttributionSourceState& attributionSource,
595 audio_usage_t usage, int id, uid_t uid)
596 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa103be862023-07-10 20:27:41 -0700597 mHasOpPlayAudio(true),
Vlad Popa103be862023-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 Hung3ff4b552023-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 Hung3ff4b552023-06-26 19:20:57 -0700612void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700613{
Vlad Popad2152122023-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 Hung3ff4b552023-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 Popa103be862023-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 Popad2152122023-08-02 18:36:04 -0700642 if (doBroadcast) {
643 auto thread = mThread.promote();
Andy Hung71742ab2023-07-07 13:47:37 -0700644 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popad2152122023-08-02 18:36:04 -0700645 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87e82412023-08-29 14:26:09 -0700646 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad2152122023-08-02 18:36:04 -0700647 thread->broadcast_l();
648 }
Vlad Popa103be862023-07-10 20:27:41 -0700649 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800650 }
651}
652
Andy Hung3ff4b552023-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 Hung3ff4b552023-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 Popad2152122023-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 Hung3ff4b552023-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 Hung3ff4b552023-06-26 19:20:57 -0700682/* static */
Andy Hung44f27182023-07-06 20:56:16 -0700683sp<IAfTrack> IAfTrack::create(
684 IAfPlaybackThread* thread,
Andy Hung3ff4b552023-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 Hung44f27182023-07-06 20:56:16 -0700707 return sp<Track>::make(thread,
Andy Hung3ff4b552023-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 Hung3ff4b552023-06-26 19:20:57 -0700731Track::Track(
Andy Hung44f27182023-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 Hung3ff4b552023-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 Popa103be862023-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 Hung44f27182023-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 Hung44f27182023-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 Hung3ff4b552023-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 Hung3ff4b552023-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 Hung3ff4b552023-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 Hung44f27182023-07-06 20:56:16 -0700891 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800892 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -0700893 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -0700894 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700895 wasActive = playbackThread->destroyTrack_l(this);
jiabin6e506fc2023-06-27 18:22:35 +0000896 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700897 }
898 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700899 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800900 }
901 }
902}
903
Andy Hung3ff4b552023-06-26 19:20:57 -0700904void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800905{
Eric Laurent973db022018-11-20 14:54:31 -0800906 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700907 " Format Chn mask SRate "
908 "ST Usg CT "
909 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000910 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700911 "%s\n",
912 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800913}
914
Andy Hung3ff4b552023-06-26 19:20:57 -0700915void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800916{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700917 char trackType;
918 switch (mType) {
919 case TYPE_DEFAULT:
920 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700921 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700922 trackType = 'S'; // static
923 } else {
924 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800925 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700926 break;
927 case TYPE_PATCH:
928 trackType = 'P';
929 break;
930 default:
931 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800932 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700933
934 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700935 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700936 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700937 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700938 }
939
Eric Laurent81784c32012-11-19 14:55:58 -0800940 char nowInUnderrun;
941 switch (mObservedUnderruns.mBitFields.mMostRecent) {
942 case UNDERRUN_FULL:
943 nowInUnderrun = ' ';
944 break;
945 case UNDERRUN_PARTIAL:
946 nowInUnderrun = '<';
947 break;
948 case UNDERRUN_EMPTY:
949 nowInUnderrun = '*';
950 break;
951 default:
952 nowInUnderrun = '?';
953 break;
954 }
Andy Hungda540db2017-04-20 14:06:17 -0700955
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700956 char fillingStatus;
Andy Hung3ff4b552023-06-26 19:20:57 -0700957 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700958 case FS_INVALID:
959 fillingStatus = 'I';
960 break;
961 case FS_FILLING:
962 fillingStatus = 'f';
963 break;
964 case FS_FILLED:
965 fillingStatus = 'F';
966 break;
967 case FS_ACTIVE:
968 fillingStatus = 'A';
969 break;
970 default:
971 fillingStatus = '?';
972 break;
973 }
974
975 // clip framesReadySafe to max representation in dump
976 const size_t framesReadySafe =
977 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
978
979 // obtain volumes
980 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
981 const std::pair<float /* volume */, bool /* active */> vsVolume =
982 mVolumeHandler->getLastVolume();
983
984 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
985 // as it may be reduced by the application.
986 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
987 // Check whether the buffer size has been modified by the app.
988 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
989 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
990 ? 'e' /* error */ : ' ' /* identical */;
991
Eric Laurent973db022018-11-20 14:54:31 -0800992 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700993 "%08X %08X %6u "
994 "%2u %3x %2x "
995 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000996 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800997 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700998 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700999 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001000 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001001 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001002 mCblk->mFlags,
1003
Eric Laurent81784c32012-11-19 14:55:58 -08001004 mFormat,
1005 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001006 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001007
1008 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001009 mAttr.usage,
1010 mAttr.content_type,
1011
1012 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001013 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1014 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001015 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1016 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001017
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001018 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001019 bufferSizeInFrames,
1020 modifiedBufferChar,
1021 framesReadySafe,
1022 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001023 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001024 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001025 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1026 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001027 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001028
1029 if (isServerLatencySupported()) {
1030 double latencyMs;
1031 bool fromTrack;
1032 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1033 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1034 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1035 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001036 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001037 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001038 }
1039 }
1040 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001041}
1042
Andy Hung3ff4b552023-06-26 19:20:57 -07001043uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001044 return mAudioTrackServerProxy->getSampleRate();
1045}
1046
Eric Laurent81784c32012-11-19 14:55:58 -08001047// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001048status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001049{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001050 ServerProxy::Buffer buf;
1051 size_t desiredFrames = buffer->frameCount;
1052 buf.mFrameCount = desiredFrames;
1053 status_t status = mServerProxy->obtainBuffer(&buf);
1054 buffer->frameCount = buf.mFrameCount;
1055 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001056 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001057 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001058 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001059 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001060 } else {
1061 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001062 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001063 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001064}
1065
Andy Hung3ff4b552023-06-26 19:20:57 -07001066void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001067{
1068 interceptBuffer(*buffer);
1069 TrackBase::releaseBuffer(buffer);
1070}
1071
1072// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001073void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001074 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001075 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001076 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001077 if (frameCount == 0) {
1078 return; // No audio to intercept.
1079 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1080 // does not allow 0 frame size request contrary to getNextBuffer
1081 }
Jiabin Huang98b8d452024-01-04 18:42:55 +00001082 TeePatches teePatches;
1083 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1084 // Cache a copy of tee patches in case it is updated while using.
1085 teePatches = mTeePatches;
1086 mTeePatchesRWLock.unlock();
1087 }
1088 for (auto& teePatch : teePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001089 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001090 const size_t framesWritten = patchRecord->writeFrames(
1091 sourceBuffer.i8, frameCount, mFrameSize);
1092 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001093 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001094 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001095 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001096 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001097 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1098 using namespace std::chrono_literals;
1099 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001100 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang98b8d452024-01-04 18:42:55 +00001101 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001102}
1103
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001104// ExtendedAudioBufferProvider interface
1105
Andy Hung27876c02014-09-09 18:07:55 -07001106// framesReady() may return an approximation of the number of frames if called
1107// from a different thread than the one calling Proxy->obtainBuffer() and
1108// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1109// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001110size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001111 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1112 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1113 // The remainder of the buffer is not drained.
1114 return 0;
1115 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001116 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001117}
1118
Andy Hung3ff4b552023-06-26 19:20:57 -07001119int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001120{
1121 return mAudioTrackServerProxy->framesReleased();
1122}
1123
Andy Hung3ff4b552023-06-26 19:20:57 -07001124void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001125{
1126 // This call comes from a FastTrack and should be kept lockless.
1127 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001128 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001129
Andy Hung818e7a32016-02-16 18:08:07 -08001130 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001131
1132 // Compute latency.
1133 // TODO: Consider whether the server latency may be passed in by FastMixer
1134 // as a constant for all active FastTracks.
1135 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1136 mServerLatencyFromTrack.store(true);
1137 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001138}
1139
Eric Laurent81784c32012-11-19 14:55:58 -08001140// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001141bool Track::isReady() const {
1142 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001143 return true;
1144 }
1145
Eric Laurent16498512014-03-17 17:22:08 -07001146 if (isStopping()) {
1147 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001148 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001149 }
Eric Laurent81784c32012-11-19 14:55:58 -08001150 return true;
1151 }
1152
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001153 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001154 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1155 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1156 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1157 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001158
1159 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1160 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1161 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001162 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001163 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001164 return true;
1165 }
1166 return false;
1167}
1168
Andy Hung3ff4b552023-06-26 19:20:57 -07001169status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001170 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001171{
1172 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001173 ALOGV("%s(%d): calling pid %d session %d",
1174 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001175
Andy Hung44f27182023-07-06 20:56:16 -07001176 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001177 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001178 if (isOffloaded()) {
Andy Hung2ac52f12023-08-28 18:36:53 -07001179 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hung94dfbb42023-09-06 19:41:47 -07001180 const bool nonOffloadableGlobalEffectEnabled =
1181 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hung87e82412023-08-29 14:26:09 -07001182 audio_utils::lock_guard _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001183 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung94dfbb42023-09-06 19:41:47 -07001184 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001185 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001186 invalidate();
1187 return PERMISSION_DENIED;
1188 }
1189 }
Andy Hung87e82412023-08-29 14:26:09 -07001190 audio_utils::lock_guard _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001191 track_state state = mState;
1192 // here the track could be either new, or restarted
1193 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001194
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001195 // initial state-stopping. next state-pausing.
1196 // What if resume is called ?
1197
Zhou Song1ed46a22020-08-17 15:36:56 +08001198 if (state == FLUSHED) {
1199 // avoid underrun glitches when starting after flush
1200 reset();
1201 }
1202
kuowei.li576f1362021-05-11 18:02:32 +08001203 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1204 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001205 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001206 if (mResumeToStopping) {
1207 // happened we need to resume to STOPPING_1
1208 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001209 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1210 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001211 } else {
1212 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001213 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1214 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001215 }
Eric Laurent81784c32012-11-19 14:55:58 -08001216 } else {
1217 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001218 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1219 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001220 }
1221
Andy Hung44f27182023-07-06 20:56:16 -07001222 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001223
1224 // states to reset position info for pcm tracks
1225 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001226 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1227 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001228
1229 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1230 // Start point of track -> sink frame map. If the HAL returns a
1231 // frame position smaller than the first written frame in
1232 // updateTrackFrameInfo, the timestamp can be interpolated
1233 // instead of using a larger value.
1234 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1235 playbackThread->framesWritten());
1236 }
Andy Hunge10393e2015-06-12 13:59:33 -07001237 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001238 if (isFastTrack()) {
1239 // refresh fast track underruns on start because that field is never cleared
1240 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1241 // after stop.
1242 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1243 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001244 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001245 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001246 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001247 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001248 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001249 mState = state;
1250 }
1251 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001252
Andy Hungb68f5eb2019-12-03 16:49:17 -08001253 // Audio timing metrics are computed a few mix cycles after starting.
1254 {
1255 mLogStartCountdown = LOG_START_COUNTDOWN;
1256 mLogStartTimeNs = systemTime();
1257 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001258 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1259 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001260 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001261 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001262
Andy Hung1d3556d2018-03-29 16:30:14 -07001263 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1264 // for streaming tracks, remove the buffer read stop limit.
1265 mAudioTrackServerProxy->start();
1266 }
1267
Eric Laurentbfb1b832013-01-07 09:53:42 -08001268 // track was already in the active list, not a problem
1269 if (status == ALREADY_EXISTS) {
1270 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001271 } else {
1272 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1273 // It is usually unsafe to access the server proxy from a binder thread.
1274 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1275 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1276 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001277 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001278 ServerProxy::Buffer buffer;
1279 buffer.mFrameCount = 1;
1280 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001281 }
jiabin6e506fc2023-06-27 18:22:35 +00001282 if (status == NO_ERROR) {
1283 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1284 }
Eric Laurent81784c32012-11-19 14:55:58 -08001285 } else {
1286 status = BAD_VALUE;
1287 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001288 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001289 // send format to AudioManager for playback activity monitoring
Andy Hung2cbc2722023-07-17 17:05:00 -07001290 const sp<IAudioManager> audioManager =
1291 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001292 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1293 std::unique_ptr<os::PersistableBundle> bundle =
1294 std::make_unique<os::PersistableBundle>();
1295 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1296 isSpatialized());
1297 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1298 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1299 status_t result = audioManager->portEvent(mPortId,
1300 PLAYER_UPDATE_FORMAT, bundle);
1301 if (result != OK) {
1302 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1303 __func__, mPortId, result);
1304 }
1305 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001306 }
Eric Laurent81784c32012-11-19 14:55:58 -08001307 return status;
1308}
1309
Andy Hung3ff4b552023-06-26 19:20:57 -07001310void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001311{
Andy Hungc0691382018-09-12 18:01:57 -07001312 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001313 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001314 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001315 audio_utils::lock_guard _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001316 track_state state = mState;
1317 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1318 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001319 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1320 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001321 reset();
1322 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001323 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1324 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1325 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001326 mState = STOPPED;
1327 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001328 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1329 // presentation is complete
1330 // For an offloaded track this starts a drain and state will
1331 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001332 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001333 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001334 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001335 }
Eric Laurent81784c32012-11-19 14:55:58 -08001336 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001337 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001338 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1339 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001340 }
jiabin6e506fc2023-06-27 18:22:35 +00001341 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001342 }
1343}
1344
Andy Hung3ff4b552023-06-26 19:20:57 -07001345void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001346{
Andy Hungc0691382018-09-12 18:01:57 -07001347 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001348 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001349 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001350 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001351 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001352 switch (mState) {
1353 case STOPPING_1:
1354 case STOPPING_2:
1355 if (!isOffloaded()) {
1356 /* nothing to do if track is not offloaded */
1357 break;
1358 }
1359
1360 // Offloaded track was draining, we need to carry on draining when resumed
1361 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001362 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001363 case ACTIVE:
1364 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001365 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001366 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1367 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001368 if (isOffloadedOrDirect()) {
1369 mPauseHwPending = true;
1370 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001371 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001372 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001373
Eric Laurentbfb1b832013-01-07 09:53:42 -08001374 default:
1375 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001376 }
jiabin6e506fc2023-06-27 18:22:35 +00001377 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1378 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001379 }
1380}
1381
Andy Hung3ff4b552023-06-26 19:20:57 -07001382void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001383{
Andy Hungc0691382018-09-12 18:01:57 -07001384 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001385 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001386 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001387 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001388 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001389
Phil Burk4bb650b2016-09-09 12:11:17 -07001390 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1391 // Otherwise the flush would not be done until the track is resumed.
1392 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001393 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001394 (void)mServerProxy->flushBufferIfNeeded();
1395 }
1396
Eric Laurentbfb1b832013-01-07 09:53:42 -08001397 if (isOffloaded()) {
1398 // If offloaded we allow flush during any state except terminated
1399 // and keep the track active to avoid problems if user is seeking
1400 // rapidly and underlying hardware has a significant delay handling
1401 // a pause
1402 if (isTerminated()) {
1403 return;
1404 }
1405
Andy Hung9d84af52018-09-12 18:03:44 -07001406 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001407 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001408
1409 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001410 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1411 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001412 mState = ACTIVE;
1413 }
1414
Haynes Mathew George7844f672014-01-15 12:32:55 -08001415 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001416 mResumeToStopping = false;
1417 } else {
1418 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1419 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1420 return;
1421 }
1422 // No point remaining in PAUSED state after a flush => go to
1423 // FLUSHED state
1424 mState = FLUSHED;
1425 // do not reset the track if it is still in the process of being stopped or paused.
1426 // this will be done by prepareTracks_l() when the track is stopped.
1427 // prepareTracks_l() will see mState == FLUSHED, then
1428 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001429 if (isDirect()) {
1430 mFlushHwPending = true;
1431 }
Andy Hung44f27182023-07-06 20:56:16 -07001432 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001433 reset();
1434 }
Eric Laurent81784c32012-11-19 14:55:58 -08001435 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001436 // Prevent flush being lost if the track is flushed and then resumed
1437 // before mixer thread can run. This is important when offloading
1438 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001439 playbackThread->broadcast_l();
jiabin6e506fc2023-06-27 18:22:35 +00001440 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1441 // new data
1442 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001443 }
1444}
1445
Haynes Mathew George7844f672014-01-15 12:32:55 -08001446// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001447void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001448{
Andy Hung71ba4b32022-10-06 12:09:49 -07001449 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001450 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001451 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001452
Phil Burk4bb650b2016-09-09 12:11:17 -07001453 // Clear the client ring buffer so that the app can prime the buffer while paused.
1454 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1455 mServerProxy->flushBufferIfNeeded();
1456
Haynes Mathew George7844f672014-01-15 12:32:55 -08001457 mFlushHwPending = false;
1458}
1459
Andy Hung3ff4b552023-06-26 19:20:57 -07001460void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001461{
1462 mPauseHwPending = false;
1463}
1464
Andy Hung3ff4b552023-06-26 19:20:57 -07001465void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001466{
1467 // Do not reset twice to avoid discarding data written just after a flush and before
1468 // the audioflinger thread detects the track is stopped.
1469 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001470 // Force underrun condition to avoid false underrun callback until first data is
1471 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001472 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001473 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001474 mResetDone = true;
1475 if (mState == FLUSHED) {
1476 mState = IDLE;
1477 }
1478 }
1479}
1480
Andy Hung3ff4b552023-06-26 19:20:57 -07001481status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001482{
Andy Hung44f27182023-07-06 20:56:16 -07001483 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001484 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001485 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001486 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001487 } else if (thread->type() == IAfThreadBase::DIRECT
1488 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001489 return thread->setParameters(keyValuePairs);
1490 } else {
1491 return PERMISSION_DENIED;
1492 }
1493}
1494
Andy Hung3ff4b552023-06-26 19:20:57 -07001495status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001496 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001497 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001498 if (thread == 0) {
1499 ALOGE("thread is dead");
1500 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001501 } else if (thread->type() == IAfThreadBase::DIRECT
1502 || thread->type() == IAfThreadBase::OFFLOAD) {
1503 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001504 return directOutputThread->selectPresentation(presentationId, programId);
1505 }
1506 return INVALID_OPERATION;
1507}
1508
Andy Hung3ff4b552023-06-26 19:20:57 -07001509VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001510 const sp<VolumeShaper::Configuration>& configuration,
1511 const sp<VolumeShaper::Operation>& operation)
1512{
Andy Hungee86cee2022-12-13 19:19:53 -08001513 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001514
1515 if (isOffloadedOrDirect()) {
1516 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001517 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001518 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001519 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001520 thread->broadcast_l();
1521 }
1522 }
1523 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001524}
1525
Andy Hung3ff4b552023-06-26 19:20:57 -07001526sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001527{
1528 // Note: We don't check if Thread exists.
1529
1530 // mVolumeHandler is thread safe.
1531 return mVolumeHandler->getVolumeShaperState(id);
1532}
1533
Andy Hung3ff4b552023-06-26 19:20:57 -07001534void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001535{
jiabin76d94692022-12-15 21:51:21 +00001536 mFinalVolumeLeft = volumeLeft;
1537 mFinalVolumeRight = volumeRight;
1538 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001539 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1540 mFinalVolume = volume;
1541 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001542 mLogForceVolumeUpdate = true;
1543 }
1544 if (mLogForceVolumeUpdate) {
1545 mLogForceVolumeUpdate = false;
1546 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001547 }
1548}
1549
Andy Hung3ff4b552023-06-26 19:20:57 -07001550void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001551{
Eric Laurent49e39282022-06-24 18:42:45 +02001552 // Do not forward metadata for PatchTrack with unspecified stream type
1553 if (mStreamType == AUDIO_STREAM_PATCH) {
1554 return;
1555 }
1556
Eric Laurent94579172020-11-20 18:41:04 +01001557 playback_track_metadata_v7_t metadata;
1558 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001559 .usage = mAttr.usage,
1560 .content_type = mAttr.content_type,
1561 .gain = mFinalVolume,
1562 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001563
1564 // When attributes are undefined, derive default values from stream type.
1565 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1566 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1567 switch (mStreamType) {
1568 case AUDIO_STREAM_VOICE_CALL:
1569 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1570 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1571 break;
1572 case AUDIO_STREAM_SYSTEM:
1573 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1574 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1575 break;
1576 case AUDIO_STREAM_RING:
1577 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1578 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1579 break;
1580 case AUDIO_STREAM_MUSIC:
1581 metadata.base.usage = AUDIO_USAGE_MEDIA;
1582 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1583 break;
1584 case AUDIO_STREAM_ALARM:
1585 metadata.base.usage = AUDIO_USAGE_ALARM;
1586 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1587 break;
1588 case AUDIO_STREAM_NOTIFICATION:
1589 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1590 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1591 break;
1592 case AUDIO_STREAM_DTMF:
1593 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1594 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1595 break;
1596 case AUDIO_STREAM_ACCESSIBILITY:
1597 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1598 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1599 break;
1600 case AUDIO_STREAM_ASSISTANT:
1601 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1602 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1603 break;
1604 case AUDIO_STREAM_REROUTING:
1605 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1606 // unknown content type
1607 break;
1608 case AUDIO_STREAM_CALL_ASSISTANT:
1609 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1610 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1611 break;
1612 default:
1613 break;
1614 }
1615 }
1616
Eric Laurent78b07302022-10-07 16:20:34 +02001617 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001618 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1619 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001620}
1621
jiabin6e506fc2023-06-27 18:22:35 +00001622void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001623 if (mTeePatchesToUpdate.has_value()) {
jiabin6e506fc2023-06-27 18:22:35 +00001624 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang98b8d452024-01-04 18:42:55 +00001625 {
1626 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1627 mTeePatches = std::move(mTeePatchesToUpdate.value());
1628 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001629 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1630 mState == TrackBase::STOPPING_1) {
jiabin6e506fc2023-06-27 18:22:35 +00001631 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001632 }
1633 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001634 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001635}
1636
jiabin6e506fc2023-06-27 18:22:35 +00001637void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001638 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1639 "%s, existing tee patches to update will be ignored", __func__);
1640 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1641}
1642
Vlad Popae8d99472022-06-30 16:02:48 +02001643// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001644void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001645 IAudioManager>& audioManager, mute_state_t muteState)
1646{
1647 if (mMuteState == muteState) {
1648 // mute state did not change, do nothing
1649 return;
1650 }
1651
1652 status_t result = UNKNOWN_ERROR;
1653 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1654 if (mMuteEventExtras == nullptr) {
1655 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1656 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001657 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001658
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001659 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001660 }
1661
1662 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001663 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
1664 int(muteState), int(mMuteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001665 mMuteState = muteState;
1666 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001667 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1668 mPortId, result);
Andy Hung818e7a32016-02-16 18:08:07 -08001669 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001670}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001671
Andy Hung3ff4b552023-06-26 19:20:57 -07001672status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001673{
1674 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001675 return INVALID_OPERATION; // normal tracks handled through SSQ
1676 }
Andy Hung44f27182023-07-06 20:56:16 -07001677 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001678 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001679 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001680 }
Phil Burk6140c792015-03-19 14:30:21 -07001681
Andy Hung87e82412023-08-29 14:26:09 -07001682 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001683 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001684 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001685}
1686
Andy Hung3ff4b552023-06-26 19:20:57 -07001687status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001688{
Andy Hung44f27182023-07-06 20:56:16 -07001689 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001690 if (thread == nullptr) {
1691 return DEAD_OBJECT;
1692 }
Eric Laurent81784c32012-11-19 14:55:58 -08001693
Andy Hung44f27182023-07-06 20:56:16 -07001694 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001695 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001696 sp<IAfPlaybackThread> srcThread;
Andy Hungfa2f4f32023-07-17 12:40:43 -07001697 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001698 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001699
Eric Laurent6c796322019-04-09 14:13:17 -07001700 if (EffectId != 0 && status == NO_ERROR) {
1701 status = dstThread->attachAuxEffect(this, EffectId);
1702 if (status == NO_ERROR) {
1703 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001704 }
Eric Laurent6c796322019-04-09 14:13:17 -07001705 }
1706
1707 if (status != NO_ERROR && srcThread != nullptr) {
1708 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001709 }
1710 return status;
1711}
1712
Andy Hung3ff4b552023-06-26 19:20:57 -07001713void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001714{
1715 mAuxEffectId = EffectId;
1716 mAuxBuffer = buffer;
1717}
1718
Andy Hung59de4262021-06-14 10:53:54 -07001719// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001720bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001721 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001722{
Andy Hung818e7a32016-02-16 18:08:07 -08001723 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1724 // This assists in proper timestamp computation as well as wakelock management.
1725
Eric Laurent81784c32012-11-19 14:55:58 -08001726 // a track is considered presented when the total number of frames written to audio HAL
1727 // corresponds to the number of frames written when presentationComplete() is called for the
1728 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001729 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1730 // to detect when all frames have been played. In this case framesWritten isn't
1731 // useful because it doesn't always reflect whether there is data in the h/w
1732 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001733 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1734 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001735 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001736 if (mPresentationCompleteFrames == 0) {
1737 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001738 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001739 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1740 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001741 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001742 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001743
Andy Hungc54b1ff2016-02-23 14:07:07 -08001744 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001745 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001746 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001747 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1748 __func__, mId, (complete ? "complete" : "waiting"),
1749 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001750 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001751 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001752 && mAudioTrackServerProxy->isDrained();
1753 }
1754
1755 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001756 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001757 return true;
1758 }
1759 return false;
1760}
1761
Andy Hung59de4262021-06-14 10:53:54 -07001762// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001763bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001764{
1765 // For Offloaded or Direct tracks.
1766
1767 // For a direct track, we incorporated time based testing for presentationComplete.
1768
1769 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1770 // to detect when all frames have been played. In this case latencyMs isn't
1771 // useful because it doesn't always reflect whether there is data in the h/w
1772 // buffers, particularly if a track has been paused and resumed during draining
1773
1774 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1775 if (mPresentationCompleteTimeNs == 0) {
1776 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1777 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1778 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1779 }
1780
1781 bool complete;
1782 if (isOffloaded()) {
1783 complete = true;
1784 } else { // Direct
1785 complete = systemTime() >= mPresentationCompleteTimeNs;
1786 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1787 }
1788 if (complete) {
1789 notifyPresentationComplete();
1790 return true;
1791 }
1792 return false;
1793}
1794
Andy Hung3ff4b552023-06-26 19:20:57 -07001795void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001796{
1797 // This only triggers once. TODO: should we enforce this?
1798 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1799 mAudioTrackServerProxy->setStreamEndDone();
1800}
1801
Andy Hung3ff4b552023-06-26 19:20:57 -07001802void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001803{
Andy Hung068e08e2023-05-15 19:02:55 -07001804 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1805 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001806 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001807 (*it)->trigger();
1808 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001809 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001810 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001811 }
1812 }
1813}
1814
1815// implement VolumeBufferProvider interface
1816
Andy Hung3ff4b552023-06-26 19:20:57 -07001817gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001818{
1819 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1820 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001821 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1822 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1823 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001824 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001825 if (vl > GAIN_FLOAT_UNITY) {
1826 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001827 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001828 if (vr > GAIN_FLOAT_UNITY) {
1829 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001830 }
1831 // now apply the cached master volume and stream type volume;
1832 // this is trusted but lacks any synchronization or barrier so may be stale
1833 float v = mCachedVolume;
1834 vl *= v;
1835 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001836 // re-combine into packed minifloat
1837 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001838 // FIXME look at mute, pause, and stop flags
1839 return vlr;
1840}
1841
Andy Hung3ff4b552023-06-26 19:20:57 -07001842status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001843 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001844{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001845 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001846 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1847 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001848 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1849 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001850 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001851 event->cancel();
1852 return INVALID_OPERATION;
1853 }
1854 (void) TrackBase::setSyncEvent(event);
1855 return NO_ERROR;
1856}
1857
Andy Hung3ff4b552023-06-26 19:20:57 -07001858void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001859{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001860 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001861 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001862}
1863
Andy Hung3ff4b552023-06-26 19:20:57 -07001864void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001865{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001866 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001867 signalClientFlag(CBLK_DISABLED);
1868}
1869
Andy Hung3ff4b552023-06-26 19:20:57 -07001870void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001871{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001872 // FIXME should use proxy, and needs work
1873 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001874 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001875 android_atomic_release_store(0x40000000, &cblk->mFutex);
1876 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001877 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001878}
1879
Andy Hung3ff4b552023-06-26 19:20:57 -07001880void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001881{
Andy Hung44f27182023-07-06 20:56:16 -07001882 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001883 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001884 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001885 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001886 t->broadcast_l();
1887 }
1888}
1889
Andy Hung3ff4b552023-06-26 19:20:57 -07001890status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001891{
1892 status_t status = INVALID_OPERATION;
1893 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001894 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001895 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001896 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001897 audio_utils::lock_guard _l(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001898 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001899 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1900 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1901 }
1902 }
1903 return status;
1904}
1905
Andy Hung3ff4b552023-06-26 19:20:57 -07001906status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001907{
1908 status_t status = INVALID_OPERATION;
1909 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001910 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001911 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001912 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001913 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001914 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001915 if (status == NO_ERROR) {
1916 mDualMonoMode = mode;
1917 }
1918 }
1919 }
1920 return status;
1921}
1922
Andy Hung3ff4b552023-06-26 19:20:57 -07001923status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001924{
1925 status_t status = INVALID_OPERATION;
1926 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001927 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001928 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001929 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001930 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001931 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1933 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1934 }
1935 }
1936 return status;
1937}
1938
Andy Hung3ff4b552023-06-26 19:20:57 -07001939status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001940{
1941 status_t status = INVALID_OPERATION;
1942 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001943 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001944 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001945 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001946 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001947 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001948 if (status == NO_ERROR) {
1949 mAudioDescriptionMixLevel = leveldB;
1950 }
1951 }
1952 }
1953 return status;
1954}
1955
Andy Hung3ff4b552023-06-26 19:20:57 -07001956status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001957 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001958{
1959 status_t status = INVALID_OPERATION;
1960 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001961 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001962 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001963 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001964 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001965 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001966 ALOGD_IF((status == NO_ERROR) &&
1967 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1968 "%s: playbackRate inconsistent", __func__);
1969 }
1970 }
1971 return status;
1972}
1973
Andy Hung3ff4b552023-06-26 19:20:57 -07001974status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001975 const audio_playback_rate_t& playbackRate)
1976{
1977 status_t status = INVALID_OPERATION;
1978 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001979 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001980 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001981 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001982 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001983 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001984 if (status == NO_ERROR) {
1985 mPlaybackRateParameters = playbackRate;
1986 }
1987 }
1988 }
1989 return status;
1990}
1991
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001992//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001993bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07001994 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001995 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001996 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001997 /* Resume is pending if track was stopping before pause was called */
1998 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07001999 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002000 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07002001 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002002
2003 return false;
2004}
2005
2006//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002007void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07002008 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002009 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07002010 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002011
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002012 // Other possibility of pending resume is stopping_1 state
2013 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002014 // drain being called.
2015 if (mState == STOPPING_1) {
2016 mResumeToStopping = false;
2017 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002018}
Andy Hunge10393e2015-06-12 13:59:33 -07002019
2020//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002021void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002022 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002023 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002024 // Make the kernel frametime available.
2025 const FrameTime ft{
2026 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2027 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2028 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2029 mKernelFrameTime.store(ft);
2030 if (!audio_is_linear_pcm(mFormat)) {
2031 return;
2032 }
2033
Andy Hung818e7a32016-02-16 18:08:07 -08002034 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002035 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002036
2037 // adjust server times and set drained state.
2038 //
2039 // Our timestamps are only updated when the track is on the Thread active list.
2040 // We need to ensure that tracks are not removed before full drain.
2041 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002042 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002043 bool checked = false;
2044 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2045 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2046 // Lookup the track frame corresponding to the sink frame position.
2047 if (local.mTimeNs[i] > 0) {
2048 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2049 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002050 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002051 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002052 checked = true;
2053 }
2054 }
Andy Hunge10393e2015-06-12 13:59:33 -07002055 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002056
Andy Hung93bb5732023-05-04 21:16:34 -07002057 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2058 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002059 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002060 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002061 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002062 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002063
2064 // Compute latency info.
2065 const bool useTrackTimestamp = !drained;
2066 const double latencyMs = useTrackTimestamp
2067 ? local.getOutputServerLatencyMs(sampleRate())
2068 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2069
2070 mServerLatencyFromTrack.store(useTrackTimestamp);
2071 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002072
Andy Hung62921122020-05-18 10:47:31 -07002073 if (mLogStartCountdown > 0
2074 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2075 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2076 {
2077 if (mLogStartCountdown > 1) {
2078 --mLogStartCountdown;
2079 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2080 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002081 // startup is the difference in times for the current timestamp and our start
2082 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002083 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002084 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002085 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2086 * 1e3 / mSampleRate;
2087 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2088 " localTime:%lld startTime:%lld"
2089 " localPosition:%lld startPosition:%lld",
2090 __func__, latencyMs, startUpMs,
2091 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002092 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002093 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002094 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002095 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002096 }
Andy Hung62921122020-05-18 10:47:31 -07002097 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002098 }
Andy Hunge10393e2015-06-12 13:59:33 -07002099}
2100
Andy Hung3ff4b552023-06-26 19:20:57 -07002101bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002102 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002103 if (thread != 0) {
2104 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87e82412023-08-29 14:26:09 -07002105 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002106 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002107 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002108 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002109 ALOGD("%s, haptic playback was %s for track %d",
2110 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002111 mTrack->setHapticPlaybackEnabled(!muted);
2112 return true;
jiabin57303cc2018-12-18 15:45:57 -08002113 }
2114 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002115 return false;
2116}
2117
Andy Hung3ff4b552023-06-26 19:20:57 -07002118binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002119 /*out*/ bool *ret) {
2120 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002121 return binder::Status::ok();
2122}
2123
Andy Hung3ff4b552023-06-26 19:20:57 -07002124binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002125 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002126 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002127 return binder::Status::ok();
2128}
2129
Eric Laurent81784c32012-11-19 14:55:58 -08002130// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002131#undef LOG_TAG
2132#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002133
Andy Hung3ff4b552023-06-26 19:20:57 -07002134/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002135sp<IAfOutputTrack> IAfOutputTrack::create(
2136 IAfPlaybackThread* playbackThread,
2137 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002138 uint32_t sampleRate,
2139 audio_format_t format,
2140 audio_channel_mask_t channelMask,
2141 size_t frameCount,
2142 const AttributionSourceState& attributionSource) {
2143 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002144 playbackThread,
2145 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002146 sampleRate,
2147 format,
2148 channelMask,
2149 frameCount,
2150 attributionSource);
2151}
2152
2153OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002154 IAfPlaybackThread* playbackThread,
2155 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002156 uint32_t sampleRate,
2157 audio_format_t format,
2158 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002159 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002160 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002161 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002162 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002163 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002164 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002165 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002166 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002167 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002168{
2169
2170 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002171 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002172 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002173 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002174 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002175 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002176 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002177 // since client and server are in the same process,
2178 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002179 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2180 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002181 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002182 mClientProxy->setSendLevel(0.0);
2183 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002184 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002185 ALOGW("%s(%d): Error creating output track on thread %d",
2186 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002187 }
2188}
2189
Andy Hung3ff4b552023-06-26 19:20:57 -07002190OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002191{
2192 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002193 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002194}
2195
Andy Hung3ff4b552023-06-26 19:20:57 -07002196status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002197 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002198{
2199 status_t status = Track::start(event, triggerSession);
2200 if (status != NO_ERROR) {
2201 return status;
2202 }
2203
2204 mActive = true;
2205 mRetryCount = 127;
2206 return status;
2207}
2208
Andy Hung3ff4b552023-06-26 19:20:57 -07002209void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002210{
2211 Track::stop();
2212 clearBufferQueue();
2213 mOutBuffer.frameCount = 0;
2214 mActive = false;
2215}
2216
Andy Hung3ff4b552023-06-26 19:20:57 -07002217ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002218{
Eric Laurent19952e12023-04-20 10:08:29 +02002219 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002220 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002221 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002222 // preload one silent buffer to trigger mixer on start()
2223 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2224 status_t status = mClientProxy->obtainBuffer(&buf);
2225 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2226 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2227 return 0;
2228 }
2229 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2230 mClientProxy->releaseBuffer(&buf);
2231
2232 (void) start();
2233
2234 // wait for HAL stream to start before sending actual audio. Doing this on each
2235 // OutputTrack makes that playback start on all output streams is synchronized.
2236 // If another OutputTrack has already started it can underrun but this is OK
2237 // as only silence has been played so far and the retry count is very high on
2238 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002239 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002240 if (!pt->waitForHalStart()) {
2241 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2242 stop();
2243 return 0;
2244 }
2245
2246 // enqueue the first buffer and exit so that other OutputTracks will also start before
2247 // write() is called again and this buffer actually consumed.
2248 Buffer firstBuffer;
2249 firstBuffer.frameCount = frames;
2250 firstBuffer.raw = data;
2251 queueBuffer(firstBuffer);
2252 return frames;
2253 } else {
2254 (void) start();
2255 }
2256 }
2257
Eric Laurent81784c32012-11-19 14:55:58 -08002258 Buffer *pInBuffer;
2259 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002260 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002261 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002262 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002263 while (waitTimeLeftMs) {
2264 // First write pending buffers, then new data
2265 if (mBufferQueue.size()) {
2266 pInBuffer = mBufferQueue.itemAt(0);
2267 } else {
2268 pInBuffer = &inBuffer;
2269 }
2270
2271 if (pInBuffer->frameCount == 0) {
2272 break;
2273 }
2274
2275 if (mOutBuffer.frameCount == 0) {
2276 mOutBuffer.frameCount = pInBuffer->frameCount;
2277 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002278 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002279 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002280 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2281 __func__, mId,
2282 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002283 break;
2284 }
2285 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2286 if (waitTimeLeftMs >= waitTimeMs) {
2287 waitTimeLeftMs -= waitTimeMs;
2288 } else {
2289 waitTimeLeftMs = 0;
2290 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002291 if (status == NOT_ENOUGH_DATA) {
2292 restartIfDisabled();
2293 continue;
2294 }
Eric Laurent81784c32012-11-19 14:55:58 -08002295 }
2296
2297 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2298 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002299 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002300 Proxy::Buffer buf;
2301 buf.mFrameCount = outFrames;
2302 buf.mRaw = NULL;
2303 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002304 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002305 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002306 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002307 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002308 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002309
2310 if (pInBuffer->frameCount == 0) {
2311 if (mBufferQueue.size()) {
2312 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002313 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002314 if (pInBuffer != &inBuffer) {
2315 delete pInBuffer;
2316 }
Andy Hung9d84af52018-09-12 18:03:44 -07002317 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2318 __func__, mId,
2319 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002320 } else {
2321 break;
2322 }
2323 }
2324 }
2325
2326 // If we could not write all frames, allocate a buffer and queue it for next time.
2327 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002328 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002329 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002330 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002331 }
2332 }
2333
Andy Hungc25b84a2015-01-14 19:04:10 -08002334 // Calling write() with a 0 length buffer means that no more data will be written:
2335 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2336 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2337 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002338 }
2339
Andy Hung1c86ebe2018-05-29 20:29:08 -07002340 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002341}
2342
Andy Hung3ff4b552023-06-26 19:20:57 -07002343void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002344
2345 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2346 Buffer *pInBuffer = new Buffer;
2347 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2348 pInBuffer->mBuffer = malloc(bufferSize);
2349 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2350 "%s: Unable to malloc size %zu", __func__, bufferSize);
2351 pInBuffer->frameCount = inBuffer.frameCount;
2352 pInBuffer->raw = pInBuffer->mBuffer;
2353 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2354 mBufferQueue.add(pInBuffer);
2355 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2356 (int)mThreadIoHandle, mBufferQueue.size());
2357 // audio data is consumed (stored locally); set frameCount to 0.
2358 inBuffer.frameCount = 0;
2359 } else {
2360 ALOGW("%s(%d): thread %d no more overflow buffers",
2361 __func__, mId, (int)mThreadIoHandle);
2362 // TODO: return error for this.
2363 }
2364}
2365
Andy Hung3ff4b552023-06-26 19:20:57 -07002366void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002367{
Andy Hung87e82412023-08-29 14:26:09 -07002368 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002369 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2370}
2371
Andy Hung3ff4b552023-06-26 19:20:57 -07002372void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002373 {
Andy Hung87e82412023-08-29 14:26:09 -07002374 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002375 mTrackMetadatas = metadatas;
2376 }
2377 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2378 setMetadataHasChanged();
2379}
2380
Andy Hung3ff4b552023-06-26 19:20:57 -07002381status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002382 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2383{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002384 ClientProxy::Buffer buf;
2385 buf.mFrameCount = buffer->frameCount;
2386 struct timespec timeout;
2387 timeout.tv_sec = waitTimeMs / 1000;
2388 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2389 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2390 buffer->frameCount = buf.mFrameCount;
2391 buffer->raw = buf.mRaw;
2392 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002393}
2394
Andy Hung3ff4b552023-06-26 19:20:57 -07002395void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002396{
2397 size_t size = mBufferQueue.size();
2398
2399 for (size_t i = 0; i < size; i++) {
2400 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002401 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002402 delete pBuffer;
2403 }
2404 mBufferQueue.clear();
2405}
2406
Andy Hung3ff4b552023-06-26 19:20:57 -07002407void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002408{
2409 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2410 if (mActive && (flags & CBLK_DISABLED)) {
2411 start();
2412 }
2413}
Eric Laurent81784c32012-11-19 14:55:58 -08002414
Andy Hung9d84af52018-09-12 18:03:44 -07002415// ----------------------------------------------------------------------------
2416#undef LOG_TAG
2417#define LOG_TAG "AF::PatchTrack"
2418
Andy Hung3ff4b552023-06-26 19:20:57 -07002419/* static */
2420sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002421 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002422 audio_stream_type_t streamType,
2423 uint32_t sampleRate,
2424 audio_channel_mask_t channelMask,
2425 audio_format_t format,
2426 size_t frameCount,
2427 void* buffer,
2428 size_t bufferSize,
2429 audio_output_flags_t flags,
2430 const Timeout& timeout,
2431 size_t frameCountToBeReady /** Default behaviour is to start
2432 * as soon as possible to have
2433 * the lowest possible latency
2434 * even if it might glitch. */)
2435{
2436 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002437 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002438 streamType,
2439 sampleRate,
2440 channelMask,
2441 format,
2442 frameCount,
2443 buffer,
2444 bufferSize,
2445 flags,
2446 timeout,
2447 frameCountToBeReady);
2448}
2449
Andy Hung44f27182023-07-06 20:56:16 -07002450PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002451 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002452 uint32_t sampleRate,
2453 audio_channel_mask_t channelMask,
2454 audio_format_t format,
2455 size_t frameCount,
2456 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002457 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002458 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002459 const Timeout& timeout,
2460 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002461 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002462 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002463 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002464 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002465 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002466 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002467 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2468 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07002469 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002470{
Andy Hung9d84af52018-09-12 18:03:44 -07002471 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2472 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002473 (int)mPeerTimeout.tv_sec,
2474 (int)(mPeerTimeout.tv_nsec / 1000000));
2475}
2476
Andy Hung3ff4b552023-06-26 19:20:57 -07002477PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002478{
Andy Hungabfab202019-03-07 19:45:54 -08002479 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002480}
2481
Andy Hung3ff4b552023-06-26 19:20:57 -07002482size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002483{
2484 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2485 return std::numeric_limits<size_t>::max();
2486 } else {
2487 return Track::framesReady();
2488 }
2489}
2490
Andy Hung3ff4b552023-06-26 19:20:57 -07002491status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002492 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002493{
2494 status_t status = Track::start(event, triggerSession);
2495 if (status != NO_ERROR) {
2496 return status;
2497 }
2498 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2499 return status;
2500}
2501
Eric Laurent83b88082014-06-20 18:31:16 -07002502// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002503status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002504 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002505{
Andy Hung9d84af52018-09-12 18:03:44 -07002506 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002507 Proxy::Buffer buf;
2508 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002509 if (ATRACE_ENABLED()) {
2510 std::string traceName("PTnReq");
2511 traceName += std::to_string(id());
2512 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2513 }
Eric Laurent83b88082014-06-20 18:31:16 -07002514 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002515 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002516 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002517 if (ATRACE_ENABLED()) {
2518 std::string traceName("PTnObt");
2519 traceName += std::to_string(id());
2520 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2521 }
Eric Laurent83b88082014-06-20 18:31:16 -07002522 if (buf.mFrameCount == 0) {
2523 return WOULD_BLOCK;
2524 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002525 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002526 return status;
2527}
2528
Andy Hung3ff4b552023-06-26 19:20:57 -07002529void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002530{
Andy Hung9d84af52018-09-12 18:03:44 -07002531 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002532 Proxy::Buffer buf;
2533 buf.mFrameCount = buffer->frameCount;
2534 buf.mRaw = buffer->raw;
2535 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002536 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002537}
2538
Andy Hung3ff4b552023-06-26 19:20:57 -07002539status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002540 const struct timespec *timeOut)
2541{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002542 status_t status = NO_ERROR;
2543 static const int32_t kMaxTries = 5;
2544 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002545 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002546 do {
2547 if (status == NOT_ENOUGH_DATA) {
2548 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002549 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002550 }
2551 status = mProxy->obtainBuffer(buffer, timeOut);
2552 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2553 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002554}
2555
Andy Hung3ff4b552023-06-26 19:20:57 -07002556void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002557{
2558 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002559 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002560
2561 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2562 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2563 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2564 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002565 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002566 && audio_is_linear_pcm(mFormat)
2567 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002568 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002569 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002570 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002571 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2572 / playbackThread->sampleRate();
2573 if (framesReady() < frameCount) {
2574 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002575 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002576 }
2577 }
2578 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002579}
2580
Andy Hung3ff4b552023-06-26 19:20:57 -07002581void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002582{
Eric Laurent83b88082014-06-20 18:31:16 -07002583 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002584 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002585 start();
2586 }
Eric Laurent83b88082014-06-20 18:31:16 -07002587}
2588
Eric Laurent81784c32012-11-19 14:55:58 -08002589// ----------------------------------------------------------------------------
2590// Record
2591// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002592
2593
Andy Hung9d84af52018-09-12 18:03:44 -07002594#undef LOG_TAG
2595#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002596
Andy Hungaaa18282023-06-23 19:27:19 -07002597class RecordHandle : public android::media::BnAudioRecord {
2598public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002599 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002600 ~RecordHandle() override;
2601 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2602 int /*audio_session_t*/ triggerSession) final;
2603 binder::Status stop() final;
2604 binder::Status getActiveMicrophones(
2605 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2606 binder::Status setPreferredMicrophoneDirection(
2607 int /*audio_microphone_direction_t*/ direction) final;
2608 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2609 binder::Status shareAudioHistory(
2610 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2611
2612private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002613 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002614
2615 // for use from destructor
2616 void stop_nonvirtual();
2617};
2618
2619/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002620sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2621 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002622 return sp<RecordHandle>::make(recordTrack);
2623}
2624
2625RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002626 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002627 : BnAudioRecord(),
2628 mRecordTrack(recordTrack)
2629{
Andy Hung225aef62022-12-06 16:33:20 -08002630 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002631}
2632
Andy Hungaaa18282023-06-23 19:27:19 -07002633RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002634 stop_nonvirtual();
2635 mRecordTrack->destroy();
2636}
2637
Andy Hungaaa18282023-06-23 19:27:19 -07002638binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002639 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002640 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002641 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002642 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002643}
2644
Andy Hungaaa18282023-06-23 19:27:19 -07002645binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002646 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002647 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002648}
2649
Andy Hungaaa18282023-06-23 19:27:19 -07002650void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002651 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002652 mRecordTrack->stop();
2653}
2654
Andy Hungaaa18282023-06-23 19:27:19 -07002655binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002656 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002657 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002658 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002659}
2660
Andy Hungaaa18282023-06-23 19:27:19 -07002661binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002662 int /*audio_microphone_direction_t*/ direction) {
2663 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002664 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002665 static_cast<audio_microphone_direction_t>(direction)));
2666}
2667
Andy Hungaaa18282023-06-23 19:27:19 -07002668binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002669 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002670 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002671}
2672
Andy Hungaaa18282023-06-23 19:27:19 -07002673binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002674 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2675 return binderStatusFromStatusT(
2676 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2677}
2678
Eric Laurent81784c32012-11-19 14:55:58 -08002679// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002680#undef LOG_TAG
2681#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002682
Andy Hung3ff4b552023-06-26 19:20:57 -07002683
Andy Hung56126702023-07-14 11:00:08 -07002684/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002685sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002686 const sp<Client>& client,
2687 const audio_attributes_t& attr,
2688 uint32_t sampleRate,
2689 audio_format_t format,
2690 audio_channel_mask_t channelMask,
2691 size_t frameCount,
2692 void* buffer,
2693 size_t bufferSize,
2694 audio_session_t sessionId,
2695 pid_t creatorPid,
2696 const AttributionSourceState& attributionSource,
2697 audio_input_flags_t flags,
2698 track_type type,
2699 audio_port_handle_t portId,
2700 int32_t startFrames)
2701{
2702 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002703 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002704 client,
2705 attr,
2706 sampleRate,
2707 format,
2708 channelMask,
2709 frameCount,
2710 buffer,
2711 bufferSize,
2712 sessionId,
2713 creatorPid,
2714 attributionSource,
2715 flags,
2716 type,
2717 portId,
2718 startFrames);
2719}
2720
Glenn Kasten05997e22014-03-13 15:08:33 -07002721// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002722RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002723 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002724 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002725 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002726 uint32_t sampleRate,
2727 audio_format_t format,
2728 audio_channel_mask_t channelMask,
2729 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002730 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002731 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002732 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002733 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002734 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002735 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002736 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002737 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002738 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002739 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002740 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002741 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002742 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002743 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002744 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002745 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002746 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002747 type, portId,
2748 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002749 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002750 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002751 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002752 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002753 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002754 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002755{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002756 if (mCblk == NULL) {
2757 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002758 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002759
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002760 if (!isDirect()) {
2761 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002762 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002763 channelMask, format, sampleRate);
2764 // Check if the RecordBufferConverter construction was successful.
2765 // If not, don't continue with construction.
2766 //
2767 // NOTE: It would be extremely rare that the record track cannot be created
2768 // for the current device, but a pending or future device change would make
2769 // the record track configuration valid.
2770 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002771 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002772 return;
2773 }
Andy Hung97a893e2015-03-29 01:03:07 -07002774 }
2775
Andy Hung6ae58432016-02-16 18:32:24 -08002776 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002777 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002778
Andy Hung97a893e2015-03-29 01:03:07 -07002779 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002780
Eric Laurent05067782016-06-01 18:27:28 -07002781 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002782 ALOG_ASSERT(thread->fastTrackAvailable());
2783 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002784 } else {
2785 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002786 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002787 }
Andy Hung8946a282018-04-19 20:04:56 -07002788#ifdef TEE_SINK
2789 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2790 + "_" + std::to_string(mId)
2791 + "_R");
2792#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002793
2794 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002795 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002796}
2797
Andy Hung3ff4b552023-06-26 19:20:57 -07002798RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002799{
Andy Hung9d84af52018-09-12 18:03:44 -07002800 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002801 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002802 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002803}
2804
Andy Hung3ff4b552023-06-26 19:20:57 -07002805status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002806{
2807 status_t status = TrackBase::initCheck();
2808 if (status == NO_ERROR && mServerProxy == 0) {
2809 status = BAD_VALUE;
2810 }
2811 return status;
2812}
2813
Eric Laurent81784c32012-11-19 14:55:58 -08002814// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002815status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002816{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002817 ServerProxy::Buffer buf;
2818 buf.mFrameCount = buffer->frameCount;
2819 status_t status = mServerProxy->obtainBuffer(&buf);
2820 buffer->frameCount = buf.mFrameCount;
2821 buffer->raw = buf.mRaw;
2822 if (buf.mFrameCount == 0) {
2823 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002824 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002825 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002826 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002827}
2828
Andy Hung3ff4b552023-06-26 19:20:57 -07002829status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002830 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002831{
Andy Hung44f27182023-07-06 20:56:16 -07002832 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002833 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002834 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002835 return recordThread->start(this, event, triggerSession);
2836 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002837 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2838 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002839 }
2840}
2841
Andy Hung3ff4b552023-06-26 19:20:57 -07002842void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002843{
Andy Hung44f27182023-07-06 20:56:16 -07002844 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002845 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002846 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002847 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002848 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002849 }
2850 }
2851}
2852
Andy Hung3ff4b552023-06-26 19:20:57 -07002853void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002854{
Andy Hung3ff4b552023-06-26 19:20:57 -07002855 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002856 sp<RecordTrack> keep(this);
2857 {
Andy Hungce685402018-10-05 17:23:27 -07002858 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002859 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002860 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07002861 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002862 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002863 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002864 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002865 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002866 }
Andy Hungce685402018-10-05 17:23:27 -07002867 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2868 }
2869 // APM portid/client management done outside of lock.
2870 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2871 if (isExternalTrack()) {
2872 switch (priorState) {
2873 case ACTIVE: // invalidated while still active
2874 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2875 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2876 AudioSystem::stopInput(mPortId);
2877 break;
2878
2879 case STARTING_1: // invalidated/start-aborted and startInput not successful
2880 case PAUSED: // OK, not active
2881 case IDLE: // OK, not active
2882 break;
2883
2884 case STOPPED: // unexpected (destroyed)
2885 default:
2886 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2887 }
2888 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002889 }
2890 }
2891}
2892
Andy Hung3ff4b552023-06-26 19:20:57 -07002893void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002894{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002895 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002896 // FIXME should use proxy, and needs work
2897 audio_track_cblk_t* cblk = mCblk;
2898 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2899 android_atomic_release_store(0x40000000, &cblk->mFutex);
2900 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002901 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002902}
2903
Eric Laurent81784c32012-11-19 14:55:58 -08002904
Andy Hung3ff4b552023-06-26 19:20:57 -07002905void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002906{
Eric Laurent973db022018-11-20 14:54:31 -08002907 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002908 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002909 " Server FrmCnt FrmRdy Sil%s\n",
2910 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002911}
2912
Andy Hung3ff4b552023-06-26 19:20:57 -07002913void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002914{
Eric Laurent973db022018-11-20 14:54:31 -08002915 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002916 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002917 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002918 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002919 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002920 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002921 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002922 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002923 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002924 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002925 mCblk->mFlags,
2926
Eric Laurent81784c32012-11-19 14:55:58 -08002927 mFormat,
2928 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002929 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002930 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002931
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002932 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002933 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002934 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002935 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002936 );
Andy Hung000adb52018-06-01 15:43:26 -07002937 if (isServerLatencySupported()) {
2938 double latencyMs;
2939 bool fromTrack;
2940 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2941 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2942 // or 'k' if estimated from kernel (usually for debugging).
2943 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2944 } else {
2945 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2946 }
2947 }
2948 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002949}
2950
Andy Hung93bb5732023-05-04 21:16:34 -07002951// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002952void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002953 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002954{
Andy Hung93bb5732023-05-04 21:16:34 -07002955 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002956 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002957 if (threadBase != 0) {
2958 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2959 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002960 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002961 }
Andy Hung93bb5732023-05-04 21:16:34 -07002962
2963 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002964}
2965
Andy Hung3ff4b552023-06-26 19:20:57 -07002966void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002967{
Andy Hung93bb5732023-05-04 21:16:34 -07002968 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002969}
2970
Andy Hung3ff4b552023-06-26 19:20:57 -07002971void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002972 int64_t trackFramesReleased, int64_t sourceFramesRead,
2973 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2974{
Andy Hung30282562018-08-08 18:27:03 -07002975 // Make the kernel frametime available.
2976 const FrameTime ft{
2977 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2978 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2979 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2980 mKernelFrameTime.store(ft);
2981 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002982 // Stream is direct, return provided timestamp with no conversion
2983 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002984 return;
2985 }
2986
Andy Hung3f0c9022016-01-15 17:49:46 -08002987 ExtendedTimestamp local = timestamp;
2988
2989 // Convert HAL frames to server-side track frames at track sample rate.
2990 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2991 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2992 if (local.mTimeNs[i] != 0) {
2993 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2994 const int64_t relativeTrackFrames = relativeServerFrames
2995 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2996 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2997 }
2998 }
Andy Hung6ae58432016-02-16 18:32:24 -08002999 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003000
3001 // Compute latency info.
3002 const bool useTrackTimestamp = true; // use track unless debugging.
3003 const double latencyMs = - (useTrackTimestamp
3004 ? local.getOutputServerLatencyMs(sampleRate())
3005 : timestamp.getOutputServerLatencyMs(halSampleRate));
3006
3007 mServerLatencyFromTrack.store(useTrackTimestamp);
3008 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003009}
Eric Laurent83b88082014-06-20 18:31:16 -07003010
Andy Hung3ff4b552023-06-26 19:20:57 -07003011status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003012 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003013{
Andy Hung44f27182023-07-06 20:56:16 -07003014 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003015 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003016 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003017 return recordThread->getActiveMicrophones(activeMicrophones);
3018 } else {
3019 return BAD_VALUE;
3020 }
3021}
3022
Andy Hung3ff4b552023-06-26 19:20:57 -07003023status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003024 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003025 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003026 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003027 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003028 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003029 } else {
3030 return BAD_VALUE;
3031 }
3032}
3033
Andy Hung3ff4b552023-06-26 19:20:57 -07003034status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003035 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003036 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003037 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003038 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003039 } else {
3040 return BAD_VALUE;
3041 }
3042}
3043
Andy Hung3ff4b552023-06-26 19:20:57 -07003044status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003045 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3046
3047 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3048 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3049 if (callingUid != mUid || callingPid != mCreatorPid) {
3050 return PERMISSION_DENIED;
3051 }
3052
Svet Ganov33761132021-05-13 22:51:08 +00003053 AttributionSourceState attributionSource{};
3054 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3055 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3056 attributionSource.token = sp<BBinder>::make();
3057 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003058 return PERMISSION_DENIED;
3059 }
3060
Andy Hung44f27182023-07-06 20:56:16 -07003061 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003062 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003063 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003064 status_t status = recordThread->shareAudioHistory(
3065 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3066 if (status == NO_ERROR) {
3067 mSharedAudioPackageName = sharedAudioPackageName;
3068 }
3069 return status;
3070 } else {
3071 return BAD_VALUE;
3072 }
3073}
3074
Andy Hung3ff4b552023-06-26 19:20:57 -07003075void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003076{
3077
3078 // Do not forward PatchRecord metadata with unspecified audio source
3079 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3080 return;
3081 }
3082
3083 // No track is invalid as this is called after prepareTrack_l in the same critical section
3084 record_track_metadata_v7_t metadata;
3085 metadata.base = {
3086 .source = mAttr.source,
3087 .gain = 1, // capture tracks do not have volumes
3088 };
3089 metadata.channel_mask = mChannelMask;
3090 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3091
3092 *backInserter++ = metadata;
3093}
Eric Laurentec376dc2021-04-08 20:41:22 +02003094
Andy Hung9d84af52018-09-12 18:03:44 -07003095// ----------------------------------------------------------------------------
3096#undef LOG_TAG
3097#define LOG_TAG "AF::PatchRecord"
3098
Andy Hung3ff4b552023-06-26 19:20:57 -07003099/* static */
3100sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003101 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003102 uint32_t sampleRate,
3103 audio_channel_mask_t channelMask,
3104 audio_format_t format,
3105 size_t frameCount,
3106 void *buffer,
3107 size_t bufferSize,
3108 audio_input_flags_t flags,
3109 const Timeout& timeout,
3110 audio_source_t source)
3111{
3112 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003113 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003114 sampleRate,
3115 channelMask,
3116 format,
3117 frameCount,
3118 buffer,
3119 bufferSize,
3120 flags,
3121 timeout,
3122 source);
3123}
3124
Andy Hung44f27182023-07-06 20:56:16 -07003125PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003126 uint32_t sampleRate,
3127 audio_channel_mask_t channelMask,
3128 audio_format_t format,
3129 size_t frameCount,
3130 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003131 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003132 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003133 const Timeout& timeout,
3134 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003135 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003136 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003137 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003138 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003139 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003140 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3141 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07003142 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003143{
Andy Hung9d84af52018-09-12 18:03:44 -07003144 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3145 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003146 (int)mPeerTimeout.tv_sec,
3147 (int)(mPeerTimeout.tv_nsec / 1000000));
3148}
3149
Andy Hung3ff4b552023-06-26 19:20:57 -07003150PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003151{
Andy Hungabfab202019-03-07 19:45:54 -08003152 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003153}
3154
Mikhail Naganov8296c252019-09-25 14:59:54 -07003155static size_t writeFramesHelper(
3156 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3157{
3158 AudioBufferProvider::Buffer patchBuffer;
3159 patchBuffer.frameCount = frameCount;
3160 auto status = dest->getNextBuffer(&patchBuffer);
3161 if (status != NO_ERROR) {
3162 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3163 __func__, status, strerror(-status));
3164 return 0;
3165 }
3166 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3167 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3168 size_t framesWritten = patchBuffer.frameCount;
3169 dest->releaseBuffer(&patchBuffer);
3170 return framesWritten;
3171}
3172
3173// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003174size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003175 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3176{
3177 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3178 // On buffer wrap, the buffer frame count will be less than requested,
3179 // when this happens a second buffer needs to be used to write the leftover audio
3180 const size_t framesLeft = frameCount - framesWritten;
3181 if (framesWritten != 0 && framesLeft != 0) {
3182 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3183 framesLeft, frameSize);
3184 }
3185 return framesWritten;
3186}
3187
Eric Laurent83b88082014-06-20 18:31:16 -07003188// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003189status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003190 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003191{
Andy Hung9d84af52018-09-12 18:03:44 -07003192 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003193 Proxy::Buffer buf;
3194 buf.mFrameCount = buffer->frameCount;
3195 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3196 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003197 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003198 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003199 if (ATRACE_ENABLED()) {
3200 std::string traceName("PRnObt");
3201 traceName += std::to_string(id());
3202 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3203 }
Eric Laurent83b88082014-06-20 18:31:16 -07003204 if (buf.mFrameCount == 0) {
3205 return WOULD_BLOCK;
3206 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003207 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003208 return status;
3209}
3210
Andy Hung3ff4b552023-06-26 19:20:57 -07003211void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003212{
Andy Hung9d84af52018-09-12 18:03:44 -07003213 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003214 Proxy::Buffer buf;
3215 buf.mFrameCount = buffer->frameCount;
3216 buf.mRaw = buffer->raw;
3217 mPeerProxy->releaseBuffer(&buf);
3218 TrackBase::releaseBuffer(buffer);
3219}
3220
Andy Hung3ff4b552023-06-26 19:20:57 -07003221status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003222 const struct timespec *timeOut)
3223{
3224 return mProxy->obtainBuffer(buffer, timeOut);
3225}
3226
Andy Hung3ff4b552023-06-26 19:20:57 -07003227void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003228{
3229 mProxy->releaseBuffer(buffer);
3230}
3231
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003232#undef LOG_TAG
3233#define LOG_TAG "AF::PthrPatchRecord"
3234
3235static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3236{
3237 void *ptr = nullptr;
3238 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003239 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003240}
3241
Andy Hung3ff4b552023-06-26 19:20:57 -07003242/* static */
3243sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003244 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003245 uint32_t sampleRate,
3246 audio_channel_mask_t channelMask,
3247 audio_format_t format,
3248 size_t frameCount,
3249 audio_input_flags_t flags,
3250 audio_source_t source)
3251{
3252 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003253 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003254 sampleRate,
3255 channelMask,
3256 format,
3257 frameCount,
3258 flags,
3259 source);
3260}
3261
3262PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003263 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003264 uint32_t sampleRate,
3265 audio_channel_mask_t channelMask,
3266 audio_format_t format,
3267 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003268 audio_input_flags_t flags,
3269 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003270 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003271 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003272 mPatchRecordAudioBufferProvider(*this),
3273 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3274 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3275{
3276 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3277}
3278
Andy Hung3ff4b552023-06-26 19:20:57 -07003279sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003280 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003281{
3282 *thread = mThread.promote();
3283 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003284 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07003285 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07003286 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003287}
3288
3289// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003290status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003291 Proxy::Buffer* buffer, const struct timespec* timeOut)
3292{
3293 if (mUnconsumedFrames) {
3294 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3295 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3296 return PatchRecord::obtainBuffer(buffer, timeOut);
3297 }
3298
3299 // Otherwise, execute a read from HAL and write into the buffer.
3300 nsecs_t startTimeNs = 0;
3301 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3302 // Will need to correct timeOut by elapsed time.
3303 startTimeNs = systemTime();
3304 }
3305 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3306 buffer->mFrameCount = 0;
3307 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003308 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003309 sp<StreamInHalInterface> stream = obtainStream(&thread);
3310 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3311
3312 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003313 size_t bytesRead = 0;
3314 {
3315 ATRACE_NAME("read");
3316 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3317 if (result != NO_ERROR) goto stream_error;
3318 if (bytesRead == 0) return NO_ERROR;
3319 }
3320
3321 {
Andy Hung094dc762023-08-28 19:12:14 -07003322 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003323 mReadBytes += bytesRead;
3324 mReadError = NO_ERROR;
3325 }
3326 mReadCV.notify_one();
3327 // writeFrames handles wraparound and should write all the provided frames.
3328 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3329 buffer->mFrameCount = writeFrames(
3330 &mPatchRecordAudioBufferProvider,
3331 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3332 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3333 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3334 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003335 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003336 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003337 // Correct the timeout by elapsed time.
3338 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003339 if (newTimeOutNs < 0) newTimeOutNs = 0;
3340 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3341 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003342 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003343 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003344 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003345
3346stream_error:
3347 stream->standby();
3348 {
Andy Hung094dc762023-08-28 19:12:14 -07003349 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003350 mReadError = result;
3351 }
3352 mReadCV.notify_one();
3353 return result;
3354}
3355
Andy Hung3ff4b552023-06-26 19:20:57 -07003356void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003357{
3358 if (buffer->mFrameCount <= mUnconsumedFrames) {
3359 mUnconsumedFrames -= buffer->mFrameCount;
3360 } else {
3361 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3362 buffer->mFrameCount, mUnconsumedFrames);
3363 mUnconsumedFrames = 0;
3364 }
3365 PatchRecord::releaseBuffer(buffer);
3366}
3367
3368// AudioBufferProvider and Source methods are called on RecordThread
3369// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3370// and 'releaseBuffer' are stubbed out and ignore their input.
3371// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3372// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003373status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003374 void* buffer, size_t bytes, size_t* read)
3375{
3376 bytes = std::min(bytes, mFrameCount * mFrameSize);
3377 {
Andy Hung094dc762023-08-28 19:12:14 -07003378 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003379 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3380 if (mReadError != NO_ERROR) {
3381 mLastReadFrames = 0;
3382 return mReadError;
3383 }
3384 *read = std::min(bytes, mReadBytes);
3385 mReadBytes -= *read;
3386 }
3387 mLastReadFrames = *read / mFrameSize;
3388 memset(buffer, 0, *read);
3389 return 0;
3390}
3391
Andy Hung3ff4b552023-06-26 19:20:57 -07003392status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003393 int64_t* frames, int64_t* time)
3394{
Andy Hung44f27182023-07-06 20:56:16 -07003395 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003396 sp<StreamInHalInterface> stream = obtainStream(&thread);
3397 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3398}
3399
Andy Hung3ff4b552023-06-26 19:20:57 -07003400status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003401{
3402 // RecordThread issues 'standby' command in two major cases:
3403 // 1. Error on read--this case is handled in 'obtainBuffer'.
3404 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3405 // output, this can only happen when the software patch
3406 // is being torn down. In this case, the RecordThread
3407 // will terminate and close the HAL stream.
3408 return 0;
3409}
3410
3411// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003412status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003413 AudioBufferProvider::Buffer* buffer)
3414{
3415 buffer->frameCount = mLastReadFrames;
3416 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3417 return NO_ERROR;
3418}
3419
Andy Hung3ff4b552023-06-26 19:20:57 -07003420void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003421 AudioBufferProvider::Buffer* buffer)
3422{
3423 buffer->frameCount = 0;
3424 buffer->raw = nullptr;
3425}
3426
Andy Hung9d84af52018-09-12 18:03:44 -07003427// ----------------------------------------------------------------------------
3428#undef LOG_TAG
3429#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003430
Andy Hung3ff4b552023-06-26 19:20:57 -07003431/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003432sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003433 const audio_attributes_t& attr,
3434 uint32_t sampleRate,
3435 audio_format_t format,
3436 audio_channel_mask_t channelMask,
3437 audio_session_t sessionId,
3438 bool isOut,
3439 const android::content::AttributionSourceState& attributionSource,
3440 pid_t creatorPid,
3441 audio_port_handle_t portId)
3442{
3443 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003444 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003445 attr,
3446 sampleRate,
3447 format,
3448 channelMask,
3449 sessionId,
3450 isOut,
3451 attributionSource,
3452 creatorPid,
3453 portId);
3454}
3455
Andy Hung44f27182023-07-06 20:56:16 -07003456MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003457 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003458 uint32_t sampleRate,
3459 audio_format_t format,
3460 audio_channel_mask_t channelMask,
3461 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003462 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003463 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003464 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003465 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003466 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003467 channelMask, (size_t)0 /* frameCount */,
3468 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003469 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003470 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003471 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003472 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003473 TYPE_DEFAULT, portId,
3474 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003475 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003476 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003477{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003478 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003479 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003480}
3481
Andy Hung3ff4b552023-06-26 19:20:57 -07003482MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003483{
3484}
3485
Andy Hung3ff4b552023-06-26 19:20:57 -07003486status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003487{
3488 return NO_ERROR;
3489}
3490
Andy Hung3ff4b552023-06-26 19:20:57 -07003491status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003492 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003493{
3494 return NO_ERROR;
3495}
3496
Andy Hung3ff4b552023-06-26 19:20:57 -07003497void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003498{
3499}
3500
3501// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003502status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003503{
3504 buffer->frameCount = 0;
3505 buffer->raw = nullptr;
3506 return INVALID_OPERATION;
3507}
3508
3509// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003510size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003511 return 0;
3512}
3513
Andy Hung3ff4b552023-06-26 19:20:57 -07003514int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003515{
3516 return 0;
3517}
3518
Andy Hung3ff4b552023-06-26 19:20:57 -07003519void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003520{
3521}
3522
Andy Hung3ff4b552023-06-26 19:20:57 -07003523void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003524{
3525 if (mMuteState == muteState) {
3526 // mute state did not change, do nothing
3527 return;
3528 }
3529
3530 status_t result = UNKNOWN_ERROR;
3531 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3532 if (mMuteEventExtras == nullptr) {
3533 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3534 }
3535 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3536 static_cast<int>(muteState));
3537
3538 result = audioManager->portEvent(mPortId,
3539 PLAYER_UPDATE_MUTED,
3540 mMuteEventExtras);
3541 }
3542
3543 if (result == OK) {
3544 mMuteState = muteState;
3545 } else {
3546 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3547 __func__,
3548 id(),
3549 mPortId,
3550 result);
3551 }
3552}
3553
Andy Hung3ff4b552023-06-26 19:20:57 -07003554void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003555{
Eric Laurent973db022018-11-20 14:54:31 -08003556 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003557 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003558}
3559
Andy Hung3ff4b552023-06-26 19:20:57 -07003560void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003561{
Eric Laurent973db022018-11-20 14:54:31 -08003562 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003563 mPid,
3564 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003565 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003566 mFormat,
3567 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003568 mSampleRate,
3569 mAttr.flags);
3570 if (isOut()) {
3571 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3572 } else {
3573 result.appendFormat("%6x", mAttr.source);
3574 }
3575 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003576}
3577
Glenn Kasten63238ef2015-03-02 15:50:29 -08003578} // namespace android