blob: 9ca23fbd614228d7d6e64047f284e31c8a204a75 [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
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070021#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080022
Glenn Kasten153b9fe2013-07-15 11:23:36 -070023#include "Configuration.h"
Glenn Kastenad8510a2015-02-17 16:24:07 -080024#include <linux/futex.h>
Eric Laurent81784c32012-11-19 14:55:58 -080025#include <math.h>
Elliott Hughesee499292014-05-21 17:55:51 -070026#include <sys/syscall.h>
Eric Laurent81784c32012-11-19 14:55:58 -080027#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070028#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080029
30#include <private/media/AudioTrackShared.h>
31
Eric Laurent81784c32012-11-19 14:55:58 -080032#include "AudioFlinger.h"
Andy Hung8d31fd22023-06-26 19:20:57 -070033#include "TrackBase.h"
34#include "PlaybackTracks.h"
35#include "RecordTracks.h"
36#include "MmapTracks.h"
Eric Laurent81784c32012-11-19 14:55:58 -080037
Glenn Kastenda6ef132013-01-10 12:31:01 -080038#include <media/nbaio/Pipe.h>
39#include <media/nbaio/PipeReader.h>
Kuowei Lid4adbdb2020-08-13 14:44:25 +080040#include <media/AudioValidator.h>
Andy Hung89816052017-01-11 17:08:23 -080041#include <media/RecordBufferConverter.h>
Andy Hungab7ef302018-05-15 19:35:29 -070042#include <mediautils/ServiceUtilities.h>
Glenn Kastenc56f3422014-03-21 17:53:17 -070043#include <audio_utils/minifloat.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080044
Eric Laurent81784c32012-11-19 14:55:58 -080045// ----------------------------------------------------------------------------
46
47// Note: the following macro is used for extremely verbose logging message. In
48// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
49// 0; but one side effect of this is to turn all LOGV's as well. Some messages
50// are so verbose that we want to suppress them even when we have ALOG_ASSERT
51// turned on. Do not uncomment the #def below unless you really know what you
52// are doing and want to see all of the extremely verbose messages.
53//#define VERY_VERY_VERBOSE_LOGGING
54#ifdef VERY_VERY_VERBOSE_LOGGING
55#define ALOGVV ALOGV
56#else
57#define ALOGVV(a...) do { } while(0)
58#endif
59
Kuowei Lid4adbdb2020-08-13 14:44:25 +080060// TODO: Remove when this is put into AidlConversionUtil.h
61#define VALUE_OR_RETURN_BINDER_STATUS(x) \
62 ({ \
63 auto _tmp = (x); \
64 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
65 std::move(_tmp.value()); \
66 })
67
Eric Laurent81784c32012-11-19 14:55:58 -080068namespace android {
69
Kuowei Lid4adbdb2020-08-13 14:44:25 +080070using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080071using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000072using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070073using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080074// ----------------------------------------------------------------------------
75// TrackBase
76// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070077#undef LOG_TAG
78#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080079
Glenn Kastenda6ef132013-01-10 12:31:01 -080080static volatile int32_t nextTrackId = 55;
81
Eric Laurent81784c32012-11-19 14:55:58 -080082// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -070083TrackBase::TrackBase(
84 AudioFlinger::ThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080085 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070086 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080087 uint32_t sampleRate,
88 audio_format_t format,
89 audio_channel_mask_t channelMask,
90 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070091 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070092 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080093 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070094 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080095 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070096 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070097 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080098 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -080099 audio_port_handle_t portId,
100 std::string metricsId)
Andy Hungd29af632023-06-23 19:27:19 -0700101 :
Eric Laurent81784c32012-11-19 14:55:58 -0800102 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700103 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800104 mClient(client),
105 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700106 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800107 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700108 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800109 mSampleRate(sampleRate),
110 mFormat(format),
111 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700112 mChannelCount(isOut ?
113 audio_channel_count_from_out_mask(channelMask) :
114 audio_channel_count_from_in_mask(channelMask)),
Phil Burkfdb3c072016-02-09 10:47:02 -0800115 mFrameSize(audio_has_proportional_frames(format) ?
Eric Laurent81784c32012-11-19 14:55:58 -0800116 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung8d31fd22023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung8d31fd22023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
279 Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung8d31fd22023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung8d31fd22023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung8d31fd22023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
318 const AudioFlinger::ThreadBase& 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
325 uint64_t mixBufferNs = ((uint64_t)2 * thread.frameCount() * 1000000000) /
326 thread.sampleRate();
327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung8d31fd22023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hunga5a7fc92023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hungd29af632023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hungd29af632023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hungd29af632023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hunga5a7fc92023-06-23 19:27:19 -0700391 // TODO(b/288339104) binder thread priority change not needed.
Andy Hung225aef62022-12-06 16:33:20 -0800392 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800393}
394
Andy Hunga5a7fc92023-06-23 19:27:19 -0700395TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800396 // just stop the track on deletion, associated resources
397 // will be freed from the main thread once all pending buffers have
398 // been played. Unless it's not in the active track list, in which
399 // case we free everything now...
400 mTrack->destroy();
401}
402
Andy Hunga5a7fc92023-06-23 19:27:19 -0700403Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800404 std::optional<media::SharedFileRegion>* _aidl_return) {
405 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
406 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800407}
408
Andy Hunga5a7fc92023-06-23 19:27:19 -0700409Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800410 *_aidl_return = mTrack->start();
411 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800412}
413
Andy Hunga5a7fc92023-06-23 19:27:19 -0700414Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800415 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800416 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800417}
418
Andy Hunga5a7fc92023-06-23 19:27:19 -0700419Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800420 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800422}
423
Andy Hunga5a7fc92023-06-23 19:27:19 -0700424Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800425 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800426 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800427}
428
Andy Hunga5a7fc92023-06-23 19:27:19 -0700429Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800430 int32_t* _aidl_return) {
431 *_aidl_return = mTrack->attachAuxEffect(effectId);
432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hunga5a7fc92023-06-23 19:27:19 -0700435Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800436 int32_t* _aidl_return) {
437 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
438 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700439}
440
Andy Hunga5a7fc92023-06-23 19:27:19 -0700441Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800442 int32_t* _aidl_return) {
443 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
444 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800445}
446
Andy Hunga5a7fc92023-06-23 19:27:19 -0700447Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800448 int32_t* _aidl_return) {
449 AudioTimestamp legacy;
450 *_aidl_return = mTrack->getTimestamp(legacy);
451 if (*_aidl_return != OK) {
452 return Status::ok();
453 }
Andy Hung973638a2020-12-08 20:47:45 -0800454 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800455 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800456}
457
Andy Hunga5a7fc92023-06-23 19:27:19 -0700458Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 mTrack->signal();
460 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800461}
462
Andy Hunga5a7fc92023-06-23 19:27:19 -0700463Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800464 const media::VolumeShaperConfiguration& configuration,
465 const media::VolumeShaperOperation& operation,
466 int32_t* _aidl_return) {
467 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
468 *_aidl_return = conf->readFromParcelable(configuration);
469 if (*_aidl_return != OK) {
470 return Status::ok();
471 }
472
473 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
474 *_aidl_return = op->readFromParcelable(operation);
475 if (*_aidl_return != OK) {
476 return Status::ok();
477 }
478
479 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
480 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700481}
482
Andy Hunga5a7fc92023-06-23 19:27:19 -0700483Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800484 int32_t id,
485 std::optional<media::VolumeShaperState>* _aidl_return) {
486 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
487 if (legacy == nullptr) {
488 _aidl_return->reset();
489 return Status::ok();
490 }
491 media::VolumeShaperState aidl;
492 legacy->writeToParcelable(&aidl);
493 *_aidl_return = aidl;
494 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800495}
496
Andy Hunga5a7fc92023-06-23 19:27:19 -0700497Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000498 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800499{
500 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
501 const status_t status = mTrack->getDualMonoMode(&mode)
502 ?: AudioValidator::validateDualMonoMode(mode);
503 if (status == OK) {
504 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
505 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
506 }
507 return binderStatusFromStatusT(status);
508}
509
Andy Hunga5a7fc92023-06-23 19:27:19 -0700510Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000511 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800512{
513 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
514 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
515 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
516 ?: mTrack->setDualMonoMode(localMonoMode));
517}
518
Andy Hunga5a7fc92023-06-23 19:27:19 -0700519Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800520{
521 float leveldB = -std::numeric_limits<float>::infinity();
522 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
523 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
524 if (status == OK) *_aidl_return = leveldB;
525 return binderStatusFromStatusT(status);
526}
527
Andy Hunga5a7fc92023-06-23 19:27:19 -0700528Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800529{
530 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
531 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
532}
533
Andy Hunga5a7fc92023-06-23 19:27:19 -0700534Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000535 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800536{
537 audio_playback_rate_t localPlaybackRate{};
538 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
539 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
540 if (status == NO_ERROR) {
541 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
542 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
543 }
544 return binderStatusFromStatusT(status);
545}
546
Andy Hunga5a7fc92023-06-23 19:27:19 -0700547Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000548 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800549{
550 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
551 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
552 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
553 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
554}
555
Eric Laurent81784c32012-11-19 14:55:58 -0800556// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800557// AppOp for audio playback
558// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700559
560// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700561sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Svet Ganov33761132021-05-13 22:51:08 +0000562 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700563 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800564{
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000565 Vector <String16> packages;
Svet Ganov33761132021-05-13 22:51:08 +0000566 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000567 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700568 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700569 if (packages.isEmpty()) {
570 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
571 id,
572 attr.usage,
573 uid);
574 return nullptr;
575 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800576 }
577 // stream type has been filtered by audio policy to indicate whether it can be muted
578 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700579 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700580 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800581 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700582 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
583 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
584 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
585 id, attr.flags);
586 return nullptr;
587 }
Eric Laurent9ff3e532022-11-10 16:04:44 +0100588 return new OpPlayAudioMonitor(attributionSource, attr.usage, id);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700589}
590
Andy Hung8d31fd22023-06-26 19:20:57 -0700591OpPlayAudioMonitor::OpPlayAudioMonitor(
Svet Ganov33761132021-05-13 22:51:08 +0000592 const AttributionSourceState& attributionSource, audio_usage_t usage, int id)
593 : mHasOpPlayAudio(true), mAttributionSource(attributionSource), mUsage((int32_t) usage),
594 mId(id)
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700595{
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800596}
597
Andy Hung8d31fd22023-06-26 19:20:57 -0700598OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800599{
600 if (mOpCallback != 0) {
601 mAppOpsManager.stopWatchingMode(mOpCallback);
602 }
603 mOpCallback.clear();
604}
605
Andy Hung8d31fd22023-06-26 19:20:57 -0700606void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700607{
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700608 checkPlayAudioForUsage();
Svet Ganov33761132021-05-13 22:51:08 +0000609 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700610 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700611 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Svet Ganov33761132021-05-13 22:51:08 +0000612 VALUE_OR_FATAL(aidl2legacy_string_view_String16(
613 mAttributionSource.packageName.value_or("")))
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700614 , mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700615 }
616}
617
Andy Hung8d31fd22023-06-26 19:20:57 -0700618bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800619 return mHasOpPlayAudio.load();
620}
621
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700622// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800623// - not called from constructor due to check on UID,
624// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung8d31fd22023-06-26 19:20:57 -0700625void OpPlayAudioMonitor::checkPlayAudioForUsage()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800626{
Svet Ganov33761132021-05-13 22:51:08 +0000627 if (!mAttributionSource.packageName.has_value()) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800628 mHasOpPlayAudio.store(false);
629 } else {
Svet Ganov33761132021-05-13 22:51:08 +0000630 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mAttributionSource.uid));
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700631 String16 packageName = VALUE_OR_FATAL(
Svet Ganov33761132021-05-13 22:51:08 +0000632 aidl2legacy_string_view_String16(mAttributionSource.packageName.value_or("")));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000633 bool hasIt = mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700634 mUsage, uid, packageName) == AppOpsManager::MODE_ALLOWED;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800635 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasIt ? "not " : "");
636 mHasOpPlayAudio.store(hasIt);
637 }
638}
639
Andy Hung8d31fd22023-06-26 19:20:57 -0700640OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800641 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
642{ }
643
Andy Hung8d31fd22023-06-26 19:20:57 -0700644void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800645 const String16& packageName) {
646 // we only have uid, so we need to check all package names anyway
647 UNUSED(packageName);
648 if (op != AppOpsManager::OP_PLAY_AUDIO) {
649 return;
650 }
651 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
652 if (monitor != NULL) {
653 monitor->checkPlayAudioForUsage();
654 }
655}
656
Eric Laurent9066ad32019-05-20 14:40:10 -0700657// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700658void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700659 uid_t uid, Vector<String16>& packages)
660{
661 PermissionController permissionController;
662 permissionController.getPackagesForUid(uid, packages);
663}
664
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800665// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700666#undef LOG_TAG
667#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800668
Andy Hung8d31fd22023-06-26 19:20:57 -0700669/* static */
670sp<IAfTrack> IAfTrack::create( // TODO(b/288339104) void*
671 void * /* AudioFlinger::PlaybackThread */ thread,
672 const sp<Client>& client,
673 audio_stream_type_t streamType,
674 const audio_attributes_t& attr,
675 uint32_t sampleRate,
676 audio_format_t format,
677 audio_channel_mask_t channelMask,
678 size_t frameCount,
679 void *buffer,
680 size_t bufferSize,
681 const sp<IMemory>& sharedBuffer,
682 audio_session_t sessionId,
683 pid_t creatorPid,
684 const AttributionSourceState& attributionSource,
685 audio_output_flags_t flags,
686 track_type type,
687 audio_port_handle_t portId,
688 /** default behaviour is to start when there are as many frames
689 * ready as possible (aka. Buffer is full). */
690 size_t frameCountToBeReady,
691 float speed,
692 bool isSpatialized,
693 bool isBitPerfect) {
694 return sp<Track>::make(reinterpret_cast<AudioFlinger::PlaybackThread*>(thread),
695 client,
696 streamType,
697 attr,
698 sampleRate,
699 format,
700 channelMask,
701 frameCount,
702 buffer,
703 bufferSize,
704 sharedBuffer,
705 sessionId,
706 creatorPid,
707 attributionSource,
708 flags,
709 type,
710 portId,
711 frameCountToBeReady,
712 speed,
713 isSpatialized,
714 isBitPerfect);
715}
716
Eric Laurent81784c32012-11-19 14:55:58 -0800717// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700718Track::Track(
719 AudioFlinger::PlaybackThread *thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800720 const sp<Client>& client,
721 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700722 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800723 uint32_t sampleRate,
724 audio_format_t format,
725 audio_channel_mask_t channelMask,
726 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700727 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700728 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800729 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800730 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700731 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000732 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700733 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800734 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100735 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000736 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200737 float speed,
jiabinc658e452022-10-21 20:52:21 +0000738 bool isSpatialized,
739 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700740 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700741 // TODO: Using unsecurePointer() has some associated security pitfalls
742 // (see declaration for details).
743 // Either document why it is safe in this case or address the
744 // issue (e.g. by copying).
745 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700746 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700747 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000748 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700749 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800750 type,
751 portId,
752 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700753 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800754 // mRetryCount initialized later when needed
755 mSharedBuffer(sharedBuffer),
756 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700757 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800758 mAuxBuffer(NULL),
759 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700760 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700761 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Svet Ganov33761132021-05-13 22:51:08 +0000762 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700763 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700764 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800765 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800766 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700767 /* The track might not play immediately after being active, similarly as if its volume was 0.
768 * When the track starts playing, its volume will be computed. */
769 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800770 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700771 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000772 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200773 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000774 mIsSpatialized(isSpatialized),
775 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800776{
Eric Laurent83b88082014-06-20 18:31:16 -0700777 // client == 0 implies sharedBuffer == 0
778 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
779
Andy Hung9d84af52018-09-12 18:03:44 -0700780 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700781 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700782
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700783 if (mCblk == NULL) {
784 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800785 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700786
Svet Ganov33761132021-05-13 22:51:08 +0000787 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700788 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
789 ALOGE("%s(%d): no more tracks available", __func__, mId);
790 releaseCblk(); // this makes the track invalid.
791 return;
792 }
793
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700794 if (sharedBuffer == 0) {
795 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700796 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700797 } else {
798 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100799 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700800 }
801 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700802 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700803
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700804 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700805 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700806 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
807 // race with setSyncEvent(). However, if we call it, we cannot properly start
808 // static fast tracks (SoundPool) immediately after stopping.
809 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700810 ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
811 int i = __builtin_ctz(thread->mFastTrackAvailMask);
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700812 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700813 // FIXME This is too eager. We allocate a fast track index before the
814 // fast track becomes active. Since fast tracks are a scarce resource,
815 // this means we are potentially denying other more important fast tracks from
816 // being created. It would be better to allocate the index dynamically.
817 mFastIndex = i;
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700818 thread->mFastTrackAvailMask &= ~(1 << i);
819 }
Andy Hung8946a282018-04-19 20:04:56 -0700820
Dean Wheatley7b036912020-06-18 16:22:11 +1000821 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700822#ifdef TEE_SINK
823 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800824 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700825#endif
jiabin57303cc2018-12-18 15:45:57 -0800826
jiabineb3bda02020-06-30 14:07:03 -0700827 if (thread->supportsHapticPlayback()) {
828 // If the track is attached to haptic playback thread, it is potentially to have
829 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
830 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800831 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000832 std::string packageName = attributionSource.packageName.has_value() ?
833 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800834 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700835 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800836 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800837
838 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700839 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800840 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800841}
842
Andy Hung8d31fd22023-06-26 19:20:57 -0700843Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800844{
Andy Hung9d84af52018-09-12 18:03:44 -0700845 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700846
847 // The destructor would clear mSharedBuffer,
848 // but it will not push the decremented reference count,
849 // leaving the client's IMemory dangling indefinitely.
850 // This prevents that leak.
851 if (mSharedBuffer != 0) {
852 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700853 }
Eric Laurent81784c32012-11-19 14:55:58 -0800854}
855
Andy Hung8d31fd22023-06-26 19:20:57 -0700856status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700857{
858 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700859 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700860 status = NO_MEMORY;
861 }
862 return status;
863}
864
Andy Hung8d31fd22023-06-26 19:20:57 -0700865void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800866{
867 // NOTE: destroyTrack_l() can remove a strong reference to this Track
868 // by removing it from mTracks vector, so there is a risk that this Tracks's
869 // destructor is called. As the destructor needs to lock mLock,
870 // we must acquire a strong reference on this Track before locking mLock
871 // here so that the destructor is called only when exiting this function.
872 // On the other hand, as long as Track::destroy() is only called by
873 // TrackHandle destructor, the TrackHandle still holds a strong ref on
874 // this Track with its member mTrack.
875 sp<Track> keep(this);
876 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700877 bool wasActive = false;
Andy Hung8d31fd22023-06-26 19:20:57 -0700878 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800879 if (thread != 0) {
Eric Laurent81784c32012-11-19 14:55:58 -0800880 Mutex::Autolock _l(thread->mLock);
Andy Hung8d31fd22023-06-26 19:20:57 -0700881 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurentaaa44472014-09-12 17:41:50 -0700882 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000883 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700884 }
885 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700886 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800887 }
888 }
889}
890
Andy Hung8d31fd22023-06-26 19:20:57 -0700891void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800892{
Eric Laurent973db022018-11-20 14:54:31 -0800893 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700894 " Format Chn mask SRate "
895 "ST Usg CT "
896 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000897 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700898 "%s\n",
899 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800900}
901
Andy Hung8d31fd22023-06-26 19:20:57 -0700902void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800903{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700904 char trackType;
905 switch (mType) {
906 case TYPE_DEFAULT:
907 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700908 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700909 trackType = 'S'; // static
910 } else {
911 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800912 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700913 break;
914 case TYPE_PATCH:
915 trackType = 'P';
916 break;
917 default:
918 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800919 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700920
921 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700922 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700923 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700924 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700925 }
926
Eric Laurent81784c32012-11-19 14:55:58 -0800927 char nowInUnderrun;
928 switch (mObservedUnderruns.mBitFields.mMostRecent) {
929 case UNDERRUN_FULL:
930 nowInUnderrun = ' ';
931 break;
932 case UNDERRUN_PARTIAL:
933 nowInUnderrun = '<';
934 break;
935 case UNDERRUN_EMPTY:
936 nowInUnderrun = '*';
937 break;
938 default:
939 nowInUnderrun = '?';
940 break;
941 }
Andy Hungda540db2017-04-20 14:06:17 -0700942
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700943 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700944 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700945 case FS_INVALID:
946 fillingStatus = 'I';
947 break;
948 case FS_FILLING:
949 fillingStatus = 'f';
950 break;
951 case FS_FILLED:
952 fillingStatus = 'F';
953 break;
954 case FS_ACTIVE:
955 fillingStatus = 'A';
956 break;
957 default:
958 fillingStatus = '?';
959 break;
960 }
961
962 // clip framesReadySafe to max representation in dump
963 const size_t framesReadySafe =
964 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
965
966 // obtain volumes
967 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
968 const std::pair<float /* volume */, bool /* active */> vsVolume =
969 mVolumeHandler->getLastVolume();
970
971 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
972 // as it may be reduced by the application.
973 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
974 // Check whether the buffer size has been modified by the app.
975 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
976 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
977 ? 'e' /* error */ : ' ' /* identical */;
978
Eric Laurent973db022018-11-20 14:54:31 -0800979 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700980 "%08X %08X %6u "
981 "%2u %3x %2x "
982 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000983 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800984 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700985 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700986 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -0800987 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -0800988 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700989 mCblk->mFlags,
990
Eric Laurent81784c32012-11-19 14:55:58 -0800991 mFormat,
992 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -0700993 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700994
995 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700996 mAttr.usage,
997 mAttr.content_type,
998
999 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001000 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1001 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001002 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1003 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001004
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001005 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001006 bufferSizeInFrames,
1007 modifiedBufferChar,
1008 framesReadySafe,
1009 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001010 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001011 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001012 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1013 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001014 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001015
1016 if (isServerLatencySupported()) {
1017 double latencyMs;
1018 bool fromTrack;
1019 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1020 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1021 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1022 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001023 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001024 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001025 }
1026 }
1027 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001028}
1029
Andy Hung8d31fd22023-06-26 19:20:57 -07001030uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001031 return mAudioTrackServerProxy->getSampleRate();
1032}
1033
Eric Laurent81784c32012-11-19 14:55:58 -08001034// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001035status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001036{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001037 ServerProxy::Buffer buf;
1038 size_t desiredFrames = buffer->frameCount;
1039 buf.mFrameCount = desiredFrames;
1040 status_t status = mServerProxy->obtainBuffer(&buf);
1041 buffer->frameCount = buf.mFrameCount;
1042 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001043 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001044 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001045 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001046 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001047 } else {
1048 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001049 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001050 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001051}
1052
Andy Hung8d31fd22023-06-26 19:20:57 -07001053void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001054{
1055 interceptBuffer(*buffer);
1056 TrackBase::releaseBuffer(buffer);
1057}
1058
1059// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001060void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001061 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001062 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001063 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001064 if (frameCount == 0) {
1065 return; // No audio to intercept.
1066 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1067 // does not allow 0 frame size request contrary to getNextBuffer
1068 }
1069 for (auto& teePatch : mTeePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001070 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001071 const size_t framesWritten = patchRecord->writeFrames(
1072 sourceBuffer.i8, frameCount, mFrameSize);
1073 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001074 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001075 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001076 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001077 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001078 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1079 using namespace std::chrono_literals;
1080 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001081 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001082 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001083}
1084
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001085// ExtendedAudioBufferProvider interface
1086
Andy Hung27876c02014-09-09 18:07:55 -07001087// framesReady() may return an approximation of the number of frames if called
1088// from a different thread than the one calling Proxy->obtainBuffer() and
1089// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1090// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001091size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001092 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1093 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1094 // The remainder of the buffer is not drained.
1095 return 0;
1096 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001097 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001098}
1099
Andy Hung8d31fd22023-06-26 19:20:57 -07001100int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001101{
1102 return mAudioTrackServerProxy->framesReleased();
1103}
1104
Andy Hung8d31fd22023-06-26 19:20:57 -07001105void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001106{
1107 // This call comes from a FastTrack and should be kept lockless.
1108 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001109 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001110
Andy Hung818e7a32016-02-16 18:08:07 -08001111 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001112
1113 // Compute latency.
1114 // TODO: Consider whether the server latency may be passed in by FastMixer
1115 // as a constant for all active FastTracks.
1116 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1117 mServerLatencyFromTrack.store(true);
1118 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001119}
1120
Eric Laurent81784c32012-11-19 14:55:58 -08001121// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001122bool Track::isReady() const {
1123 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001124 return true;
1125 }
1126
Eric Laurent16498512014-03-17 17:22:08 -07001127 if (isStopping()) {
1128 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001129 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001130 }
Eric Laurent81784c32012-11-19 14:55:58 -08001131 return true;
1132 }
1133
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001134 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001135 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1136 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1137 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1138 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001139
1140 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1141 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1142 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001143 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001144 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001145 return true;
1146 }
1147 return false;
1148}
1149
Andy Hung8d31fd22023-06-26 19:20:57 -07001150status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001151 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001152{
1153 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001154 ALOGV("%s(%d): calling pid %d session %d",
1155 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001156
Andy Hung8d31fd22023-06-26 19:20:57 -07001157 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001158 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001159 if (isOffloaded()) {
1160 Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
1161 Mutex::Autolock _lth(thread->mLock);
Andy Hung116bc262023-06-20 18:56:17 -07001162 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Eric Laurent5baf2af2013-09-12 17:37:00 -07001163 if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
1164 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001165 invalidate();
1166 return PERMISSION_DENIED;
1167 }
1168 }
1169 Mutex::Autolock _lth(thread->mLock);
Eric Laurent81784c32012-11-19 14:55:58 -08001170 track_state state = mState;
1171 // here the track could be either new, or restarted
1172 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001173
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001174 // initial state-stopping. next state-pausing.
1175 // What if resume is called ?
1176
Zhou Song1ed46a22020-08-17 15:36:56 +08001177 if (state == FLUSHED) {
1178 // avoid underrun glitches when starting after flush
1179 reset();
1180 }
1181
kuowei.li576f1362021-05-11 18:02:32 +08001182 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1183 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001184 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001185 if (mResumeToStopping) {
1186 // happened we need to resume to STOPPING_1
1187 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001188 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1189 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001190 } else {
1191 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001192 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1193 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001194 }
Eric Laurent81784c32012-11-19 14:55:58 -08001195 } else {
1196 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001197 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1198 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001199 }
1200
Andy Hung8d31fd22023-06-26 19:20:57 -07001201 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
yucliu6cfb5932022-07-20 17:40:39 -07001202
1203 // states to reset position info for pcm tracks
1204 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001205 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1206 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001207
1208 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1209 // Start point of track -> sink frame map. If the HAL returns a
1210 // frame position smaller than the first written frame in
1211 // updateTrackFrameInfo, the timestamp can be interpolated
1212 // instead of using a larger value.
1213 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1214 playbackThread->framesWritten());
1215 }
Andy Hunge10393e2015-06-12 13:59:33 -07001216 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001217 if (isFastTrack()) {
1218 // refresh fast track underruns on start because that field is never cleared
1219 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1220 // after stop.
1221 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1222 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001223 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001224 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001225 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001226 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001227 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001228 mState = state;
1229 }
1230 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001231
Andy Hungb68f5eb2019-12-03 16:49:17 -08001232 // Audio timing metrics are computed a few mix cycles after starting.
1233 {
1234 mLogStartCountdown = LOG_START_COUNTDOWN;
1235 mLogStartTimeNs = systemTime();
1236 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001237 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1238 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001239 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001240 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001241
Andy Hung1d3556d2018-03-29 16:30:14 -07001242 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1243 // for streaming tracks, remove the buffer read stop limit.
1244 mAudioTrackServerProxy->start();
1245 }
1246
Eric Laurentbfb1b832013-01-07 09:53:42 -08001247 // track was already in the active list, not a problem
1248 if (status == ALREADY_EXISTS) {
1249 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001250 } else {
1251 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1252 // It is usually unsafe to access the server proxy from a binder thread.
1253 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1254 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1255 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001256 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001257 ServerProxy::Buffer buffer;
1258 buffer.mFrameCount = 1;
1259 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001260 }
jiabin7434e812023-06-27 18:22:35 +00001261 if (status == NO_ERROR) {
1262 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1263 }
Eric Laurent81784c32012-11-19 14:55:58 -08001264 } else {
1265 status = BAD_VALUE;
1266 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001267 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001268 // send format to AudioManager for playback activity monitoring
1269 sp<IAudioManager> audioManager = thread->mAudioFlinger->getOrCreateAudioManager();
1270 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1271 std::unique_ptr<os::PersistableBundle> bundle =
1272 std::make_unique<os::PersistableBundle>();
1273 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1274 isSpatialized());
1275 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1276 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1277 status_t result = audioManager->portEvent(mPortId,
1278 PLAYER_UPDATE_FORMAT, bundle);
1279 if (result != OK) {
1280 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1281 __func__, mPortId, result);
1282 }
1283 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001284 }
Eric Laurent81784c32012-11-19 14:55:58 -08001285 return status;
1286}
1287
Andy Hung8d31fd22023-06-26 19:20:57 -07001288void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001289{
Andy Hungc0691382018-09-12 18:01:57 -07001290 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung8d31fd22023-06-26 19:20:57 -07001291 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001292 if (thread != 0) {
1293 Mutex::Autolock _l(thread->mLock);
1294 track_state state = mState;
1295 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1296 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung8d31fd22023-06-26 19:20:57 -07001297 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurent81784c32012-11-19 14:55:58 -08001298 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
1299 reset();
1300 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001301 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001302 mState = STOPPED;
1303 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001304 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1305 // presentation is complete
1306 // For an offloaded track this starts a drain and state will
1307 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001308 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001309 if (isOffloaded()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001310 mRetryCount = AudioFlinger::PlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001311 }
Eric Laurent81784c32012-11-19 14:55:58 -08001312 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001313 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001314 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1315 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001316 }
jiabin7434e812023-06-27 18:22:35 +00001317 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001318 }
1319}
1320
Andy Hung8d31fd22023-06-26 19:20:57 -07001321void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001322{
Andy Hungc0691382018-09-12 18:01:57 -07001323 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung8d31fd22023-06-26 19:20:57 -07001324 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001325 if (thread != 0) {
1326 Mutex::Autolock _l(thread->mLock);
Andy Hung8d31fd22023-06-26 19:20:57 -07001327 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurentbfb1b832013-01-07 09:53:42 -08001328 switch (mState) {
1329 case STOPPING_1:
1330 case STOPPING_2:
1331 if (!isOffloaded()) {
1332 /* nothing to do if track is not offloaded */
1333 break;
1334 }
1335
1336 // Offloaded track was draining, we need to carry on draining when resumed
1337 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001338 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001339 case ACTIVE:
1340 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001341 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001342 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1343 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001344 if (isOffloadedOrDirect()) {
1345 mPauseHwPending = true;
1346 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001347 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001348 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001349
Eric Laurentbfb1b832013-01-07 09:53:42 -08001350 default:
1351 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001352 }
jiabin7434e812023-06-27 18:22:35 +00001353 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1354 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001355 }
1356}
1357
Andy Hung8d31fd22023-06-26 19:20:57 -07001358void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001359{
Andy Hungc0691382018-09-12 18:01:57 -07001360 ALOGV("%s(%d)", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07001361 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001362 if (thread != 0) {
1363 Mutex::Autolock _l(thread->mLock);
Andy Hung8d31fd22023-06-26 19:20:57 -07001364 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurentbfb1b832013-01-07 09:53:42 -08001365
Phil Burk4bb650b2016-09-09 12:11:17 -07001366 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1367 // Otherwise the flush would not be done until the track is resumed.
1368 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
1369 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
1370 (void)mServerProxy->flushBufferIfNeeded();
1371 }
1372
Eric Laurentbfb1b832013-01-07 09:53:42 -08001373 if (isOffloaded()) {
1374 // If offloaded we allow flush during any state except terminated
1375 // and keep the track active to avoid problems if user is seeking
1376 // rapidly and underlying hardware has a significant delay handling
1377 // a pause
1378 if (isTerminated()) {
1379 return;
1380 }
1381
Andy Hung9d84af52018-09-12 18:03:44 -07001382 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001383 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001384
1385 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001386 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1387 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001388 mState = ACTIVE;
1389 }
1390
Haynes Mathew George7844f672014-01-15 12:32:55 -08001391 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001392 mResumeToStopping = false;
1393 } else {
1394 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1395 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1396 return;
1397 }
1398 // No point remaining in PAUSED state after a flush => go to
1399 // FLUSHED state
1400 mState = FLUSHED;
1401 // do not reset the track if it is still in the process of being stopped or paused.
1402 // this will be done by prepareTracks_l() when the track is stopped.
1403 // prepareTracks_l() will see mState == FLUSHED, then
1404 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001405 if (isDirect()) {
1406 mFlushHwPending = true;
1407 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001408 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
1409 reset();
1410 }
Eric Laurent81784c32012-11-19 14:55:58 -08001411 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001412 // Prevent flush being lost if the track is flushed and then resumed
1413 // before mixer thread can run. This is important when offloading
1414 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001415 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001416 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1417 // new data
1418 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001419 }
1420}
1421
Haynes Mathew George7844f672014-01-15 12:32:55 -08001422// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001423void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001424{
Andy Hung920f6572022-10-06 12:09:49 -07001425 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001426 return;
Andy Hung920f6572022-10-06 12:09:49 -07001427 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001428
Phil Burk4bb650b2016-09-09 12:11:17 -07001429 // Clear the client ring buffer so that the app can prime the buffer while paused.
1430 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1431 mServerProxy->flushBufferIfNeeded();
1432
Haynes Mathew George7844f672014-01-15 12:32:55 -08001433 mFlushHwPending = false;
1434}
1435
Andy Hung8d31fd22023-06-26 19:20:57 -07001436void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001437{
1438 mPauseHwPending = false;
1439}
1440
Andy Hung8d31fd22023-06-26 19:20:57 -07001441void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001442{
1443 // Do not reset twice to avoid discarding data written just after a flush and before
1444 // the audioflinger thread detects the track is stopped.
1445 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001446 // Force underrun condition to avoid false underrun callback until first data is
1447 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001448 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001449 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001450 mResetDone = true;
1451 if (mState == FLUSHED) {
1452 mState = IDLE;
1453 }
1454 }
1455}
1456
Andy Hung8d31fd22023-06-26 19:20:57 -07001457status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001458{
Andy Hung8d31fd22023-06-26 19:20:57 -07001459 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001460 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001461 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001462 return FAILED_TRANSACTION;
Andy Hung8d31fd22023-06-26 19:20:57 -07001463 } else if ((thread->type() == AudioFlinger::ThreadBase::DIRECT) ||
1464 (thread->type() == AudioFlinger::ThreadBase::OFFLOAD)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001465 return thread->setParameters(keyValuePairs);
1466 } else {
1467 return PERMISSION_DENIED;
1468 }
1469}
1470
Andy Hung8d31fd22023-06-26 19:20:57 -07001471status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001472 int programId) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001473 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001474 if (thread == 0) {
1475 ALOGE("thread is dead");
1476 return FAILED_TRANSACTION;
Andy Hung8d31fd22023-06-26 19:20:57 -07001477 } else if ((thread->type() == AudioFlinger::ThreadBase::DIRECT)
1478 || (thread->type() == AudioFlinger::ThreadBase::OFFLOAD)) {
1479 auto directOutputThread = static_cast<AudioFlinger::DirectOutputThread*>(thread.get());
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001480 return directOutputThread->selectPresentation(presentationId, programId);
1481 }
1482 return INVALID_OPERATION;
1483}
1484
Andy Hung8d31fd22023-06-26 19:20:57 -07001485VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001486 const sp<VolumeShaper::Configuration>& configuration,
1487 const sp<VolumeShaper::Operation>& operation)
1488{
Andy Hung398ffa22022-12-13 19:19:53 -08001489 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001490
1491 if (isOffloadedOrDirect()) {
1492 // Signal thread to fetch new volume.
Andy Hung8d31fd22023-06-26 19:20:57 -07001493 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001494 if (thread != 0) {
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001495 Mutex::Autolock _l(thread->mLock);
Andy Hung10cbff12017-02-21 17:30:14 -08001496 thread->broadcast_l();
1497 }
1498 }
1499 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001500}
1501
Andy Hung8d31fd22023-06-26 19:20:57 -07001502sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001503{
1504 // Note: We don't check if Thread exists.
1505
1506 // mVolumeHandler is thread safe.
1507 return mVolumeHandler->getVolumeShaperState(id);
1508}
1509
Andy Hung8d31fd22023-06-26 19:20:57 -07001510void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001511{
jiabin76d94692022-12-15 21:51:21 +00001512 mFinalVolumeLeft = volumeLeft;
1513 mFinalVolumeRight = volumeRight;
1514 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001515 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1516 mFinalVolume = volume;
1517 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001518 mLogForceVolumeUpdate = true;
1519 }
1520 if (mLogForceVolumeUpdate) {
1521 mLogForceVolumeUpdate = false;
1522 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001523 }
1524}
1525
Andy Hung8d31fd22023-06-26 19:20:57 -07001526void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001527{
Eric Laurent49e39282022-06-24 18:42:45 +02001528 // Do not forward metadata for PatchTrack with unspecified stream type
1529 if (mStreamType == AUDIO_STREAM_PATCH) {
1530 return;
1531 }
1532
Eric Laurent94579172020-11-20 18:41:04 +01001533 playback_track_metadata_v7_t metadata;
1534 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001535 .usage = mAttr.usage,
1536 .content_type = mAttr.content_type,
1537 .gain = mFinalVolume,
1538 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001539
1540 // When attributes are undefined, derive default values from stream type.
1541 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1542 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1543 switch (mStreamType) {
1544 case AUDIO_STREAM_VOICE_CALL:
1545 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1546 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1547 break;
1548 case AUDIO_STREAM_SYSTEM:
1549 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1550 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1551 break;
1552 case AUDIO_STREAM_RING:
1553 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1554 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1555 break;
1556 case AUDIO_STREAM_MUSIC:
1557 metadata.base.usage = AUDIO_USAGE_MEDIA;
1558 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1559 break;
1560 case AUDIO_STREAM_ALARM:
1561 metadata.base.usage = AUDIO_USAGE_ALARM;
1562 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1563 break;
1564 case AUDIO_STREAM_NOTIFICATION:
1565 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1566 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1567 break;
1568 case AUDIO_STREAM_DTMF:
1569 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1570 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1571 break;
1572 case AUDIO_STREAM_ACCESSIBILITY:
1573 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1574 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1575 break;
1576 case AUDIO_STREAM_ASSISTANT:
1577 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1578 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1579 break;
1580 case AUDIO_STREAM_REROUTING:
1581 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1582 // unknown content type
1583 break;
1584 case AUDIO_STREAM_CALL_ASSISTANT:
1585 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1586 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1587 break;
1588 default:
1589 break;
1590 }
1591 }
1592
Eric Laurent78b07302022-10-07 16:20:34 +02001593 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001594 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1595 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001596}
1597
Andy Hung8d31fd22023-06-26 19:20:57 -07001598void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001599 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001600 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001601 mTeePatches = mTeePatchesToUpdate.value();
1602 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1603 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001604 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001605 }
1606 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001607 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001608}
1609
Andy Hung8d31fd22023-06-26 19:20:57 -07001610void Track::setTeePatchesToUpdate_l(AudioFlinger::TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001611 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1612 "%s, existing tee patches to update will be ignored", __func__);
1613 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1614}
1615
Vlad Popae8d99472022-06-30 16:02:48 +02001616// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001617void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001618 IAudioManager>& audioManager, mute_state_t muteState)
1619{
1620 if (mMuteState == muteState) {
1621 // mute state did not change, do nothing
1622 return;
1623 }
1624
1625 status_t result = UNKNOWN_ERROR;
1626 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1627 if (mMuteEventExtras == nullptr) {
1628 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1629 }
1630 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1631 static_cast<int>(muteState));
1632
1633 result = audioManager->portEvent(mPortId,
1634 PLAYER_UPDATE_MUTED,
1635 mMuteEventExtras);
1636 }
1637
1638 if (result == OK) {
1639 mMuteState = muteState;
1640 } else {
1641 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1642 __func__,
1643 id(),
1644 mPortId,
1645 result);
1646 }
1647}
1648
Andy Hung8d31fd22023-06-26 19:20:57 -07001649status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001650{
Andy Hung818e7a32016-02-16 18:08:07 -08001651 if (!isOffloaded() && !isDirect()) {
1652 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001653 }
Andy Hung8d31fd22023-06-26 19:20:57 -07001654 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001655 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001656 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001657 }
Phil Burk6140c792015-03-19 14:30:21 -07001658
Glenn Kasten573d80a2013-08-26 09:36:23 -07001659 Mutex::Autolock _l(thread->mLock);
Andy Hung8d31fd22023-06-26 19:20:57 -07001660 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Andy Hung818e7a32016-02-16 18:08:07 -08001661 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001662}
1663
Andy Hung8d31fd22023-06-26 19:20:57 -07001664status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001665{
Andy Hung8d31fd22023-06-26 19:20:57 -07001666 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001667 if (thread == nullptr) {
1668 return DEAD_OBJECT;
1669 }
Eric Laurent81784c32012-11-19 14:55:58 -08001670
Andy Hung8d31fd22023-06-26 19:20:57 -07001671 auto dstThread = sp<AudioFlinger::PlaybackThread>::cast(thread);
1672 // srcThread is initialized by call to moveAuxEffectToIo()
1673 sp<AudioFlinger::PlaybackThread> srcThread;
Eric Laurent6c796322019-04-09 14:13:17 -07001674 sp<AudioFlinger> af = mClient->audioFlinger();
1675 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001676
Eric Laurent6c796322019-04-09 14:13:17 -07001677 if (EffectId != 0 && status == NO_ERROR) {
1678 status = dstThread->attachAuxEffect(this, EffectId);
1679 if (status == NO_ERROR) {
1680 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001681 }
Eric Laurent6c796322019-04-09 14:13:17 -07001682 }
1683
1684 if (status != NO_ERROR && srcThread != nullptr) {
1685 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001686 }
1687 return status;
1688}
1689
Andy Hung8d31fd22023-06-26 19:20:57 -07001690void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001691{
1692 mAuxEffectId = EffectId;
1693 mAuxBuffer = buffer;
1694}
1695
Andy Hung59de4262021-06-14 10:53:54 -07001696// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001697bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001698 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001699{
Andy Hung818e7a32016-02-16 18:08:07 -08001700 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1701 // This assists in proper timestamp computation as well as wakelock management.
1702
Eric Laurent81784c32012-11-19 14:55:58 -08001703 // a track is considered presented when the total number of frames written to audio HAL
1704 // corresponds to the number of frames written when presentationComplete() is called for the
1705 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001706 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1707 // to detect when all frames have been played. In this case framesWritten isn't
1708 // useful because it doesn't always reflect whether there is data in the h/w
1709 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001710 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1711 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001712 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001713 if (mPresentationCompleteFrames == 0) {
1714 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001715 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001716 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1717 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001718 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001719 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001720
Andy Hungc54b1ff2016-02-23 14:07:07 -08001721 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001722 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001723 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001724 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1725 __func__, mId, (complete ? "complete" : "waiting"),
1726 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001727 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001728 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001729 && mAudioTrackServerProxy->isDrained();
1730 }
1731
1732 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001733 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001734 return true;
1735 }
1736 return false;
1737}
1738
Andy Hung59de4262021-06-14 10:53:54 -07001739// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001740bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001741{
1742 // For Offloaded or Direct tracks.
1743
1744 // For a direct track, we incorporated time based testing for presentationComplete.
1745
1746 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1747 // to detect when all frames have been played. In this case latencyMs isn't
1748 // useful because it doesn't always reflect whether there is data in the h/w
1749 // buffers, particularly if a track has been paused and resumed during draining
1750
1751 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1752 if (mPresentationCompleteTimeNs == 0) {
1753 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1754 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1755 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1756 }
1757
1758 bool complete;
1759 if (isOffloaded()) {
1760 complete = true;
1761 } else { // Direct
1762 complete = systemTime() >= mPresentationCompleteTimeNs;
1763 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1764 }
1765 if (complete) {
1766 notifyPresentationComplete();
1767 return true;
1768 }
1769 return false;
1770}
1771
Andy Hung8d31fd22023-06-26 19:20:57 -07001772void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001773{
1774 // This only triggers once. TODO: should we enforce this?
1775 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1776 mAudioTrackServerProxy->setStreamEndDone();
1777}
1778
Andy Hung8d31fd22023-06-26 19:20:57 -07001779void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001780{
Andy Hung068e08e2023-05-15 19:02:55 -07001781 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1782 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001783 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001784 (*it)->trigger();
1785 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001786 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001787 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001788 }
1789 }
1790}
1791
1792// implement VolumeBufferProvider interface
1793
Andy Hung8d31fd22023-06-26 19:20:57 -07001794gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001795{
1796 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1797 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001798 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1799 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1800 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001801 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001802 if (vl > GAIN_FLOAT_UNITY) {
1803 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001804 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001805 if (vr > GAIN_FLOAT_UNITY) {
1806 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001807 }
1808 // now apply the cached master volume and stream type volume;
1809 // this is trusted but lacks any synchronization or barrier so may be stale
1810 float v = mCachedVolume;
1811 vl *= v;
1812 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001813 // re-combine into packed minifloat
1814 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001815 // FIXME look at mute, pause, and stop flags
1816 return vlr;
1817}
1818
Andy Hung8d31fd22023-06-26 19:20:57 -07001819status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001820 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001821{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001822 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001823 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1824 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001825 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1826 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001827 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001828 event->cancel();
1829 return INVALID_OPERATION;
1830 }
1831 (void) TrackBase::setSyncEvent(event);
1832 return NO_ERROR;
1833}
1834
Andy Hung8d31fd22023-06-26 19:20:57 -07001835void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001836{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001837 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001838 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001839}
1840
Andy Hung8d31fd22023-06-26 19:20:57 -07001841void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001842{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001843 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001844 signalClientFlag(CBLK_DISABLED);
1845}
1846
Andy Hung8d31fd22023-06-26 19:20:57 -07001847void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001848{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001849 // FIXME should use proxy, and needs work
1850 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001851 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001852 android_atomic_release_store(0x40000000, &cblk->mFutex);
1853 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001854 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001855}
1856
Andy Hung8d31fd22023-06-26 19:20:57 -07001857void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001858{
Andy Hung8d31fd22023-06-26 19:20:57 -07001859 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001860 if (thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001861 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurent59fe0102013-09-27 18:48:26 -07001862 Mutex::Autolock _l(t->mLock);
1863 t->broadcast_l();
1864 }
1865}
1866
Andy Hung8d31fd22023-06-26 19:20:57 -07001867status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001868{
1869 status_t status = INVALID_OPERATION;
1870 if (isOffloadedOrDirect()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001871 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001872 if (thread != nullptr) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001873 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001874 Mutex::Autolock _l(t->mLock);
1875 status = t->mOutput->stream->getDualMonoMode(mode);
1876 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1877 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1878 }
1879 }
1880 return status;
1881}
1882
Andy Hung8d31fd22023-06-26 19:20:57 -07001883status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001884{
1885 status_t status = INVALID_OPERATION;
1886 if (isOffloadedOrDirect()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001887 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001888 if (thread != nullptr) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001889 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001890 Mutex::Autolock lock(t->mLock);
1891 status = t->mOutput->stream->setDualMonoMode(mode);
1892 if (status == NO_ERROR) {
1893 mDualMonoMode = mode;
1894 }
1895 }
1896 }
1897 return status;
1898}
1899
Andy Hung8d31fd22023-06-26 19:20:57 -07001900status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001901{
1902 status_t status = INVALID_OPERATION;
1903 if (isOffloadedOrDirect()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001904 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001905 if (thread != nullptr) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001906 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001907 Mutex::Autolock lock(t->mLock);
1908 status = t->mOutput->stream->getAudioDescriptionMixLevel(leveldB);
1909 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1910 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1911 }
1912 }
1913 return status;
1914}
1915
Andy Hung8d31fd22023-06-26 19:20:57 -07001916status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001917{
1918 status_t status = INVALID_OPERATION;
1919 if (isOffloadedOrDirect()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001920 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001921 if (thread != nullptr) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001922 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001923 Mutex::Autolock lock(t->mLock);
1924 status = t->mOutput->stream->setAudioDescriptionMixLevel(leveldB);
1925 if (status == NO_ERROR) {
1926 mAudioDescriptionMixLevel = leveldB;
1927 }
1928 }
1929 }
1930 return status;
1931}
1932
Andy Hung8d31fd22023-06-26 19:20:57 -07001933status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001934 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001935{
1936 status_t status = INVALID_OPERATION;
1937 if (isOffloadedOrDirect()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001938 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001939 if (thread != nullptr) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001940 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001941 Mutex::Autolock lock(t->mLock);
1942 status = t->mOutput->stream->getPlaybackRateParameters(playbackRate);
1943 ALOGD_IF((status == NO_ERROR) &&
1944 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1945 "%s: playbackRate inconsistent", __func__);
1946 }
1947 }
1948 return status;
1949}
1950
Andy Hung8d31fd22023-06-26 19:20:57 -07001951status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001952 const audio_playback_rate_t& playbackRate)
1953{
1954 status_t status = INVALID_OPERATION;
1955 if (isOffloadedOrDirect()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001956 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001957 if (thread != nullptr) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001958 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001959 Mutex::Autolock lock(t->mLock);
1960 status = t->mOutput->stream->setPlaybackRateParameters(playbackRate);
1961 if (status == NO_ERROR) {
1962 mPlaybackRateParameters = playbackRate;
1963 }
1964 }
1965 }
1966 return status;
1967}
1968
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001969//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001970bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07001971 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001972 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001973 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001974 /* Resume is pending if track was stopping before pause was called */
1975 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07001976 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001977 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001978 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001979
1980 return false;
1981}
1982
1983//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001984void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07001985 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001986 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07001987 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001988
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001989 // Other possibility of pending resume is stopping_1 state
1990 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001991 // drain being called.
1992 if (mState == STOPPING_1) {
1993 mResumeToStopping = false;
1994 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001995}
Andy Hunge10393e2015-06-12 13:59:33 -07001996
1997//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001998void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08001999 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002000 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002001 // Make the kernel frametime available.
2002 const FrameTime ft{
2003 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2004 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2005 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2006 mKernelFrameTime.store(ft);
2007 if (!audio_is_linear_pcm(mFormat)) {
2008 return;
2009 }
2010
Andy Hung818e7a32016-02-16 18:08:07 -08002011 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002012 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002013
2014 // adjust server times and set drained state.
2015 //
2016 // Our timestamps are only updated when the track is on the Thread active list.
2017 // We need to ensure that tracks are not removed before full drain.
2018 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002019 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002020 bool checked = false;
2021 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2022 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2023 // Lookup the track frame corresponding to the sink frame position.
2024 if (local.mTimeNs[i] > 0) {
2025 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2026 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002027 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002028 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002029 checked = true;
2030 }
2031 }
Andy Hunge10393e2015-06-12 13:59:33 -07002032 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002033
Andy Hung93bb5732023-05-04 21:16:34 -07002034 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2035 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002036 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002037 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002038 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002039 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002040
2041 // Compute latency info.
2042 const bool useTrackTimestamp = !drained;
2043 const double latencyMs = useTrackTimestamp
2044 ? local.getOutputServerLatencyMs(sampleRate())
2045 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2046
2047 mServerLatencyFromTrack.store(useTrackTimestamp);
2048 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002049
Andy Hung62921122020-05-18 10:47:31 -07002050 if (mLogStartCountdown > 0
2051 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2052 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2053 {
2054 if (mLogStartCountdown > 1) {
2055 --mLogStartCountdown;
2056 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2057 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002058 // startup is the difference in times for the current timestamp and our start
2059 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002060 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002061 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002062 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2063 * 1e3 / mSampleRate;
2064 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2065 " localTime:%lld startTime:%lld"
2066 " localPosition:%lld startPosition:%lld",
2067 __func__, latencyMs, startUpMs,
2068 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002069 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002070 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002071 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002072 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002073 }
Andy Hung62921122020-05-18 10:47:31 -07002074 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002075 }
Andy Hunge10393e2015-06-12 13:59:33 -07002076}
2077
Andy Hung8d31fd22023-06-26 19:20:57 -07002078bool Track::AudioVibrationController::setMute(bool muted) {
2079 sp<AudioFlinger::ThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002080 if (thread != 0) {
2081 // Lock for updating mHapticPlaybackEnabled.
2082 Mutex::Autolock _l(thread->mLock);
Andy Hung8d31fd22023-06-26 19:20:57 -07002083 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
jiabin57303cc2018-12-18 15:45:57 -08002084 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
2085 && playbackThread->mHapticChannelCount > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002086 ALOGD("%s, haptic playback was %s for track %d",
2087 __func__, muted ? "muted" : "unmuted", mTrack->id());
2088 mTrack->setHapticPlaybackEnabled(!muted);
2089 return true;
jiabin57303cc2018-12-18 15:45:57 -08002090 }
2091 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002092 return false;
2093}
2094
Andy Hung8d31fd22023-06-26 19:20:57 -07002095binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002096 /*out*/ bool *ret) {
2097 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002098 return binder::Status::ok();
2099}
2100
Andy Hung8d31fd22023-06-26 19:20:57 -07002101binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002102 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002103 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002104 return binder::Status::ok();
2105}
2106
Eric Laurent81784c32012-11-19 14:55:58 -08002107// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002108#undef LOG_TAG
2109#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002110
Andy Hung8d31fd22023-06-26 19:20:57 -07002111/* static */
2112sp<IAfOutputTrack> IAfOutputTrack::create( // TODO(b/288339104) void*
2113 void* /* AudioFlinger::PlaybackThread */ playbackThread,
2114 void* /* AudioFlinger::DuplicatingThread */ sourceThread,
2115 uint32_t sampleRate,
2116 audio_format_t format,
2117 audio_channel_mask_t channelMask,
2118 size_t frameCount,
2119 const AttributionSourceState& attributionSource) {
2120 return sp<OutputTrack>::make(
2121 reinterpret_cast<AudioFlinger::PlaybackThread*>(playbackThread),
2122 reinterpret_cast<AudioFlinger::DuplicatingThread*>(sourceThread),
2123 sampleRate,
2124 format,
2125 channelMask,
2126 frameCount,
2127 attributionSource);
2128}
2129
2130OutputTrack::OutputTrack(
2131 AudioFlinger::PlaybackThread *playbackThread,
2132 AudioFlinger::DuplicatingThread *sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002133 uint32_t sampleRate,
2134 audio_format_t format,
2135 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002136 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002137 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002138 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002139 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002140 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002141 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002142 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002143 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002144 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002145{
2146
2147 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002148 mOutBuffer.frameCount = 0;
2149 playbackThread->mTracks.add(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002150 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002151 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002152 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002153 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002154 // since client and server are in the same process,
2155 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002156 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2157 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002158 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002159 mClientProxy->setSendLevel(0.0);
2160 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002161 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002162 ALOGW("%s(%d): Error creating output track on thread %d",
2163 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002164 }
2165}
2166
Andy Hung8d31fd22023-06-26 19:20:57 -07002167OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002168{
2169 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002170 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002171}
2172
Andy Hung8d31fd22023-06-26 19:20:57 -07002173status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002174 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002175{
2176 status_t status = Track::start(event, triggerSession);
2177 if (status != NO_ERROR) {
2178 return status;
2179 }
2180
2181 mActive = true;
2182 mRetryCount = 127;
2183 return status;
2184}
2185
Andy Hung8d31fd22023-06-26 19:20:57 -07002186void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002187{
2188 Track::stop();
2189 clearBufferQueue();
2190 mOutBuffer.frameCount = 0;
2191 mActive = false;
2192}
2193
Andy Hung8d31fd22023-06-26 19:20:57 -07002194ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002195{
Eric Laurent19952e12023-04-20 10:08:29 +02002196 if (!mActive && frames != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07002197 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002198 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002199 // preload one silent buffer to trigger mixer on start()
2200 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2201 status_t status = mClientProxy->obtainBuffer(&buf);
2202 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2203 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2204 return 0;
2205 }
2206 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2207 mClientProxy->releaseBuffer(&buf);
2208
2209 (void) start();
2210
2211 // wait for HAL stream to start before sending actual audio. Doing this on each
2212 // OutputTrack makes that playback start on all output streams is synchronized.
2213 // If another OutputTrack has already started it can underrun but this is OK
2214 // as only silence has been played so far and the retry count is very high on
2215 // OutputTrack.
Andy Hung8d31fd22023-06-26 19:20:57 -07002216 auto* const pt = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurent19952e12023-04-20 10:08:29 +02002217 if (!pt->waitForHalStart()) {
2218 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2219 stop();
2220 return 0;
2221 }
2222
2223 // enqueue the first buffer and exit so that other OutputTracks will also start before
2224 // write() is called again and this buffer actually consumed.
2225 Buffer firstBuffer;
2226 firstBuffer.frameCount = frames;
2227 firstBuffer.raw = data;
2228 queueBuffer(firstBuffer);
2229 return frames;
2230 } else {
2231 (void) start();
2232 }
2233 }
2234
Eric Laurent81784c32012-11-19 14:55:58 -08002235 Buffer *pInBuffer;
2236 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002237 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002238 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002239 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002240 while (waitTimeLeftMs) {
2241 // First write pending buffers, then new data
2242 if (mBufferQueue.size()) {
2243 pInBuffer = mBufferQueue.itemAt(0);
2244 } else {
2245 pInBuffer = &inBuffer;
2246 }
2247
2248 if (pInBuffer->frameCount == 0) {
2249 break;
2250 }
2251
2252 if (mOutBuffer.frameCount == 0) {
2253 mOutBuffer.frameCount = pInBuffer->frameCount;
2254 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002255 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002256 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002257 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2258 __func__, mId,
2259 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002260 break;
2261 }
2262 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2263 if (waitTimeLeftMs >= waitTimeMs) {
2264 waitTimeLeftMs -= waitTimeMs;
2265 } else {
2266 waitTimeLeftMs = 0;
2267 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002268 if (status == NOT_ENOUGH_DATA) {
2269 restartIfDisabled();
2270 continue;
2271 }
Eric Laurent81784c32012-11-19 14:55:58 -08002272 }
2273
2274 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2275 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002276 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002277 Proxy::Buffer buf;
2278 buf.mFrameCount = outFrames;
2279 buf.mRaw = NULL;
2280 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002281 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002282 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002283 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002284 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002285 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002286
2287 if (pInBuffer->frameCount == 0) {
2288 if (mBufferQueue.size()) {
2289 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002290 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002291 if (pInBuffer != &inBuffer) {
2292 delete pInBuffer;
2293 }
Andy Hung9d84af52018-09-12 18:03:44 -07002294 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2295 __func__, mId,
2296 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002297 } else {
2298 break;
2299 }
2300 }
2301 }
2302
2303 // If we could not write all frames, allocate a buffer and queue it for next time.
2304 if (inBuffer.frameCount) {
Andy Hung8d31fd22023-06-26 19:20:57 -07002305 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002306 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002307 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002308 }
2309 }
2310
Andy Hungc25b84a2015-01-14 19:04:10 -08002311 // Calling write() with a 0 length buffer means that no more data will be written:
2312 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2313 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2314 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002315 }
2316
Andy Hung1c86ebe2018-05-29 20:29:08 -07002317 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002318}
2319
Andy Hung8d31fd22023-06-26 19:20:57 -07002320void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002321
2322 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2323 Buffer *pInBuffer = new Buffer;
2324 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2325 pInBuffer->mBuffer = malloc(bufferSize);
2326 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2327 "%s: Unable to malloc size %zu", __func__, bufferSize);
2328 pInBuffer->frameCount = inBuffer.frameCount;
2329 pInBuffer->raw = pInBuffer->mBuffer;
2330 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2331 mBufferQueue.add(pInBuffer);
2332 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2333 (int)mThreadIoHandle, mBufferQueue.size());
2334 // audio data is consumed (stored locally); set frameCount to 0.
2335 inBuffer.frameCount = 0;
2336 } else {
2337 ALOGW("%s(%d): thread %d no more overflow buffers",
2338 __func__, mId, (int)mThreadIoHandle);
2339 // TODO: return error for this.
2340 }
2341}
2342
Andy Hung8d31fd22023-06-26 19:20:57 -07002343void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002344{
2345 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2346 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2347}
2348
Andy Hung8d31fd22023-06-26 19:20:57 -07002349void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002350 {
2351 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2352 mTrackMetadatas = metadatas;
2353 }
2354 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2355 setMetadataHasChanged();
2356}
2357
Andy Hung8d31fd22023-06-26 19:20:57 -07002358status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002359 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2360{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002361 ClientProxy::Buffer buf;
2362 buf.mFrameCount = buffer->frameCount;
2363 struct timespec timeout;
2364 timeout.tv_sec = waitTimeMs / 1000;
2365 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2366 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2367 buffer->frameCount = buf.mFrameCount;
2368 buffer->raw = buf.mRaw;
2369 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002370}
2371
Andy Hung8d31fd22023-06-26 19:20:57 -07002372void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002373{
2374 size_t size = mBufferQueue.size();
2375
2376 for (size_t i = 0; i < size; i++) {
2377 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002378 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002379 delete pBuffer;
2380 }
2381 mBufferQueue.clear();
2382}
2383
Andy Hung8d31fd22023-06-26 19:20:57 -07002384void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002385{
2386 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2387 if (mActive && (flags & CBLK_DISABLED)) {
2388 start();
2389 }
2390}
Eric Laurent81784c32012-11-19 14:55:58 -08002391
Andy Hung9d84af52018-09-12 18:03:44 -07002392// ----------------------------------------------------------------------------
2393#undef LOG_TAG
2394#define LOG_TAG "AF::PatchTrack"
2395
Andy Hung8d31fd22023-06-26 19:20:57 -07002396/* static */
2397sp<IAfPatchTrack> IAfPatchTrack::create(
2398 void* /* PlaybackThread */ playbackThread, // TODO(b/288339104)
2399 audio_stream_type_t streamType,
2400 uint32_t sampleRate,
2401 audio_channel_mask_t channelMask,
2402 audio_format_t format,
2403 size_t frameCount,
2404 void* buffer,
2405 size_t bufferSize,
2406 audio_output_flags_t flags,
2407 const Timeout& timeout,
2408 size_t frameCountToBeReady /** Default behaviour is to start
2409 * as soon as possible to have
2410 * the lowest possible latency
2411 * even if it might glitch. */)
2412{
2413 return sp<PatchTrack>::make(
2414 reinterpret_cast<AudioFlinger::PlaybackThread*>(playbackThread),
2415 streamType,
2416 sampleRate,
2417 channelMask,
2418 format,
2419 frameCount,
2420 buffer,
2421 bufferSize,
2422 flags,
2423 timeout,
2424 frameCountToBeReady);
2425}
2426
2427PatchTrack::PatchTrack(AudioFlinger::PlaybackThread *playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002428 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002429 uint32_t sampleRate,
2430 audio_channel_mask_t channelMask,
2431 audio_format_t format,
2432 size_t frameCount,
2433 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002434 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002435 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002436 const Timeout& timeout,
2437 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002438 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002439 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002440 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002441 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002442 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002443 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002444 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2445 : nullptr,
Kevin Rocard45986c72018-12-18 18:22:59 -08002446 *playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002447{
Andy Hung9d84af52018-09-12 18:03:44 -07002448 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2449 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002450 (int)mPeerTimeout.tv_sec,
2451 (int)(mPeerTimeout.tv_nsec / 1000000));
2452}
2453
Andy Hung8d31fd22023-06-26 19:20:57 -07002454PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002455{
Andy Hungabfab202019-03-07 19:45:54 -08002456 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002457}
2458
Andy Hung8d31fd22023-06-26 19:20:57 -07002459size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002460{
2461 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2462 return std::numeric_limits<size_t>::max();
2463 } else {
2464 return Track::framesReady();
2465 }
2466}
2467
Andy Hung8d31fd22023-06-26 19:20:57 -07002468status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002469 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002470{
2471 status_t status = Track::start(event, triggerSession);
2472 if (status != NO_ERROR) {
2473 return status;
2474 }
2475 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2476 return status;
2477}
2478
Eric Laurent83b88082014-06-20 18:31:16 -07002479// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002480status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002481 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002482{
Andy Hung9d84af52018-09-12 18:03:44 -07002483 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002484 Proxy::Buffer buf;
2485 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002486 if (ATRACE_ENABLED()) {
2487 std::string traceName("PTnReq");
2488 traceName += std::to_string(id());
2489 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2490 }
Eric Laurent83b88082014-06-20 18:31:16 -07002491 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002492 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002493 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002494 if (ATRACE_ENABLED()) {
2495 std::string traceName("PTnObt");
2496 traceName += std::to_string(id());
2497 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2498 }
Eric Laurent83b88082014-06-20 18:31:16 -07002499 if (buf.mFrameCount == 0) {
2500 return WOULD_BLOCK;
2501 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002502 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002503 return status;
2504}
2505
Andy Hung8d31fd22023-06-26 19:20:57 -07002506void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002507{
Andy Hung9d84af52018-09-12 18:03:44 -07002508 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002509 Proxy::Buffer buf;
2510 buf.mFrameCount = buffer->frameCount;
2511 buf.mRaw = buffer->raw;
2512 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002513 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002514}
2515
Andy Hung8d31fd22023-06-26 19:20:57 -07002516status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002517 const struct timespec *timeOut)
2518{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002519 status_t status = NO_ERROR;
2520 static const int32_t kMaxTries = 5;
2521 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002522 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002523 do {
2524 if (status == NOT_ENOUGH_DATA) {
2525 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002526 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002527 }
2528 status = mProxy->obtainBuffer(buffer, timeOut);
2529 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2530 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002531}
2532
Andy Hung8d31fd22023-06-26 19:20:57 -07002533void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002534{
2535 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002536 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002537
2538 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2539 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2540 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2541 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002542 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002543 && audio_is_linear_pcm(mFormat)
2544 && !isOffloadedOrDirect()) {
Andy Hung8d31fd22023-06-26 19:20:57 -07002545 if (sp<AudioFlinger::ThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002546 thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07002547 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
naoki miyazuf37f9982019-11-28 11:18:18 +09002548 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2549 / playbackThread->sampleRate();
2550 if (framesReady() < frameCount) {
2551 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002552 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002553 }
2554 }
2555 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002556}
2557
Andy Hung8d31fd22023-06-26 19:20:57 -07002558void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002559{
Eric Laurent83b88082014-06-20 18:31:16 -07002560 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002561 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002562 start();
2563 }
Eric Laurent83b88082014-06-20 18:31:16 -07002564}
2565
Eric Laurent81784c32012-11-19 14:55:58 -08002566// ----------------------------------------------------------------------------
2567// Record
2568// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002569
2570
Andy Hung9d84af52018-09-12 18:03:44 -07002571#undef LOG_TAG
2572#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002573
Andy Hunga5a7fc92023-06-23 19:27:19 -07002574class RecordHandle : public android::media::BnAudioRecord {
2575public:
Andy Hungd29af632023-06-23 19:27:19 -07002576 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002577 ~RecordHandle() override;
2578 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2579 int /*audio_session_t*/ triggerSession) final;
2580 binder::Status stop() final;
2581 binder::Status getActiveMicrophones(
2582 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2583 binder::Status setPreferredMicrophoneDirection(
2584 int /*audio_microphone_direction_t*/ direction) final;
2585 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2586 binder::Status shareAudioHistory(
2587 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2588
2589private:
Andy Hungd29af632023-06-23 19:27:19 -07002590 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002591
2592 // for use from destructor
2593 void stop_nonvirtual();
2594};
2595
2596/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002597sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2598 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002599 return sp<RecordHandle>::make(recordTrack);
2600}
2601
2602RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002603 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002604 : BnAudioRecord(),
2605 mRecordTrack(recordTrack)
2606{
Andy Hunga5a7fc92023-06-23 19:27:19 -07002607 // TODO(b/288339104) binder thread priority change not needed.
Andy Hung225aef62022-12-06 16:33:20 -08002608 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002609}
2610
Andy Hunga5a7fc92023-06-23 19:27:19 -07002611RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002612 stop_nonvirtual();
2613 mRecordTrack->destroy();
2614}
2615
Andy Hunga5a7fc92023-06-23 19:27:19 -07002616binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002617 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002618 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002619 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002620 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002621}
2622
Andy Hunga5a7fc92023-06-23 19:27:19 -07002623binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002624 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002625 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002626}
2627
Andy Hunga5a7fc92023-06-23 19:27:19 -07002628void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002629 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002630 mRecordTrack->stop();
2631}
2632
Andy Hunga5a7fc92023-06-23 19:27:19 -07002633binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002634 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002635 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002636 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002637}
2638
Andy Hunga5a7fc92023-06-23 19:27:19 -07002639binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002640 int /*audio_microphone_direction_t*/ direction) {
2641 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002642 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002643 static_cast<audio_microphone_direction_t>(direction)));
2644}
2645
Andy Hunga5a7fc92023-06-23 19:27:19 -07002646binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002647 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002648 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002649}
2650
Andy Hunga5a7fc92023-06-23 19:27:19 -07002651binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002652 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2653 return binderStatusFromStatusT(
2654 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2655}
2656
Eric Laurent81784c32012-11-19 14:55:58 -08002657// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002658#undef LOG_TAG
2659#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002660
Andy Hung8d31fd22023-06-26 19:20:57 -07002661
2662/* static */ // TODO(b/288339104)
2663sp<IAfRecordTrack> IAfRecordTrack::create(void* /*AudioFlinger::RecordThread */ thread,
2664 const sp<Client>& client,
2665 const audio_attributes_t& attr,
2666 uint32_t sampleRate,
2667 audio_format_t format,
2668 audio_channel_mask_t channelMask,
2669 size_t frameCount,
2670 void* buffer,
2671 size_t bufferSize,
2672 audio_session_t sessionId,
2673 pid_t creatorPid,
2674 const AttributionSourceState& attributionSource,
2675 audio_input_flags_t flags,
2676 track_type type,
2677 audio_port_handle_t portId,
2678 int32_t startFrames)
2679{
2680 return sp<RecordTrack>::make(
2681 reinterpret_cast<AudioFlinger::RecordThread*>(thread),
2682 client,
2683 attr,
2684 sampleRate,
2685 format,
2686 channelMask,
2687 frameCount,
2688 buffer,
2689 bufferSize,
2690 sessionId,
2691 creatorPid,
2692 attributionSource,
2693 flags,
2694 type,
2695 portId,
2696 startFrames);
2697}
2698
Glenn Kasten05997e22014-03-13 15:08:33 -07002699// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002700RecordTrack::RecordTrack(
2701 AudioFlinger::RecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002702 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002703 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002704 uint32_t sampleRate,
2705 audio_format_t format,
2706 audio_channel_mask_t channelMask,
2707 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002708 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002709 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002710 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002711 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002712 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002713 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002714 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002715 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002716 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002717 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002718 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002719 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002720 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002721 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002722 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002723 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002724 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002725 type, portId,
2726 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002727 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002728 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002729 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002730 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002731 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002732 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002733{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002734 if (mCblk == NULL) {
2735 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002736 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002737
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002738 if (!isDirect()) {
2739 mRecordBufferConverter = new RecordBufferConverter(
2740 thread->mChannelMask, thread->mFormat, thread->mSampleRate,
2741 channelMask, format, sampleRate);
2742 // Check if the RecordBufferConverter construction was successful.
2743 // If not, don't continue with construction.
2744 //
2745 // NOTE: It would be extremely rare that the record track cannot be created
2746 // for the current device, but a pending or future device change would make
2747 // the record track configuration valid.
2748 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002749 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002750 return;
2751 }
Andy Hung97a893e2015-03-29 01:03:07 -07002752 }
2753
Andy Hung6ae58432016-02-16 18:32:24 -08002754 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002755 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002756
Andy Hung97a893e2015-03-29 01:03:07 -07002757 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002758
Eric Laurent05067782016-06-01 18:27:28 -07002759 if (flags & AUDIO_INPUT_FLAG_FAST) {
Glenn Kastenc263ca02014-06-04 20:31:46 -07002760 ALOG_ASSERT(thread->mFastTrackAvail);
2761 thread->mFastTrackAvail = false;
Andy Hung000adb52018-06-01 15:43:26 -07002762 } else {
2763 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002764 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002765 }
Andy Hung8946a282018-04-19 20:04:56 -07002766#ifdef TEE_SINK
2767 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2768 + "_" + std::to_string(mId)
2769 + "_R");
2770#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002771
2772 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002773 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002774}
2775
Andy Hung8d31fd22023-06-26 19:20:57 -07002776RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002777{
Andy Hung9d84af52018-09-12 18:03:44 -07002778 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002779 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002780 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002781}
2782
Andy Hung8d31fd22023-06-26 19:20:57 -07002783status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002784{
2785 status_t status = TrackBase::initCheck();
2786 if (status == NO_ERROR && mServerProxy == 0) {
2787 status = BAD_VALUE;
2788 }
2789 return status;
2790}
2791
Eric Laurent81784c32012-11-19 14:55:58 -08002792// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002793status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002794{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002795 ServerProxy::Buffer buf;
2796 buf.mFrameCount = buffer->frameCount;
2797 status_t status = mServerProxy->obtainBuffer(&buf);
2798 buffer->frameCount = buf.mFrameCount;
2799 buffer->raw = buf.mRaw;
2800 if (buf.mFrameCount == 0) {
2801 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002802 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002803 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002804 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002805}
2806
Andy Hung8d31fd22023-06-26 19:20:57 -07002807status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002808 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002809{
Andy Hung8d31fd22023-06-26 19:20:57 -07002810 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002811 if (thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07002812 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Eric Laurent81784c32012-11-19 14:55:58 -08002813 return recordThread->start(this, event, triggerSession);
2814 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002815 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2816 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002817 }
2818}
2819
Andy Hung8d31fd22023-06-26 19:20:57 -07002820void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002821{
Andy Hung8d31fd22023-06-26 19:20:57 -07002822 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002823 if (thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07002824 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Eric Laurent83b88082014-06-20 18:31:16 -07002825 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002826 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002827 }
2828 }
2829}
2830
Andy Hung8d31fd22023-06-26 19:20:57 -07002831void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002832{
Andy Hung8d31fd22023-06-26 19:20:57 -07002833 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002834 sp<RecordTrack> keep(this);
2835 {
Andy Hungce685402018-10-05 17:23:27 -07002836 track_state priorState = mState;
Andy Hung8d31fd22023-06-26 19:20:57 -07002837 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002838 if (thread != 0) {
Eric Laurent81784c32012-11-19 14:55:58 -08002839 Mutex::Autolock _l(thread->mLock);
Andy Hung8d31fd22023-06-26 19:20:57 -07002840 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Andy Hungce685402018-10-05 17:23:27 -07002841 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002842 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002843 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002844 }
Andy Hungce685402018-10-05 17:23:27 -07002845 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2846 }
2847 // APM portid/client management done outside of lock.
2848 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2849 if (isExternalTrack()) {
2850 switch (priorState) {
2851 case ACTIVE: // invalidated while still active
2852 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2853 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2854 AudioSystem::stopInput(mPortId);
2855 break;
2856
2857 case STARTING_1: // invalidated/start-aborted and startInput not successful
2858 case PAUSED: // OK, not active
2859 case IDLE: // OK, not active
2860 break;
2861
2862 case STOPPED: // unexpected (destroyed)
2863 default:
2864 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2865 }
2866 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002867 }
2868 }
2869}
2870
Andy Hung8d31fd22023-06-26 19:20:57 -07002871void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002872{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002873 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002874 // FIXME should use proxy, and needs work
2875 audio_track_cblk_t* cblk = mCblk;
2876 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2877 android_atomic_release_store(0x40000000, &cblk->mFutex);
2878 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002879 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002880}
2881
Eric Laurent81784c32012-11-19 14:55:58 -08002882
Andy Hung8d31fd22023-06-26 19:20:57 -07002883void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002884{
Eric Laurent973db022018-11-20 14:54:31 -08002885 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002886 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002887 " Server FrmCnt FrmRdy Sil%s\n",
2888 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002889}
2890
Andy Hung8d31fd22023-06-26 19:20:57 -07002891void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002892{
Eric Laurent973db022018-11-20 14:54:31 -08002893 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002894 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002895 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002896 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002897 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002898 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002899 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002900 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002901 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002902 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002903 mCblk->mFlags,
2904
Eric Laurent81784c32012-11-19 14:55:58 -08002905 mFormat,
2906 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002907 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002908 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002909
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002910 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002911 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002912 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002913 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002914 );
Andy Hung000adb52018-06-01 15:43:26 -07002915 if (isServerLatencySupported()) {
2916 double latencyMs;
2917 bool fromTrack;
2918 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2919 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2920 // or 'k' if estimated from kernel (usually for debugging).
2921 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2922 } else {
2923 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2924 }
2925 }
2926 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002927}
2928
Andy Hung93bb5732023-05-04 21:16:34 -07002929// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002930void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002931 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002932{
Andy Hung93bb5732023-05-04 21:16:34 -07002933 size_t framesToDrop = 0;
Andy Hung8d31fd22023-06-26 19:20:57 -07002934 sp<AudioFlinger::ThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002935 if (threadBase != 0) {
2936 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2937 // from audio HAL
2938 framesToDrop = threadBase->mFrameCount * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002939 }
Andy Hung93bb5732023-05-04 21:16:34 -07002940
2941 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002942}
2943
Andy Hung8d31fd22023-06-26 19:20:57 -07002944void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002945{
Andy Hung93bb5732023-05-04 21:16:34 -07002946 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002947}
2948
Andy Hung8d31fd22023-06-26 19:20:57 -07002949void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002950 int64_t trackFramesReleased, int64_t sourceFramesRead,
2951 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2952{
Andy Hung30282562018-08-08 18:27:03 -07002953 // Make the kernel frametime available.
2954 const FrameTime ft{
2955 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2956 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2957 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2958 mKernelFrameTime.store(ft);
2959 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002960 // Stream is direct, return provided timestamp with no conversion
2961 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002962 return;
2963 }
2964
Andy Hung3f0c9022016-01-15 17:49:46 -08002965 ExtendedTimestamp local = timestamp;
2966
2967 // Convert HAL frames to server-side track frames at track sample rate.
2968 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2969 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2970 if (local.mTimeNs[i] != 0) {
2971 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2972 const int64_t relativeTrackFrames = relativeServerFrames
2973 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2974 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2975 }
2976 }
Andy Hung6ae58432016-02-16 18:32:24 -08002977 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002978
2979 // Compute latency info.
2980 const bool useTrackTimestamp = true; // use track unless debugging.
2981 const double latencyMs = - (useTrackTimestamp
2982 ? local.getOutputServerLatencyMs(sampleRate())
2983 : timestamp.getOutputServerLatencyMs(halSampleRate));
2984
2985 mServerLatencyFromTrack.store(useTrackTimestamp);
2986 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08002987}
Eric Laurent83b88082014-06-20 18:31:16 -07002988
Andy Hung8d31fd22023-06-26 19:20:57 -07002989status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07002990 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08002991{
Andy Hung8d31fd22023-06-26 19:20:57 -07002992 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08002993 if (thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07002994 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
jiabin653cc0a2018-01-17 17:54:10 -08002995 return recordThread->getActiveMicrophones(activeMicrophones);
2996 } else {
2997 return BAD_VALUE;
2998 }
2999}
3000
Andy Hung8d31fd22023-06-26 19:20:57 -07003001status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003002 audio_microphone_direction_t direction) {
Andy Hung8d31fd22023-06-26 19:20:57 -07003003 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003004 if (thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07003005 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Paul McLean12340082019-03-19 09:35:05 -06003006 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003007 } else {
3008 return BAD_VALUE;
3009 }
3010}
3011
Andy Hung8d31fd22023-06-26 19:20:57 -07003012status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
3013 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003014 if (thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07003015 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Paul McLean12340082019-03-19 09:35:05 -06003016 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003017 } else {
3018 return BAD_VALUE;
3019 }
3020}
3021
Andy Hung8d31fd22023-06-26 19:20:57 -07003022status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003023 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3024
3025 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3026 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3027 if (callingUid != mUid || callingPid != mCreatorPid) {
3028 return PERMISSION_DENIED;
3029 }
3030
Svet Ganov33761132021-05-13 22:51:08 +00003031 AttributionSourceState attributionSource{};
3032 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3033 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3034 attributionSource.token = sp<BBinder>::make();
3035 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003036 return PERMISSION_DENIED;
3037 }
3038
Andy Hung8d31fd22023-06-26 19:20:57 -07003039 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003040 if (thread != 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07003041 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Eric Laurentec376dc2021-04-08 20:41:22 +02003042 status_t status = recordThread->shareAudioHistory(
3043 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3044 if (status == NO_ERROR) {
3045 mSharedAudioPackageName = sharedAudioPackageName;
3046 }
3047 return status;
3048 } else {
3049 return BAD_VALUE;
3050 }
3051}
3052
Andy Hung8d31fd22023-06-26 19:20:57 -07003053void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003054{
3055
3056 // Do not forward PatchRecord metadata with unspecified audio source
3057 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3058 return;
3059 }
3060
3061 // No track is invalid as this is called after prepareTrack_l in the same critical section
3062 record_track_metadata_v7_t metadata;
3063 metadata.base = {
3064 .source = mAttr.source,
3065 .gain = 1, // capture tracks do not have volumes
3066 };
3067 metadata.channel_mask = mChannelMask;
3068 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3069
3070 *backInserter++ = metadata;
3071}
Eric Laurentec376dc2021-04-08 20:41:22 +02003072
Andy Hung9d84af52018-09-12 18:03:44 -07003073// ----------------------------------------------------------------------------
3074#undef LOG_TAG
3075#define LOG_TAG "AF::PatchRecord"
3076
Andy Hung8d31fd22023-06-26 19:20:57 -07003077/* static */
3078sp<IAfPatchRecord> IAfPatchRecord::create(
3079 void* /* RecordThread */ recordThread, // TODO(b/288339104)
3080 uint32_t sampleRate,
3081 audio_channel_mask_t channelMask,
3082 audio_format_t format,
3083 size_t frameCount,
3084 void *buffer,
3085 size_t bufferSize,
3086 audio_input_flags_t flags,
3087 const Timeout& timeout,
3088 audio_source_t source)
3089{
3090 return sp<PatchRecord>::make(
3091 reinterpret_cast<AudioFlinger::RecordThread*>(recordThread),
3092 sampleRate,
3093 channelMask,
3094 format,
3095 frameCount,
3096 buffer,
3097 bufferSize,
3098 flags,
3099 timeout,
3100 source);
3101}
3102
3103PatchRecord::PatchRecord(AudioFlinger::RecordThread *recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003104 uint32_t sampleRate,
3105 audio_channel_mask_t channelMask,
3106 audio_format_t format,
3107 size_t frameCount,
3108 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003109 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003110 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003111 const Timeout& timeout,
3112 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003113 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003114 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003115 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003116 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003117 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003118 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3119 : nullptr,
Kevin Rocard45986c72018-12-18 18:22:59 -08003120 *recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003121{
Andy Hung9d84af52018-09-12 18:03:44 -07003122 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3123 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003124 (int)mPeerTimeout.tv_sec,
3125 (int)(mPeerTimeout.tv_nsec / 1000000));
3126}
3127
Andy Hung8d31fd22023-06-26 19:20:57 -07003128PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003129{
Andy Hungabfab202019-03-07 19:45:54 -08003130 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003131}
3132
Mikhail Naganov8296c252019-09-25 14:59:54 -07003133static size_t writeFramesHelper(
3134 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3135{
3136 AudioBufferProvider::Buffer patchBuffer;
3137 patchBuffer.frameCount = frameCount;
3138 auto status = dest->getNextBuffer(&patchBuffer);
3139 if (status != NO_ERROR) {
3140 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3141 __func__, status, strerror(-status));
3142 return 0;
3143 }
3144 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3145 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3146 size_t framesWritten = patchBuffer.frameCount;
3147 dest->releaseBuffer(&patchBuffer);
3148 return framesWritten;
3149}
3150
3151// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003152size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003153 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3154{
3155 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3156 // On buffer wrap, the buffer frame count will be less than requested,
3157 // when this happens a second buffer needs to be used to write the leftover audio
3158 const size_t framesLeft = frameCount - framesWritten;
3159 if (framesWritten != 0 && framesLeft != 0) {
3160 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3161 framesLeft, frameSize);
3162 }
3163 return framesWritten;
3164}
3165
Eric Laurent83b88082014-06-20 18:31:16 -07003166// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003167status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003168 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003169{
Andy Hung9d84af52018-09-12 18:03:44 -07003170 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003171 Proxy::Buffer buf;
3172 buf.mFrameCount = buffer->frameCount;
3173 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3174 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003175 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003176 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003177 if (ATRACE_ENABLED()) {
3178 std::string traceName("PRnObt");
3179 traceName += std::to_string(id());
3180 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3181 }
Eric Laurent83b88082014-06-20 18:31:16 -07003182 if (buf.mFrameCount == 0) {
3183 return WOULD_BLOCK;
3184 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003185 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003186 return status;
3187}
3188
Andy Hung8d31fd22023-06-26 19:20:57 -07003189void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003190{
Andy Hung9d84af52018-09-12 18:03:44 -07003191 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003192 Proxy::Buffer buf;
3193 buf.mFrameCount = buffer->frameCount;
3194 buf.mRaw = buffer->raw;
3195 mPeerProxy->releaseBuffer(&buf);
3196 TrackBase::releaseBuffer(buffer);
3197}
3198
Andy Hung8d31fd22023-06-26 19:20:57 -07003199status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003200 const struct timespec *timeOut)
3201{
3202 return mProxy->obtainBuffer(buffer, timeOut);
3203}
3204
Andy Hung8d31fd22023-06-26 19:20:57 -07003205void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003206{
3207 mProxy->releaseBuffer(buffer);
3208}
3209
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003210#undef LOG_TAG
3211#define LOG_TAG "AF::PthrPatchRecord"
3212
3213static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3214{
3215 void *ptr = nullptr;
3216 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003217 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003218}
3219
Andy Hung8d31fd22023-06-26 19:20:57 -07003220/* static */
3221sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
3222 void* /* RecordThread */ recordThread, // TODO(b/288339104)
3223 uint32_t sampleRate,
3224 audio_channel_mask_t channelMask,
3225 audio_format_t format,
3226 size_t frameCount,
3227 audio_input_flags_t flags,
3228 audio_source_t source)
3229{
3230 return sp<PassthruPatchRecord>::make(
3231 reinterpret_cast<AudioFlinger::RecordThread*>(recordThread),
3232 sampleRate,
3233 channelMask,
3234 format,
3235 frameCount,
3236 flags,
3237 source);
3238}
3239
3240PassthruPatchRecord::PassthruPatchRecord(
3241 AudioFlinger::RecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003242 uint32_t sampleRate,
3243 audio_channel_mask_t channelMask,
3244 audio_format_t format,
3245 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003246 audio_input_flags_t flags,
3247 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003248 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003249 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003250 mPatchRecordAudioBufferProvider(*this),
3251 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3252 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3253{
3254 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3255}
3256
Andy Hung8d31fd22023-06-26 19:20:57 -07003257sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
3258 sp<AudioFlinger::ThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003259{
3260 *thread = mThread.promote();
3261 if (!*thread) return nullptr;
Andy Hung8d31fd22023-06-26 19:20:57 -07003262 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>((*thread).get());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003263 Mutex::Autolock _l(recordThread->mLock);
3264 return recordThread->mInput ? recordThread->mInput->stream : nullptr;
3265}
3266
3267// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003268status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003269 Proxy::Buffer* buffer, const struct timespec* timeOut)
3270{
3271 if (mUnconsumedFrames) {
3272 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3273 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3274 return PatchRecord::obtainBuffer(buffer, timeOut);
3275 }
3276
3277 // Otherwise, execute a read from HAL and write into the buffer.
3278 nsecs_t startTimeNs = 0;
3279 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3280 // Will need to correct timeOut by elapsed time.
3281 startTimeNs = systemTime();
3282 }
3283 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3284 buffer->mFrameCount = 0;
3285 buffer->mRaw = nullptr;
Andy Hung8d31fd22023-06-26 19:20:57 -07003286 sp<AudioFlinger::ThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003287 sp<StreamInHalInterface> stream = obtainStream(&thread);
3288 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3289
3290 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003291 size_t bytesRead = 0;
3292 {
3293 ATRACE_NAME("read");
3294 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3295 if (result != NO_ERROR) goto stream_error;
3296 if (bytesRead == 0) return NO_ERROR;
3297 }
3298
3299 {
3300 std::lock_guard<std::mutex> lock(mReadLock);
3301 mReadBytes += bytesRead;
3302 mReadError = NO_ERROR;
3303 }
3304 mReadCV.notify_one();
3305 // writeFrames handles wraparound and should write all the provided frames.
3306 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3307 buffer->mFrameCount = writeFrames(
3308 &mPatchRecordAudioBufferProvider,
3309 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3310 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3311 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3312 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003313 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003314 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003315 // Correct the timeout by elapsed time.
3316 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003317 if (newTimeOutNs < 0) newTimeOutNs = 0;
3318 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3319 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003320 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003321 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003322 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003323
3324stream_error:
3325 stream->standby();
3326 {
3327 std::lock_guard<std::mutex> lock(mReadLock);
3328 mReadError = result;
3329 }
3330 mReadCV.notify_one();
3331 return result;
3332}
3333
Andy Hung8d31fd22023-06-26 19:20:57 -07003334void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003335{
3336 if (buffer->mFrameCount <= mUnconsumedFrames) {
3337 mUnconsumedFrames -= buffer->mFrameCount;
3338 } else {
3339 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3340 buffer->mFrameCount, mUnconsumedFrames);
3341 mUnconsumedFrames = 0;
3342 }
3343 PatchRecord::releaseBuffer(buffer);
3344}
3345
3346// AudioBufferProvider and Source methods are called on RecordThread
3347// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3348// and 'releaseBuffer' are stubbed out and ignore their input.
3349// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3350// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003351status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003352 void* buffer, size_t bytes, size_t* read)
3353{
3354 bytes = std::min(bytes, mFrameCount * mFrameSize);
3355 {
3356 std::unique_lock<std::mutex> lock(mReadLock);
3357 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3358 if (mReadError != NO_ERROR) {
3359 mLastReadFrames = 0;
3360 return mReadError;
3361 }
3362 *read = std::min(bytes, mReadBytes);
3363 mReadBytes -= *read;
3364 }
3365 mLastReadFrames = *read / mFrameSize;
3366 memset(buffer, 0, *read);
3367 return 0;
3368}
3369
Andy Hung8d31fd22023-06-26 19:20:57 -07003370status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003371 int64_t* frames, int64_t* time)
3372{
Andy Hung8d31fd22023-06-26 19:20:57 -07003373 sp<AudioFlinger::ThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003374 sp<StreamInHalInterface> stream = obtainStream(&thread);
3375 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3376}
3377
Andy Hung8d31fd22023-06-26 19:20:57 -07003378status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003379{
3380 // RecordThread issues 'standby' command in two major cases:
3381 // 1. Error on read--this case is handled in 'obtainBuffer'.
3382 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3383 // output, this can only happen when the software patch
3384 // is being torn down. In this case, the RecordThread
3385 // will terminate and close the HAL stream.
3386 return 0;
3387}
3388
3389// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003390status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003391 AudioBufferProvider::Buffer* buffer)
3392{
3393 buffer->frameCount = mLastReadFrames;
3394 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3395 return NO_ERROR;
3396}
3397
Andy Hung8d31fd22023-06-26 19:20:57 -07003398void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003399 AudioBufferProvider::Buffer* buffer)
3400{
3401 buffer->frameCount = 0;
3402 buffer->raw = nullptr;
3403}
3404
Andy Hung9d84af52018-09-12 18:03:44 -07003405// ----------------------------------------------------------------------------
3406#undef LOG_TAG
3407#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003408
Andy Hung8d31fd22023-06-26 19:20:57 -07003409/* static */
3410sp<IAfMmapTrack> IAfMmapTrack::create(void* /* AudioFlinger::ThreadBase */ thread,
3411 const audio_attributes_t& attr,
3412 uint32_t sampleRate,
3413 audio_format_t format,
3414 audio_channel_mask_t channelMask,
3415 audio_session_t sessionId,
3416 bool isOut,
3417 const android::content::AttributionSourceState& attributionSource,
3418 pid_t creatorPid,
3419 audio_port_handle_t portId)
3420{
3421 return sp<MmapTrack>::make(
3422 reinterpret_cast<AudioFlinger::ThreadBase*>(thread),
3423 attr,
3424 sampleRate,
3425 format,
3426 channelMask,
3427 sessionId,
3428 isOut,
3429 attributionSource,
3430 creatorPid,
3431 portId);
3432}
3433
3434MmapTrack::MmapTrack(AudioFlinger::ThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003435 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003436 uint32_t sampleRate,
3437 audio_format_t format,
3438 audio_channel_mask_t channelMask,
3439 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003440 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003441 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003442 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003443 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003444 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003445 channelMask, (size_t)0 /* frameCount */,
3446 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003447 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003448 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003449 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003450 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003451 TYPE_DEFAULT, portId,
3452 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003453 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003454 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003455{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003456 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003457 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003458}
3459
Andy Hung8d31fd22023-06-26 19:20:57 -07003460MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003461{
3462}
3463
Andy Hung8d31fd22023-06-26 19:20:57 -07003464status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003465{
3466 return NO_ERROR;
3467}
3468
Andy Hung8d31fd22023-06-26 19:20:57 -07003469status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003470 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003471{
3472 return NO_ERROR;
3473}
3474
Andy Hung8d31fd22023-06-26 19:20:57 -07003475void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003476{
3477}
3478
3479// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003480status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003481{
3482 buffer->frameCount = 0;
3483 buffer->raw = nullptr;
3484 return INVALID_OPERATION;
3485}
3486
3487// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003488size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003489 return 0;
3490}
3491
Andy Hung8d31fd22023-06-26 19:20:57 -07003492int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003493{
3494 return 0;
3495}
3496
Andy Hung8d31fd22023-06-26 19:20:57 -07003497void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003498{
3499}
3500
Andy Hung8d31fd22023-06-26 19:20:57 -07003501void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003502{
3503 if (mMuteState == muteState) {
3504 // mute state did not change, do nothing
3505 return;
3506 }
3507
3508 status_t result = UNKNOWN_ERROR;
3509 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3510 if (mMuteEventExtras == nullptr) {
3511 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3512 }
3513 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3514 static_cast<int>(muteState));
3515
3516 result = audioManager->portEvent(mPortId,
3517 PLAYER_UPDATE_MUTED,
3518 mMuteEventExtras);
3519 }
3520
3521 if (result == OK) {
3522 mMuteState = muteState;
3523 } else {
3524 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3525 __func__,
3526 id(),
3527 mPortId,
3528 result);
3529 }
3530}
3531
Andy Hung8d31fd22023-06-26 19:20:57 -07003532void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003533{
Eric Laurent973db022018-11-20 14:54:31 -08003534 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003535 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003536}
3537
Andy Hung8d31fd22023-06-26 19:20:57 -07003538void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003539{
Eric Laurent973db022018-11-20 14:54:31 -08003540 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003541 mPid,
3542 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003543 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003544 mFormat,
3545 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003546 mSampleRate,
3547 mAttr.flags);
3548 if (isOut()) {
3549 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3550 } else {
3551 result.appendFormat("%6x", mAttr.source);
3552 }
3553 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003554}
3555
Glenn Kasten63238ef2015-03-02 15:50:29 -08003556} // namespace android