blob: 093c14a1e1bd5929a655fa52fb82adcc02700399 [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 Hung3ff4b552023-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 Hung3ff4b552023-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 Hung02a6c4e2023-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 Hung3ff4b552023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung3ff4b552023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
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 Hung3ff4b552023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung3ff4b552023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung3ff4b552023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
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 Hung3ff4b552023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hungaaa18282023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hungaaa18282023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hungaaa18282023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hungaaa18282023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hung02a6c4e2023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-06-23 19:27:19 -0700497Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-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 Hungaaa18282023-06-23 19:27:19 -0700510Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-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 Hungaaa18282023-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 Hungaaa18282023-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 Hungaaa18282023-06-23 19:27:19 -0700534Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-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 Hungaaa18282023-06-23 19:27:19 -0700547Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-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 Hung3ff4b552023-06-26 19:20:57 -0700561sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Vlad Popa103be862023-07-10 20:27:41 -0700562 AudioFlinger::ThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000563 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700564 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800565{
Vlad Popa103be862023-07-10 20:27:41 -0700566 Vector<String16> packages;
567 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000568 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700569 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700570 if (packages.isEmpty()) {
571 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
572 id,
573 attr.usage,
574 uid);
575 return nullptr;
576 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800577 }
578 // stream type has been filtered by audio policy to indicate whether it can be muted
579 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700580 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700581 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800582 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700583 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
584 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
585 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
586 id, attr.flags);
587 return nullptr;
588 }
Vlad Popa103be862023-07-10 20:27:41 -0700589 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700590}
591
Andy Hung3ff4b552023-06-26 19:20:57 -0700592OpPlayAudioMonitor::OpPlayAudioMonitor(
Vlad Popa103be862023-07-10 20:27:41 -0700593 AudioFlinger::ThreadBase* thread,
594 const AttributionSourceState& attributionSource,
595 audio_usage_t usage, int id, uid_t uid)
596 : mThread(wp<AudioFlinger::ThreadBase>::fromExisting(thread)),
597 mHasOpPlayAudio(true),
598 mAttributionSource(attributionSource),
599 mUsage((int32_t)usage),
600 mId(id),
601 mUid(uid),
602 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
603 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800604
Andy Hung3ff4b552023-06-26 19:20:57 -0700605OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800606{
607 if (mOpCallback != 0) {
608 mAppOpsManager.stopWatchingMode(mOpCallback);
609 }
610 mOpCallback.clear();
611}
612
Andy Hung3ff4b552023-06-26 19:20:57 -0700613void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700614{
Vlad Popad2152122023-08-02 18:36:04 -0700615 // make sure not to broadcast the initial state since it is not needed and could
616 // cause a deadlock since this method can be called with the mThread->mLock held
617 checkPlayAudioForUsage(/*doBroadcast=*/false);
Svet Ganov33761132021-05-13 22:51:08 +0000618 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700619 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700620 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Vlad Popa103be862023-07-10 20:27:41 -0700621 mPackageName, mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700622 }
623}
624
Andy Hung3ff4b552023-06-26 19:20:57 -0700625bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800626 return mHasOpPlayAudio.load();
627}
628
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700629// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800630// - not called from constructor due to check on UID,
631// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung3ff4b552023-06-26 19:20:57 -0700632void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800633{
Vlad Popa103be862023-07-10 20:27:41 -0700634 const bool hasAppOps = mAttributionSource.packageName.has_value()
635 && mAppOpsManager.checkAudioOpNoThrow(
636 AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
637 AppOpsManager::MODE_ALLOWED;
638
639 bool shouldChange = !hasAppOps; // check if we need to update.
640 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
641 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
Vlad Popad2152122023-08-02 18:36:04 -0700642 if (doBroadcast) {
643 auto thread = mThread.promote();
644 if (thread != nullptr && thread->type() == AudioFlinger::ThreadBase::OFFLOAD) {
645 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
646 Mutex::Autolock _l(thread->mLock);
647 thread->broadcast_l();
648 }
Vlad Popa103be862023-07-10 20:27:41 -0700649 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800650 }
651}
652
Andy Hung3ff4b552023-06-26 19:20:57 -0700653OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800654 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
655{ }
656
Andy Hung3ff4b552023-06-26 19:20:57 -0700657void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800658 const String16& packageName) {
659 // we only have uid, so we need to check all package names anyway
660 UNUSED(packageName);
661 if (op != AppOpsManager::OP_PLAY_AUDIO) {
662 return;
663 }
664 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
665 if (monitor != NULL) {
Vlad Popad2152122023-08-02 18:36:04 -0700666 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800667 }
668}
669
Eric Laurent9066ad32019-05-20 14:40:10 -0700670// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700671void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700672 uid_t uid, Vector<String16>& packages)
673{
674 PermissionController permissionController;
675 permissionController.getPackagesForUid(uid, packages);
676}
677
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800678// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700679#undef LOG_TAG
680#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800681
Andy Hung3ff4b552023-06-26 19:20:57 -0700682/* static */
683sp<IAfTrack> IAfTrack::create( // TODO(b/288339104) void*
684 void * /* AudioFlinger::PlaybackThread */ thread,
685 const sp<Client>& client,
686 audio_stream_type_t streamType,
687 const audio_attributes_t& attr,
688 uint32_t sampleRate,
689 audio_format_t format,
690 audio_channel_mask_t channelMask,
691 size_t frameCount,
692 void *buffer,
693 size_t bufferSize,
694 const sp<IMemory>& sharedBuffer,
695 audio_session_t sessionId,
696 pid_t creatorPid,
697 const AttributionSourceState& attributionSource,
698 audio_output_flags_t flags,
699 track_type type,
700 audio_port_handle_t portId,
701 /** default behaviour is to start when there are as many frames
702 * ready as possible (aka. Buffer is full). */
703 size_t frameCountToBeReady,
704 float speed,
705 bool isSpatialized,
706 bool isBitPerfect) {
707 return sp<Track>::make(reinterpret_cast<AudioFlinger::PlaybackThread*>(thread),
708 client,
709 streamType,
710 attr,
711 sampleRate,
712 format,
713 channelMask,
714 frameCount,
715 buffer,
716 bufferSize,
717 sharedBuffer,
718 sessionId,
719 creatorPid,
720 attributionSource,
721 flags,
722 type,
723 portId,
724 frameCountToBeReady,
725 speed,
726 isSpatialized,
727 isBitPerfect);
728}
729
Eric Laurent81784c32012-11-19 14:55:58 -0800730// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -0700731Track::Track(
732 AudioFlinger::PlaybackThread *thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800733 const sp<Client>& client,
734 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700735 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800736 uint32_t sampleRate,
737 audio_format_t format,
738 audio_channel_mask_t channelMask,
739 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700740 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700741 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800742 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800743 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700744 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000745 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700746 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800747 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100748 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000749 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200750 float speed,
jiabinc658e452022-10-21 20:52:21 +0000751 bool isSpatialized,
752 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700753 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700754 // TODO: Using unsecurePointer() has some associated security pitfalls
755 // (see declaration for details).
756 // Either document why it is safe in this case or address the
757 // issue (e.g. by copying).
758 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700759 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700760 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000761 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700762 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800763 type,
764 portId,
765 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung3ff4b552023-06-26 19:20:57 -0700766 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800767 // mRetryCount initialized later when needed
768 mSharedBuffer(sharedBuffer),
769 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700770 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800771 mAuxBuffer(NULL),
772 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700773 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700774 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa103be862023-07-10 20:27:41 -0700775 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700776 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700777 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800778 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800779 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700780 /* The track might not play immediately after being active, similarly as if its volume was 0.
781 * When the track starts playing, its volume will be computed. */
782 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800783 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700784 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000785 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200786 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000787 mIsSpatialized(isSpatialized),
788 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800789{
Eric Laurent83b88082014-06-20 18:31:16 -0700790 // client == 0 implies sharedBuffer == 0
791 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
792
Andy Hung9d84af52018-09-12 18:03:44 -0700793 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700794 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700795
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700796 if (mCblk == NULL) {
797 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800798 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700799
Svet Ganov33761132021-05-13 22:51:08 +0000800 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700801 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
802 ALOGE("%s(%d): no more tracks available", __func__, mId);
803 releaseCblk(); // this makes the track invalid.
804 return;
805 }
806
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700807 if (sharedBuffer == 0) {
808 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700809 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700810 } else {
811 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100812 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700813 }
814 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700815 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700816
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700817 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700818 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700819 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
820 // race with setSyncEvent(). However, if we call it, we cannot properly start
821 // static fast tracks (SoundPool) immediately after stopping.
822 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700823 ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
824 int i = __builtin_ctz(thread->mFastTrackAvailMask);
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700825 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700826 // FIXME This is too eager. We allocate a fast track index before the
827 // fast track becomes active. Since fast tracks are a scarce resource,
828 // this means we are potentially denying other more important fast tracks from
829 // being created. It would be better to allocate the index dynamically.
830 mFastIndex = i;
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700831 thread->mFastTrackAvailMask &= ~(1 << i);
832 }
Andy Hung8946a282018-04-19 20:04:56 -0700833
Dean Wheatley7b036912020-06-18 16:22:11 +1000834 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700835#ifdef TEE_SINK
836 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800837 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700838#endif
jiabin57303cc2018-12-18 15:45:57 -0800839
jiabineb3bda02020-06-30 14:07:03 -0700840 if (thread->supportsHapticPlayback()) {
841 // If the track is attached to haptic playback thread, it is potentially to have
842 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
843 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800844 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000845 std::string packageName = attributionSource.packageName.has_value() ?
846 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800847 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700848 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800849 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800850
851 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700852 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800853 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800854}
855
Andy Hung3ff4b552023-06-26 19:20:57 -0700856Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800857{
Andy Hung9d84af52018-09-12 18:03:44 -0700858 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700859
860 // The destructor would clear mSharedBuffer,
861 // but it will not push the decremented reference count,
862 // leaving the client's IMemory dangling indefinitely.
863 // This prevents that leak.
864 if (mSharedBuffer != 0) {
865 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700866 }
Eric Laurent81784c32012-11-19 14:55:58 -0800867}
868
Andy Hung3ff4b552023-06-26 19:20:57 -0700869status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700870{
871 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700872 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700873 status = NO_MEMORY;
874 }
875 return status;
876}
877
Andy Hung3ff4b552023-06-26 19:20:57 -0700878void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800879{
880 // NOTE: destroyTrack_l() can remove a strong reference to this Track
881 // by removing it from mTracks vector, so there is a risk that this Tracks's
882 // destructor is called. As the destructor needs to lock mLock,
883 // we must acquire a strong reference on this Track before locking mLock
884 // here so that the destructor is called only when exiting this function.
885 // On the other hand, as long as Track::destroy() is only called by
886 // TrackHandle destructor, the TrackHandle still holds a strong ref on
887 // this Track with its member mTrack.
888 sp<Track> keep(this);
889 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700890 bool wasActive = false;
Andy Hung3ff4b552023-06-26 19:20:57 -0700891 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800892 if (thread != 0) {
Eric Laurent81784c32012-11-19 14:55:58 -0800893 Mutex::Autolock _l(thread->mLock);
Andy Hung3ff4b552023-06-26 19:20:57 -0700894 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurentaaa44472014-09-12 17:41:50 -0700895 wasActive = playbackThread->destroyTrack_l(this);
896 }
897 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700898 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800899 }
900 }
Kevin Rocardc43ea142019-01-31 18:17:37 -0800901 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
Eric Laurent81784c32012-11-19 14:55:58 -0800902}
903
Andy Hung3ff4b552023-06-26 19:20:57 -0700904void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800905{
Eric Laurent973db022018-11-20 14:54:31 -0800906 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700907 " Format Chn mask SRate "
908 "ST Usg CT "
909 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000910 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700911 "%s\n",
912 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800913}
914
Andy Hung3ff4b552023-06-26 19:20:57 -0700915void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800916{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700917 char trackType;
918 switch (mType) {
919 case TYPE_DEFAULT:
920 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700921 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700922 trackType = 'S'; // static
923 } else {
924 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800925 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700926 break;
927 case TYPE_PATCH:
928 trackType = 'P';
929 break;
930 default:
931 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800932 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700933
934 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700935 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700936 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700937 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700938 }
939
Eric Laurent81784c32012-11-19 14:55:58 -0800940 char nowInUnderrun;
941 switch (mObservedUnderruns.mBitFields.mMostRecent) {
942 case UNDERRUN_FULL:
943 nowInUnderrun = ' ';
944 break;
945 case UNDERRUN_PARTIAL:
946 nowInUnderrun = '<';
947 break;
948 case UNDERRUN_EMPTY:
949 nowInUnderrun = '*';
950 break;
951 default:
952 nowInUnderrun = '?';
953 break;
954 }
Andy Hungda540db2017-04-20 14:06:17 -0700955
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700956 char fillingStatus;
Andy Hung3ff4b552023-06-26 19:20:57 -0700957 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700958 case FS_INVALID:
959 fillingStatus = 'I';
960 break;
961 case FS_FILLING:
962 fillingStatus = 'f';
963 break;
964 case FS_FILLED:
965 fillingStatus = 'F';
966 break;
967 case FS_ACTIVE:
968 fillingStatus = 'A';
969 break;
970 default:
971 fillingStatus = '?';
972 break;
973 }
974
975 // clip framesReadySafe to max representation in dump
976 const size_t framesReadySafe =
977 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
978
979 // obtain volumes
980 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
981 const std::pair<float /* volume */, bool /* active */> vsVolume =
982 mVolumeHandler->getLastVolume();
983
984 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
985 // as it may be reduced by the application.
986 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
987 // Check whether the buffer size has been modified by the app.
988 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
989 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
990 ? 'e' /* error */ : ' ' /* identical */;
991
Eric Laurent973db022018-11-20 14:54:31 -0800992 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700993 "%08X %08X %6u "
994 "%2u %3x %2x "
995 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000996 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800997 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700998 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700999 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001000 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001001 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001002 mCblk->mFlags,
1003
Eric Laurent81784c32012-11-19 14:55:58 -08001004 mFormat,
1005 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001006 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001007
1008 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001009 mAttr.usage,
1010 mAttr.content_type,
1011
1012 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001013 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1014 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001015 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1016 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001017
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001018 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001019 bufferSizeInFrames,
1020 modifiedBufferChar,
1021 framesReadySafe,
1022 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001023 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001024 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001025 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1026 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001027 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001028
1029 if (isServerLatencySupported()) {
1030 double latencyMs;
1031 bool fromTrack;
1032 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1033 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1034 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1035 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001036 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001037 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001038 }
1039 }
1040 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001041}
1042
Andy Hung3ff4b552023-06-26 19:20:57 -07001043uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001044 return mAudioTrackServerProxy->getSampleRate();
1045}
1046
Eric Laurent81784c32012-11-19 14:55:58 -08001047// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001048status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001049{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001050 ServerProxy::Buffer buf;
1051 size_t desiredFrames = buffer->frameCount;
1052 buf.mFrameCount = desiredFrames;
1053 status_t status = mServerProxy->obtainBuffer(&buf);
1054 buffer->frameCount = buf.mFrameCount;
1055 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001056 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001057 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001058 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001059 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001060 } else {
1061 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001062 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001063 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001064}
1065
Andy Hung3ff4b552023-06-26 19:20:57 -07001066void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001067{
1068 interceptBuffer(*buffer);
1069 TrackBase::releaseBuffer(buffer);
1070}
1071
1072// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001073void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001074 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001075 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001076 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001077 if (frameCount == 0) {
1078 return; // No audio to intercept.
1079 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1080 // does not allow 0 frame size request contrary to getNextBuffer
1081 }
1082 for (auto& teePatch : mTeePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001083 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001084 const size_t framesWritten = patchRecord->writeFrames(
1085 sourceBuffer.i8, frameCount, mFrameSize);
1086 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001087 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001088 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001089 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001090 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001091 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1092 using namespace std::chrono_literals;
1093 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001094 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001095 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001096}
1097
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001098// ExtendedAudioBufferProvider interface
1099
Andy Hung27876c02014-09-09 18:07:55 -07001100// framesReady() may return an approximation of the number of frames if called
1101// from a different thread than the one calling Proxy->obtainBuffer() and
1102// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1103// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001104size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001105 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1106 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1107 // The remainder of the buffer is not drained.
1108 return 0;
1109 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001110 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001111}
1112
Andy Hung3ff4b552023-06-26 19:20:57 -07001113int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001114{
1115 return mAudioTrackServerProxy->framesReleased();
1116}
1117
Andy Hung3ff4b552023-06-26 19:20:57 -07001118void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001119{
1120 // This call comes from a FastTrack and should be kept lockless.
1121 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001122 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001123
Andy Hung818e7a32016-02-16 18:08:07 -08001124 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001125
1126 // Compute latency.
1127 // TODO: Consider whether the server latency may be passed in by FastMixer
1128 // as a constant for all active FastTracks.
1129 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1130 mServerLatencyFromTrack.store(true);
1131 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001132}
1133
Eric Laurent81784c32012-11-19 14:55:58 -08001134// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001135bool Track::isReady() const {
1136 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001137 return true;
1138 }
1139
Eric Laurent16498512014-03-17 17:22:08 -07001140 if (isStopping()) {
1141 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001142 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001143 }
Eric Laurent81784c32012-11-19 14:55:58 -08001144 return true;
1145 }
1146
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001147 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001148 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1149 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1150 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1151 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001152
1153 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1154 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1155 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001156 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001157 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001158 return true;
1159 }
1160 return false;
1161}
1162
Andy Hung3ff4b552023-06-26 19:20:57 -07001163status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001164 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001165{
1166 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001167 ALOGV("%s(%d): calling pid %d session %d",
1168 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001169
Andy Hung3ff4b552023-06-26 19:20:57 -07001170 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001171 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001172 if (isOffloaded()) {
1173 Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
1174 Mutex::Autolock _lth(thread->mLock);
Andy Hungbd72c542023-06-20 18:56:17 -07001175 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Eric Laurent5baf2af2013-09-12 17:37:00 -07001176 if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
1177 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001178 invalidate();
1179 return PERMISSION_DENIED;
1180 }
1181 }
1182 Mutex::Autolock _lth(thread->mLock);
Eric Laurent81784c32012-11-19 14:55:58 -08001183 track_state state = mState;
1184 // here the track could be either new, or restarted
1185 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001186
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001187 // initial state-stopping. next state-pausing.
1188 // What if resume is called ?
1189
Zhou Song1ed46a22020-08-17 15:36:56 +08001190 if (state == FLUSHED) {
1191 // avoid underrun glitches when starting after flush
1192 reset();
1193 }
1194
kuowei.li576f1362021-05-11 18:02:32 +08001195 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1196 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001197 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001198 if (mResumeToStopping) {
1199 // happened we need to resume to STOPPING_1
1200 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001201 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1202 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001203 } else {
1204 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001205 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1206 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001207 }
Eric Laurent81784c32012-11-19 14:55:58 -08001208 } else {
1209 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001210 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1211 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001212 }
1213
Andy Hung3ff4b552023-06-26 19:20:57 -07001214 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
yucliu91503922022-07-20 17:40:39 -07001215
1216 // states to reset position info for pcm tracks
1217 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001218 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1219 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001220
1221 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1222 // Start point of track -> sink frame map. If the HAL returns a
1223 // frame position smaller than the first written frame in
1224 // updateTrackFrameInfo, the timestamp can be interpolated
1225 // instead of using a larger value.
1226 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1227 playbackThread->framesWritten());
1228 }
Andy Hunge10393e2015-06-12 13:59:33 -07001229 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001230 if (isFastTrack()) {
1231 // refresh fast track underruns on start because that field is never cleared
1232 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1233 // after stop.
1234 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1235 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001236 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001237 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001238 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001239 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001240 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001241 mState = state;
1242 }
1243 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001244
Andy Hungb68f5eb2019-12-03 16:49:17 -08001245 // Audio timing metrics are computed a few mix cycles after starting.
1246 {
1247 mLogStartCountdown = LOG_START_COUNTDOWN;
1248 mLogStartTimeNs = systemTime();
1249 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001250 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1251 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001252 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001253 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001254
Andy Hung1d3556d2018-03-29 16:30:14 -07001255 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1256 // for streaming tracks, remove the buffer read stop limit.
1257 mAudioTrackServerProxy->start();
1258 }
1259
Eric Laurentbfb1b832013-01-07 09:53:42 -08001260 // track was already in the active list, not a problem
1261 if (status == ALREADY_EXISTS) {
1262 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001263 } else {
1264 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1265 // It is usually unsafe to access the server proxy from a binder thread.
1266 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1267 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1268 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001269 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001270 ServerProxy::Buffer buffer;
1271 buffer.mFrameCount = 1;
1272 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001273 }
1274 } else {
1275 status = BAD_VALUE;
1276 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001277 if (status == NO_ERROR) {
1278 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001279
1280 // send format to AudioManager for playback activity monitoring
1281 sp<IAudioManager> audioManager = thread->mAudioFlinger->getOrCreateAudioManager();
1282 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1283 std::unique_ptr<os::PersistableBundle> bundle =
1284 std::make_unique<os::PersistableBundle>();
1285 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1286 isSpatialized());
1287 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1288 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1289 status_t result = audioManager->portEvent(mPortId,
1290 PLAYER_UPDATE_FORMAT, bundle);
1291 if (result != OK) {
1292 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1293 __func__, mPortId, result);
1294 }
1295 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001296 }
Eric Laurent81784c32012-11-19 14:55:58 -08001297 return status;
1298}
1299
Andy Hung3ff4b552023-06-26 19:20:57 -07001300void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001301{
Andy Hungc0691382018-09-12 18:01:57 -07001302 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung3ff4b552023-06-26 19:20:57 -07001303 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001304 if (thread != 0) {
1305 Mutex::Autolock _l(thread->mLock);
1306 track_state state = mState;
1307 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1308 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung3ff4b552023-06-26 19:20:57 -07001309 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurent81784c32012-11-19 14:55:58 -08001310 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
1311 reset();
1312 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001313 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001314 mState = STOPPED;
1315 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001316 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1317 // presentation is complete
1318 // For an offloaded track this starts a drain and state will
1319 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001320 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001321 if (isOffloaded()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001322 mRetryCount = AudioFlinger::PlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001323 }
Eric Laurent81784c32012-11-19 14:55:58 -08001324 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001325 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001326 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1327 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001328 }
Eric Laurent81784c32012-11-19 14:55:58 -08001329 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001330 forEachTeePatchTrack([](auto patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001331}
1332
Andy Hung3ff4b552023-06-26 19:20:57 -07001333void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001334{
Andy Hungc0691382018-09-12 18:01:57 -07001335 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung3ff4b552023-06-26 19:20:57 -07001336 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001337 if (thread != 0) {
1338 Mutex::Autolock _l(thread->mLock);
Andy Hung3ff4b552023-06-26 19:20:57 -07001339 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurentbfb1b832013-01-07 09:53:42 -08001340 switch (mState) {
1341 case STOPPING_1:
1342 case STOPPING_2:
1343 if (!isOffloaded()) {
1344 /* nothing to do if track is not offloaded */
1345 break;
1346 }
1347
1348 // Offloaded track was draining, we need to carry on draining when resumed
1349 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001350 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001351 case ACTIVE:
1352 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001353 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001354 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1355 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001356 if (isOffloadedOrDirect()) {
1357 mPauseHwPending = true;
1358 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001359 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001360 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001361
Eric Laurentbfb1b832013-01-07 09:53:42 -08001362 default:
1363 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001364 }
1365 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001366 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1367 forEachTeePatchTrack([](auto patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001368}
1369
Andy Hung3ff4b552023-06-26 19:20:57 -07001370void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001371{
Andy Hungc0691382018-09-12 18:01:57 -07001372 ALOGV("%s(%d)", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07001373 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001374 if (thread != 0) {
1375 Mutex::Autolock _l(thread->mLock);
Andy Hung3ff4b552023-06-26 19:20:57 -07001376 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurentbfb1b832013-01-07 09:53:42 -08001377
Phil Burk4bb650b2016-09-09 12:11:17 -07001378 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1379 // Otherwise the flush would not be done until the track is resumed.
1380 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
1381 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
1382 (void)mServerProxy->flushBufferIfNeeded();
1383 }
1384
Eric Laurentbfb1b832013-01-07 09:53:42 -08001385 if (isOffloaded()) {
1386 // If offloaded we allow flush during any state except terminated
1387 // and keep the track active to avoid problems if user is seeking
1388 // rapidly and underlying hardware has a significant delay handling
1389 // a pause
1390 if (isTerminated()) {
1391 return;
1392 }
1393
Andy Hung9d84af52018-09-12 18:03:44 -07001394 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001395 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001396
1397 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001398 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1399 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001400 mState = ACTIVE;
1401 }
1402
Haynes Mathew George7844f672014-01-15 12:32:55 -08001403 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001404 mResumeToStopping = false;
1405 } else {
1406 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1407 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1408 return;
1409 }
1410 // No point remaining in PAUSED state after a flush => go to
1411 // FLUSHED state
1412 mState = FLUSHED;
1413 // do not reset the track if it is still in the process of being stopped or paused.
1414 // this will be done by prepareTracks_l() when the track is stopped.
1415 // prepareTracks_l() will see mState == FLUSHED, then
1416 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001417 if (isDirect()) {
1418 mFlushHwPending = true;
1419 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001420 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
1421 reset();
1422 }
Eric Laurent81784c32012-11-19 14:55:58 -08001423 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001424 // Prevent flush being lost if the track is flushed and then resumed
1425 // before mixer thread can run. This is important when offloading
1426 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001427 playbackThread->broadcast_l();
Eric Laurent81784c32012-11-19 14:55:58 -08001428 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001429 // Flush the Tee to avoid on resume playing old data and glitching on the transition to new data
1430 forEachTeePatchTrack([](auto patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001431}
1432
Haynes Mathew George7844f672014-01-15 12:32:55 -08001433// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001434void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001435{
Andy Hung71ba4b32022-10-06 12:09:49 -07001436 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001437 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001438 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001439
Phil Burk4bb650b2016-09-09 12:11:17 -07001440 // Clear the client ring buffer so that the app can prime the buffer while paused.
1441 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1442 mServerProxy->flushBufferIfNeeded();
1443
Haynes Mathew George7844f672014-01-15 12:32:55 -08001444 mFlushHwPending = false;
1445}
1446
Andy Hung3ff4b552023-06-26 19:20:57 -07001447void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001448{
1449 mPauseHwPending = false;
1450}
1451
Andy Hung3ff4b552023-06-26 19:20:57 -07001452void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001453{
1454 // Do not reset twice to avoid discarding data written just after a flush and before
1455 // the audioflinger thread detects the track is stopped.
1456 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001457 // Force underrun condition to avoid false underrun callback until first data is
1458 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001459 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001460 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001461 mResetDone = true;
1462 if (mState == FLUSHED) {
1463 mState = IDLE;
1464 }
1465 }
1466}
1467
Andy Hung3ff4b552023-06-26 19:20:57 -07001468status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001469{
Andy Hung3ff4b552023-06-26 19:20:57 -07001470 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001471 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001472 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001473 return FAILED_TRANSACTION;
Andy Hung3ff4b552023-06-26 19:20:57 -07001474 } else if ((thread->type() == AudioFlinger::ThreadBase::DIRECT) ||
1475 (thread->type() == AudioFlinger::ThreadBase::OFFLOAD)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001476 return thread->setParameters(keyValuePairs);
1477 } else {
1478 return PERMISSION_DENIED;
1479 }
1480}
1481
Andy Hung3ff4b552023-06-26 19:20:57 -07001482status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001483 int programId) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001484 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001485 if (thread == 0) {
1486 ALOGE("thread is dead");
1487 return FAILED_TRANSACTION;
Andy Hung3ff4b552023-06-26 19:20:57 -07001488 } else if ((thread->type() == AudioFlinger::ThreadBase::DIRECT)
1489 || (thread->type() == AudioFlinger::ThreadBase::OFFLOAD)) {
1490 auto directOutputThread = static_cast<AudioFlinger::DirectOutputThread*>(thread.get());
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001491 return directOutputThread->selectPresentation(presentationId, programId);
1492 }
1493 return INVALID_OPERATION;
1494}
1495
Andy Hung3ff4b552023-06-26 19:20:57 -07001496VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001497 const sp<VolumeShaper::Configuration>& configuration,
1498 const sp<VolumeShaper::Operation>& operation)
1499{
Andy Hungee86cee2022-12-13 19:19:53 -08001500 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001501
1502 if (isOffloadedOrDirect()) {
1503 // Signal thread to fetch new volume.
Andy Hung3ff4b552023-06-26 19:20:57 -07001504 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001505 if (thread != 0) {
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001506 Mutex::Autolock _l(thread->mLock);
Andy Hung10cbff12017-02-21 17:30:14 -08001507 thread->broadcast_l();
1508 }
1509 }
1510 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001511}
1512
Andy Hung3ff4b552023-06-26 19:20:57 -07001513sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001514{
1515 // Note: We don't check if Thread exists.
1516
1517 // mVolumeHandler is thread safe.
1518 return mVolumeHandler->getVolumeShaperState(id);
1519}
1520
Andy Hung3ff4b552023-06-26 19:20:57 -07001521void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001522{
jiabin76d94692022-12-15 21:51:21 +00001523 mFinalVolumeLeft = volumeLeft;
1524 mFinalVolumeRight = volumeRight;
1525 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001526 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1527 mFinalVolume = volume;
1528 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001529 mLogForceVolumeUpdate = true;
1530 }
1531 if (mLogForceVolumeUpdate) {
1532 mLogForceVolumeUpdate = false;
1533 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001534 }
1535}
1536
Andy Hung3ff4b552023-06-26 19:20:57 -07001537void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001538{
Eric Laurent49e39282022-06-24 18:42:45 +02001539 // Do not forward metadata for PatchTrack with unspecified stream type
1540 if (mStreamType == AUDIO_STREAM_PATCH) {
1541 return;
1542 }
1543
Eric Laurent94579172020-11-20 18:41:04 +01001544 playback_track_metadata_v7_t metadata;
1545 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001546 .usage = mAttr.usage,
1547 .content_type = mAttr.content_type,
1548 .gain = mFinalVolume,
1549 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001550
1551 // When attributes are undefined, derive default values from stream type.
1552 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1553 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1554 switch (mStreamType) {
1555 case AUDIO_STREAM_VOICE_CALL:
1556 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1557 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1558 break;
1559 case AUDIO_STREAM_SYSTEM:
1560 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1561 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1562 break;
1563 case AUDIO_STREAM_RING:
1564 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1565 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1566 break;
1567 case AUDIO_STREAM_MUSIC:
1568 metadata.base.usage = AUDIO_USAGE_MEDIA;
1569 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1570 break;
1571 case AUDIO_STREAM_ALARM:
1572 metadata.base.usage = AUDIO_USAGE_ALARM;
1573 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1574 break;
1575 case AUDIO_STREAM_NOTIFICATION:
1576 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1577 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1578 break;
1579 case AUDIO_STREAM_DTMF:
1580 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1581 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1582 break;
1583 case AUDIO_STREAM_ACCESSIBILITY:
1584 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1585 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1586 break;
1587 case AUDIO_STREAM_ASSISTANT:
1588 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1589 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1590 break;
1591 case AUDIO_STREAM_REROUTING:
1592 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1593 // unknown content type
1594 break;
1595 case AUDIO_STREAM_CALL_ASSISTANT:
1596 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1597 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1598 break;
1599 default:
1600 break;
1601 }
1602 }
1603
Eric Laurent78b07302022-10-07 16:20:34 +02001604 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001605 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1606 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001607}
1608
Andy Hung3ff4b552023-06-26 19:20:57 -07001609void Track::updateTeePatches() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001610 if (mTeePatchesToUpdate.has_value()) {
1611 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
1612 mTeePatches = mTeePatchesToUpdate.value();
1613 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1614 mState == TrackBase::STOPPING_1) {
1615 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
1616 }
1617 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001618 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001619}
1620
Andy Hung3ff4b552023-06-26 19:20:57 -07001621void Track::setTeePatchesToUpdate(AudioFlinger::TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001622 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1623 "%s, existing tee patches to update will be ignored", __func__);
1624 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1625}
1626
Vlad Popae8d99472022-06-30 16:02:48 +02001627// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001628void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001629 IAudioManager>& audioManager, mute_state_t muteState)
1630{
1631 if (mMuteState == muteState) {
1632 // mute state did not change, do nothing
1633 return;
1634 }
1635
1636 status_t result = UNKNOWN_ERROR;
1637 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1638 if (mMuteEventExtras == nullptr) {
1639 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1640 }
1641 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1642 static_cast<int>(muteState));
1643
1644 result = audioManager->portEvent(mPortId,
1645 PLAYER_UPDATE_MUTED,
1646 mMuteEventExtras);
1647 }
1648
1649 if (result == OK) {
1650 mMuteState = muteState;
1651 } else {
1652 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1653 __func__,
1654 id(),
1655 mPortId,
1656 result);
Andy Hung818e7a32016-02-16 18:08:07 -08001657 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001658}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001659
Andy Hung3ff4b552023-06-26 19:20:57 -07001660status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001661{
1662 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001663 return INVALID_OPERATION; // normal tracks handled through SSQ
1664 }
Andy Hung3ff4b552023-06-26 19:20:57 -07001665 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001666 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001667 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001668 }
Phil Burk6140c792015-03-19 14:30:21 -07001669
Glenn Kasten573d80a2013-08-26 09:36:23 -07001670 Mutex::Autolock _l(thread->mLock);
Andy Hung3ff4b552023-06-26 19:20:57 -07001671 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Andy Hung818e7a32016-02-16 18:08:07 -08001672 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001673}
1674
Andy Hung3ff4b552023-06-26 19:20:57 -07001675status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001676{
Andy Hung3ff4b552023-06-26 19:20:57 -07001677 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001678 if (thread == nullptr) {
1679 return DEAD_OBJECT;
1680 }
Eric Laurent81784c32012-11-19 14:55:58 -08001681
Andy Hung3ff4b552023-06-26 19:20:57 -07001682 auto dstThread = sp<AudioFlinger::PlaybackThread>::cast(thread);
1683 // srcThread is initialized by call to moveAuxEffectToIo()
1684 sp<AudioFlinger::PlaybackThread> srcThread;
Eric Laurent6c796322019-04-09 14:13:17 -07001685 sp<AudioFlinger> af = mClient->audioFlinger();
1686 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001687
Eric Laurent6c796322019-04-09 14:13:17 -07001688 if (EffectId != 0 && status == NO_ERROR) {
1689 status = dstThread->attachAuxEffect(this, EffectId);
1690 if (status == NO_ERROR) {
1691 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001692 }
Eric Laurent6c796322019-04-09 14:13:17 -07001693 }
1694
1695 if (status != NO_ERROR && srcThread != nullptr) {
1696 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001697 }
1698 return status;
1699}
1700
Andy Hung3ff4b552023-06-26 19:20:57 -07001701void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001702{
1703 mAuxEffectId = EffectId;
1704 mAuxBuffer = buffer;
1705}
1706
Andy Hung59de4262021-06-14 10:53:54 -07001707// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001708bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001709 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001710{
Andy Hung818e7a32016-02-16 18:08:07 -08001711 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1712 // This assists in proper timestamp computation as well as wakelock management.
1713
Eric Laurent81784c32012-11-19 14:55:58 -08001714 // a track is considered presented when the total number of frames written to audio HAL
1715 // corresponds to the number of frames written when presentationComplete() is called for the
1716 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001717 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1718 // to detect when all frames have been played. In this case framesWritten isn't
1719 // useful because it doesn't always reflect whether there is data in the h/w
1720 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001721 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1722 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001723 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001724 if (mPresentationCompleteFrames == 0) {
1725 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001726 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001727 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1728 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001729 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001730 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001731
Andy Hungc54b1ff2016-02-23 14:07:07 -08001732 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001733 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001734 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001735 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1736 __func__, mId, (complete ? "complete" : "waiting"),
1737 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001738 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001739 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001740 && mAudioTrackServerProxy->isDrained();
1741 }
1742
1743 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001744 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001745 return true;
1746 }
1747 return false;
1748}
1749
Andy Hung59de4262021-06-14 10:53:54 -07001750// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001751bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001752{
1753 // For Offloaded or Direct tracks.
1754
1755 // For a direct track, we incorporated time based testing for presentationComplete.
1756
1757 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1758 // to detect when all frames have been played. In this case latencyMs isn't
1759 // useful because it doesn't always reflect whether there is data in the h/w
1760 // buffers, particularly if a track has been paused and resumed during draining
1761
1762 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1763 if (mPresentationCompleteTimeNs == 0) {
1764 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1765 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1766 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1767 }
1768
1769 bool complete;
1770 if (isOffloaded()) {
1771 complete = true;
1772 } else { // Direct
1773 complete = systemTime() >= mPresentationCompleteTimeNs;
1774 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1775 }
1776 if (complete) {
1777 notifyPresentationComplete();
1778 return true;
1779 }
1780 return false;
1781}
1782
Andy Hung3ff4b552023-06-26 19:20:57 -07001783void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001784{
1785 // This only triggers once. TODO: should we enforce this?
1786 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1787 mAudioTrackServerProxy->setStreamEndDone();
1788}
1789
Andy Hung3ff4b552023-06-26 19:20:57 -07001790void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001791{
Andy Hung068e08e2023-05-15 19:02:55 -07001792 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1793 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001794 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001795 (*it)->trigger();
1796 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001797 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001798 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001799 }
1800 }
1801}
1802
1803// implement VolumeBufferProvider interface
1804
Andy Hung3ff4b552023-06-26 19:20:57 -07001805gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001806{
1807 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1808 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001809 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1810 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1811 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001812 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001813 if (vl > GAIN_FLOAT_UNITY) {
1814 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001815 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001816 if (vr > GAIN_FLOAT_UNITY) {
1817 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001818 }
1819 // now apply the cached master volume and stream type volume;
1820 // this is trusted but lacks any synchronization or barrier so may be stale
1821 float v = mCachedVolume;
1822 vl *= v;
1823 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001824 // re-combine into packed minifloat
1825 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001826 // FIXME look at mute, pause, and stop flags
1827 return vlr;
1828}
1829
Andy Hung3ff4b552023-06-26 19:20:57 -07001830status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001831 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001832{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001833 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001834 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1835 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001836 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1837 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001838 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001839 event->cancel();
1840 return INVALID_OPERATION;
1841 }
1842 (void) TrackBase::setSyncEvent(event);
1843 return NO_ERROR;
1844}
1845
Andy Hung3ff4b552023-06-26 19:20:57 -07001846void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001847{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001848 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001849 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001850}
1851
Andy Hung3ff4b552023-06-26 19:20:57 -07001852void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001853{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001854 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001855 signalClientFlag(CBLK_DISABLED);
1856}
1857
Andy Hung3ff4b552023-06-26 19:20:57 -07001858void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001859{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001860 // FIXME should use proxy, and needs work
1861 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001862 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001863 android_atomic_release_store(0x40000000, &cblk->mFutex);
1864 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001865 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001866}
1867
Andy Hung3ff4b552023-06-26 19:20:57 -07001868void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001869{
Andy Hung3ff4b552023-06-26 19:20:57 -07001870 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001871 if (thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001872 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurent59fe0102013-09-27 18:48:26 -07001873 Mutex::Autolock _l(t->mLock);
1874 t->broadcast_l();
1875 }
1876}
1877
Andy Hung3ff4b552023-06-26 19:20:57 -07001878status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001879{
1880 status_t status = INVALID_OPERATION;
1881 if (isOffloadedOrDirect()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001882 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001883 if (thread != nullptr) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001884 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001885 Mutex::Autolock _l(t->mLock);
1886 status = t->mOutput->stream->getDualMonoMode(mode);
1887 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1888 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1889 }
1890 }
1891 return status;
1892}
1893
Andy Hung3ff4b552023-06-26 19:20:57 -07001894status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001895{
1896 status_t status = INVALID_OPERATION;
1897 if (isOffloadedOrDirect()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001898 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001899 if (thread != nullptr) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001900 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001901 Mutex::Autolock lock(t->mLock);
1902 status = t->mOutput->stream->setDualMonoMode(mode);
1903 if (status == NO_ERROR) {
1904 mDualMonoMode = mode;
1905 }
1906 }
1907 }
1908 return status;
1909}
1910
Andy Hung3ff4b552023-06-26 19:20:57 -07001911status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001912{
1913 status_t status = INVALID_OPERATION;
1914 if (isOffloadedOrDirect()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001915 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001916 if (thread != nullptr) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001917 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001918 Mutex::Autolock lock(t->mLock);
1919 status = t->mOutput->stream->getAudioDescriptionMixLevel(leveldB);
1920 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1921 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1922 }
1923 }
1924 return status;
1925}
1926
Andy Hung3ff4b552023-06-26 19:20:57 -07001927status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001928{
1929 status_t status = INVALID_OPERATION;
1930 if (isOffloadedOrDirect()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001931 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932 if (thread != nullptr) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001933 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001934 Mutex::Autolock lock(t->mLock);
1935 status = t->mOutput->stream->setAudioDescriptionMixLevel(leveldB);
1936 if (status == NO_ERROR) {
1937 mAudioDescriptionMixLevel = leveldB;
1938 }
1939 }
1940 }
1941 return status;
1942}
1943
Andy Hung3ff4b552023-06-26 19:20:57 -07001944status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001945 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001946{
1947 status_t status = INVALID_OPERATION;
1948 if (isOffloadedOrDirect()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001949 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001950 if (thread != nullptr) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001951 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001952 Mutex::Autolock lock(t->mLock);
1953 status = t->mOutput->stream->getPlaybackRateParameters(playbackRate);
1954 ALOGD_IF((status == NO_ERROR) &&
1955 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1956 "%s: playbackRate inconsistent", __func__);
1957 }
1958 }
1959 return status;
1960}
1961
Andy Hung3ff4b552023-06-26 19:20:57 -07001962status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001963 const audio_playback_rate_t& playbackRate)
1964{
1965 status_t status = INVALID_OPERATION;
1966 if (isOffloadedOrDirect()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001967 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001968 if (thread != nullptr) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001969 auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001970 Mutex::Autolock lock(t->mLock);
1971 status = t->mOutput->stream->setPlaybackRateParameters(playbackRate);
1972 if (status == NO_ERROR) {
1973 mPlaybackRateParameters = playbackRate;
1974 }
1975 }
1976 }
1977 return status;
1978}
1979
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001980//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001981bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07001982 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001983 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001984 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001985 /* Resume is pending if track was stopping before pause was called */
1986 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07001987 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001988 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001989 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001990
1991 return false;
1992}
1993
1994//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001995void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07001996 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001997 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07001998 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001999
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002000 // Other possibility of pending resume is stopping_1 state
2001 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002002 // drain being called.
2003 if (mState == STOPPING_1) {
2004 mResumeToStopping = false;
2005 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002006}
Andy Hunge10393e2015-06-12 13:59:33 -07002007
2008//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002009void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002010 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002011 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002012 // Make the kernel frametime available.
2013 const FrameTime ft{
2014 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2015 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2016 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2017 mKernelFrameTime.store(ft);
2018 if (!audio_is_linear_pcm(mFormat)) {
2019 return;
2020 }
2021
Andy Hung818e7a32016-02-16 18:08:07 -08002022 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002023 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002024
2025 // adjust server times and set drained state.
2026 //
2027 // Our timestamps are only updated when the track is on the Thread active list.
2028 // We need to ensure that tracks are not removed before full drain.
2029 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002030 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002031 bool checked = false;
2032 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2033 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2034 // Lookup the track frame corresponding to the sink frame position.
2035 if (local.mTimeNs[i] > 0) {
2036 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2037 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002038 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002039 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002040 checked = true;
2041 }
2042 }
Andy Hunge10393e2015-06-12 13:59:33 -07002043 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002044
Andy Hung93bb5732023-05-04 21:16:34 -07002045 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2046 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002047 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002048 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002049 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002050 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002051
2052 // Compute latency info.
2053 const bool useTrackTimestamp = !drained;
2054 const double latencyMs = useTrackTimestamp
2055 ? local.getOutputServerLatencyMs(sampleRate())
2056 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2057
2058 mServerLatencyFromTrack.store(useTrackTimestamp);
2059 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002060
Andy Hung62921122020-05-18 10:47:31 -07002061 if (mLogStartCountdown > 0
2062 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2063 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2064 {
2065 if (mLogStartCountdown > 1) {
2066 --mLogStartCountdown;
2067 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2068 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002069 // startup is the difference in times for the current timestamp and our start
2070 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002071 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002072 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002073 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2074 * 1e3 / mSampleRate;
2075 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2076 " localTime:%lld startTime:%lld"
2077 " localPosition:%lld startPosition:%lld",
2078 __func__, latencyMs, startUpMs,
2079 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002080 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002081 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002082 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002083 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002084 }
Andy Hung62921122020-05-18 10:47:31 -07002085 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002086 }
Andy Hunge10393e2015-06-12 13:59:33 -07002087}
2088
Andy Hung3ff4b552023-06-26 19:20:57 -07002089bool Track::AudioVibrationController::setMute(bool muted) {
2090 sp<AudioFlinger::ThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002091 if (thread != 0) {
2092 // Lock for updating mHapticPlaybackEnabled.
2093 Mutex::Autolock _l(thread->mLock);
Andy Hung3ff4b552023-06-26 19:20:57 -07002094 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
jiabin57303cc2018-12-18 15:45:57 -08002095 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
2096 && playbackThread->mHapticChannelCount > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002097 ALOGD("%s, haptic playback was %s for track %d",
2098 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002099 mTrack->setHapticPlaybackEnabled(!muted);
2100 return true;
jiabin57303cc2018-12-18 15:45:57 -08002101 }
2102 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002103 return false;
2104}
2105
Andy Hung3ff4b552023-06-26 19:20:57 -07002106binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002107 /*out*/ bool *ret) {
2108 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002109 return binder::Status::ok();
2110}
2111
Andy Hung3ff4b552023-06-26 19:20:57 -07002112binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002113 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002114 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002115 return binder::Status::ok();
2116}
2117
Eric Laurent81784c32012-11-19 14:55:58 -08002118// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002119#undef LOG_TAG
2120#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002121
Andy Hung3ff4b552023-06-26 19:20:57 -07002122/* static */
2123sp<IAfOutputTrack> IAfOutputTrack::create( // TODO(b/288339104) void*
2124 void* /* AudioFlinger::PlaybackThread */ playbackThread,
2125 void* /* AudioFlinger::DuplicatingThread */ sourceThread,
2126 uint32_t sampleRate,
2127 audio_format_t format,
2128 audio_channel_mask_t channelMask,
2129 size_t frameCount,
2130 const AttributionSourceState& attributionSource) {
2131 return sp<OutputTrack>::make(
2132 reinterpret_cast<AudioFlinger::PlaybackThread*>(playbackThread),
2133 reinterpret_cast<AudioFlinger::DuplicatingThread*>(sourceThread),
2134 sampleRate,
2135 format,
2136 channelMask,
2137 frameCount,
2138 attributionSource);
2139}
2140
2141OutputTrack::OutputTrack(
2142 AudioFlinger::PlaybackThread *playbackThread,
2143 AudioFlinger::DuplicatingThread *sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002144 uint32_t sampleRate,
2145 audio_format_t format,
2146 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002147 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002148 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002149 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002150 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002151 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002152 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002153 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002154 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002155 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002156{
2157
2158 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002159 mOutBuffer.frameCount = 0;
2160 playbackThread->mTracks.add(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002161 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002162 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002163 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002164 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002165 // since client and server are in the same process,
2166 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002167 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2168 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002169 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002170 mClientProxy->setSendLevel(0.0);
2171 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002172 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002173 ALOGW("%s(%d): Error creating output track on thread %d",
2174 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002175 }
2176}
2177
Andy Hung3ff4b552023-06-26 19:20:57 -07002178OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002179{
2180 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002181 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002182}
2183
Andy Hung3ff4b552023-06-26 19:20:57 -07002184status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002185 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002186{
2187 status_t status = Track::start(event, triggerSession);
2188 if (status != NO_ERROR) {
2189 return status;
2190 }
2191
2192 mActive = true;
2193 mRetryCount = 127;
2194 return status;
2195}
2196
Andy Hung3ff4b552023-06-26 19:20:57 -07002197void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002198{
2199 Track::stop();
2200 clearBufferQueue();
2201 mOutBuffer.frameCount = 0;
2202 mActive = false;
2203}
2204
Andy Hung3ff4b552023-06-26 19:20:57 -07002205ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002206{
Eric Laurent19952e12023-04-20 10:08:29 +02002207 if (!mActive && frames != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07002208 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002209 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002210 // preload one silent buffer to trigger mixer on start()
2211 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2212 status_t status = mClientProxy->obtainBuffer(&buf);
2213 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2214 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2215 return 0;
2216 }
2217 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2218 mClientProxy->releaseBuffer(&buf);
2219
2220 (void) start();
2221
2222 // wait for HAL stream to start before sending actual audio. Doing this on each
2223 // OutputTrack makes that playback start on all output streams is synchronized.
2224 // If another OutputTrack has already started it can underrun but this is OK
2225 // as only silence has been played so far and the retry count is very high on
2226 // OutputTrack.
Andy Hung3ff4b552023-06-26 19:20:57 -07002227 auto* const pt = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Eric Laurent19952e12023-04-20 10:08:29 +02002228 if (!pt->waitForHalStart()) {
2229 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2230 stop();
2231 return 0;
2232 }
2233
2234 // enqueue the first buffer and exit so that other OutputTracks will also start before
2235 // write() is called again and this buffer actually consumed.
2236 Buffer firstBuffer;
2237 firstBuffer.frameCount = frames;
2238 firstBuffer.raw = data;
2239 queueBuffer(firstBuffer);
2240 return frames;
2241 } else {
2242 (void) start();
2243 }
2244 }
2245
Eric Laurent81784c32012-11-19 14:55:58 -08002246 Buffer *pInBuffer;
2247 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002248 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002249 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002250 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002251 while (waitTimeLeftMs) {
2252 // First write pending buffers, then new data
2253 if (mBufferQueue.size()) {
2254 pInBuffer = mBufferQueue.itemAt(0);
2255 } else {
2256 pInBuffer = &inBuffer;
2257 }
2258
2259 if (pInBuffer->frameCount == 0) {
2260 break;
2261 }
2262
2263 if (mOutBuffer.frameCount == 0) {
2264 mOutBuffer.frameCount = pInBuffer->frameCount;
2265 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002266 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002267 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002268 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2269 __func__, mId,
2270 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002271 break;
2272 }
2273 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2274 if (waitTimeLeftMs >= waitTimeMs) {
2275 waitTimeLeftMs -= waitTimeMs;
2276 } else {
2277 waitTimeLeftMs = 0;
2278 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002279 if (status == NOT_ENOUGH_DATA) {
2280 restartIfDisabled();
2281 continue;
2282 }
Eric Laurent81784c32012-11-19 14:55:58 -08002283 }
2284
2285 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2286 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002287 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002288 Proxy::Buffer buf;
2289 buf.mFrameCount = outFrames;
2290 buf.mRaw = NULL;
2291 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002292 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002293 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002294 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002295 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002296 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002297
2298 if (pInBuffer->frameCount == 0) {
2299 if (mBufferQueue.size()) {
2300 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002301 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002302 if (pInBuffer != &inBuffer) {
2303 delete pInBuffer;
2304 }
Andy Hung9d84af52018-09-12 18:03:44 -07002305 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2306 __func__, mId,
2307 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002308 } else {
2309 break;
2310 }
2311 }
2312 }
2313
2314 // If we could not write all frames, allocate a buffer and queue it for next time.
2315 if (inBuffer.frameCount) {
Andy Hung3ff4b552023-06-26 19:20:57 -07002316 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002317 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002318 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002319 }
2320 }
2321
Andy Hungc25b84a2015-01-14 19:04:10 -08002322 // Calling write() with a 0 length buffer means that no more data will be written:
2323 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2324 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2325 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002326 }
2327
Andy Hung1c86ebe2018-05-29 20:29:08 -07002328 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002329}
2330
Andy Hung3ff4b552023-06-26 19:20:57 -07002331void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002332
2333 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2334 Buffer *pInBuffer = new Buffer;
2335 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2336 pInBuffer->mBuffer = malloc(bufferSize);
2337 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2338 "%s: Unable to malloc size %zu", __func__, bufferSize);
2339 pInBuffer->frameCount = inBuffer.frameCount;
2340 pInBuffer->raw = pInBuffer->mBuffer;
2341 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2342 mBufferQueue.add(pInBuffer);
2343 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2344 (int)mThreadIoHandle, mBufferQueue.size());
2345 // audio data is consumed (stored locally); set frameCount to 0.
2346 inBuffer.frameCount = 0;
2347 } else {
2348 ALOGW("%s(%d): thread %d no more overflow buffers",
2349 __func__, mId, (int)mThreadIoHandle);
2350 // TODO: return error for this.
2351 }
2352}
2353
Andy Hung3ff4b552023-06-26 19:20:57 -07002354void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002355{
2356 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2357 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2358}
2359
Andy Hung3ff4b552023-06-26 19:20:57 -07002360void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002361 {
2362 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2363 mTrackMetadatas = metadatas;
2364 }
2365 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2366 setMetadataHasChanged();
2367}
2368
Andy Hung3ff4b552023-06-26 19:20:57 -07002369status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002370 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2371{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002372 ClientProxy::Buffer buf;
2373 buf.mFrameCount = buffer->frameCount;
2374 struct timespec timeout;
2375 timeout.tv_sec = waitTimeMs / 1000;
2376 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2377 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2378 buffer->frameCount = buf.mFrameCount;
2379 buffer->raw = buf.mRaw;
2380 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002381}
2382
Andy Hung3ff4b552023-06-26 19:20:57 -07002383void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002384{
2385 size_t size = mBufferQueue.size();
2386
2387 for (size_t i = 0; i < size; i++) {
2388 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002389 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002390 delete pBuffer;
2391 }
2392 mBufferQueue.clear();
2393}
2394
Andy Hung3ff4b552023-06-26 19:20:57 -07002395void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002396{
2397 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2398 if (mActive && (flags & CBLK_DISABLED)) {
2399 start();
2400 }
2401}
Eric Laurent81784c32012-11-19 14:55:58 -08002402
Andy Hung9d84af52018-09-12 18:03:44 -07002403// ----------------------------------------------------------------------------
2404#undef LOG_TAG
2405#define LOG_TAG "AF::PatchTrack"
2406
Andy Hung3ff4b552023-06-26 19:20:57 -07002407/* static */
2408sp<IAfPatchTrack> IAfPatchTrack::create(
2409 void* /* PlaybackThread */ playbackThread, // TODO(b/288339104)
2410 audio_stream_type_t streamType,
2411 uint32_t sampleRate,
2412 audio_channel_mask_t channelMask,
2413 audio_format_t format,
2414 size_t frameCount,
2415 void* buffer,
2416 size_t bufferSize,
2417 audio_output_flags_t flags,
2418 const Timeout& timeout,
2419 size_t frameCountToBeReady /** Default behaviour is to start
2420 * as soon as possible to have
2421 * the lowest possible latency
2422 * even if it might glitch. */)
2423{
2424 return sp<PatchTrack>::make(
2425 reinterpret_cast<AudioFlinger::PlaybackThread*>(playbackThread),
2426 streamType,
2427 sampleRate,
2428 channelMask,
2429 format,
2430 frameCount,
2431 buffer,
2432 bufferSize,
2433 flags,
2434 timeout,
2435 frameCountToBeReady);
2436}
2437
2438PatchTrack::PatchTrack(AudioFlinger::PlaybackThread *playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002439 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002440 uint32_t sampleRate,
2441 audio_channel_mask_t channelMask,
2442 audio_format_t format,
2443 size_t frameCount,
2444 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002445 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002446 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002447 const Timeout& timeout,
2448 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002449 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002450 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002451 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002452 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002453 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002454 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002455 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2456 : nullptr,
Kevin Rocard45986c72018-12-18 18:22:59 -08002457 *playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002458{
Andy Hung9d84af52018-09-12 18:03:44 -07002459 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2460 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002461 (int)mPeerTimeout.tv_sec,
2462 (int)(mPeerTimeout.tv_nsec / 1000000));
2463}
2464
Andy Hung3ff4b552023-06-26 19:20:57 -07002465PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002466{
Andy Hungabfab202019-03-07 19:45:54 -08002467 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002468}
2469
Andy Hung3ff4b552023-06-26 19:20:57 -07002470size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002471{
2472 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2473 return std::numeric_limits<size_t>::max();
2474 } else {
2475 return Track::framesReady();
2476 }
2477}
2478
Andy Hung3ff4b552023-06-26 19:20:57 -07002479status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002480 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002481{
2482 status_t status = Track::start(event, triggerSession);
2483 if (status != NO_ERROR) {
2484 return status;
2485 }
2486 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2487 return status;
2488}
2489
Eric Laurent83b88082014-06-20 18:31:16 -07002490// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002491status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002492 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002493{
Andy Hung9d84af52018-09-12 18:03:44 -07002494 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002495 Proxy::Buffer buf;
2496 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002497 if (ATRACE_ENABLED()) {
2498 std::string traceName("PTnReq");
2499 traceName += std::to_string(id());
2500 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2501 }
Eric Laurent83b88082014-06-20 18:31:16 -07002502 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002503 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002504 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002505 if (ATRACE_ENABLED()) {
2506 std::string traceName("PTnObt");
2507 traceName += std::to_string(id());
2508 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2509 }
Eric Laurent83b88082014-06-20 18:31:16 -07002510 if (buf.mFrameCount == 0) {
2511 return WOULD_BLOCK;
2512 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002513 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002514 return status;
2515}
2516
Andy Hung3ff4b552023-06-26 19:20:57 -07002517void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002518{
Andy Hung9d84af52018-09-12 18:03:44 -07002519 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002520 Proxy::Buffer buf;
2521 buf.mFrameCount = buffer->frameCount;
2522 buf.mRaw = buffer->raw;
2523 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002524 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002525}
2526
Andy Hung3ff4b552023-06-26 19:20:57 -07002527status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002528 const struct timespec *timeOut)
2529{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002530 status_t status = NO_ERROR;
2531 static const int32_t kMaxTries = 5;
2532 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002533 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002534 do {
2535 if (status == NOT_ENOUGH_DATA) {
2536 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002537 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002538 }
2539 status = mProxy->obtainBuffer(buffer, timeOut);
2540 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2541 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002542}
2543
Andy Hung3ff4b552023-06-26 19:20:57 -07002544void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002545{
2546 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002547 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002548
2549 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2550 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2551 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2552 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002553 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002554 && audio_is_linear_pcm(mFormat)
2555 && !isOffloadedOrDirect()) {
Andy Hung3ff4b552023-06-26 19:20:57 -07002556 if (sp<AudioFlinger::ThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002557 thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07002558 auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
naoki miyazuf37f9982019-11-28 11:18:18 +09002559 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2560 / playbackThread->sampleRate();
2561 if (framesReady() < frameCount) {
2562 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002563 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002564 }
2565 }
2566 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002567}
2568
Andy Hung3ff4b552023-06-26 19:20:57 -07002569void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002570{
Eric Laurent83b88082014-06-20 18:31:16 -07002571 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002572 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002573 start();
2574 }
Eric Laurent83b88082014-06-20 18:31:16 -07002575}
2576
Eric Laurent81784c32012-11-19 14:55:58 -08002577// ----------------------------------------------------------------------------
2578// Record
2579// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002580
2581
Andy Hung9d84af52018-09-12 18:03:44 -07002582#undef LOG_TAG
2583#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002584
Andy Hungaaa18282023-06-23 19:27:19 -07002585class RecordHandle : public android::media::BnAudioRecord {
2586public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002587 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002588 ~RecordHandle() override;
2589 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2590 int /*audio_session_t*/ triggerSession) final;
2591 binder::Status stop() final;
2592 binder::Status getActiveMicrophones(
2593 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2594 binder::Status setPreferredMicrophoneDirection(
2595 int /*audio_microphone_direction_t*/ direction) final;
2596 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2597 binder::Status shareAudioHistory(
2598 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2599
2600private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002601 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002602
2603 // for use from destructor
2604 void stop_nonvirtual();
2605};
2606
2607/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002608sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2609 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002610 return sp<RecordHandle>::make(recordTrack);
2611}
2612
2613RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002614 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002615 : BnAudioRecord(),
2616 mRecordTrack(recordTrack)
2617{
Andy Hungaaa18282023-06-23 19:27:19 -07002618 // TODO(b/288339104) binder thread priority change not needed.
Andy Hung225aef62022-12-06 16:33:20 -08002619 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002620}
2621
Andy Hungaaa18282023-06-23 19:27:19 -07002622RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002623 stop_nonvirtual();
2624 mRecordTrack->destroy();
2625}
2626
Andy Hungaaa18282023-06-23 19:27:19 -07002627binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002628 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002629 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002630 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002631 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002632}
2633
Andy Hungaaa18282023-06-23 19:27:19 -07002634binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002635 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002636 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002637}
2638
Andy Hungaaa18282023-06-23 19:27:19 -07002639void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002640 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002641 mRecordTrack->stop();
2642}
2643
Andy Hungaaa18282023-06-23 19:27:19 -07002644binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002645 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002646 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002647 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002648}
2649
Andy Hungaaa18282023-06-23 19:27:19 -07002650binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002651 int /*audio_microphone_direction_t*/ direction) {
2652 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002653 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002654 static_cast<audio_microphone_direction_t>(direction)));
2655}
2656
Andy Hungaaa18282023-06-23 19:27:19 -07002657binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002658 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002659 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002660}
2661
Andy Hungaaa18282023-06-23 19:27:19 -07002662binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002663 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2664 return binderStatusFromStatusT(
2665 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2666}
2667
Eric Laurent81784c32012-11-19 14:55:58 -08002668// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002669#undef LOG_TAG
2670#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002671
Andy Hung3ff4b552023-06-26 19:20:57 -07002672
2673/* static */ // TODO(b/288339104)
2674sp<IAfRecordTrack> IAfRecordTrack::create(void* /*AudioFlinger::RecordThread */ thread,
2675 const sp<Client>& client,
2676 const audio_attributes_t& attr,
2677 uint32_t sampleRate,
2678 audio_format_t format,
2679 audio_channel_mask_t channelMask,
2680 size_t frameCount,
2681 void* buffer,
2682 size_t bufferSize,
2683 audio_session_t sessionId,
2684 pid_t creatorPid,
2685 const AttributionSourceState& attributionSource,
2686 audio_input_flags_t flags,
2687 track_type type,
2688 audio_port_handle_t portId,
2689 int32_t startFrames)
2690{
2691 return sp<RecordTrack>::make(
2692 reinterpret_cast<AudioFlinger::RecordThread*>(thread),
2693 client,
2694 attr,
2695 sampleRate,
2696 format,
2697 channelMask,
2698 frameCount,
2699 buffer,
2700 bufferSize,
2701 sessionId,
2702 creatorPid,
2703 attributionSource,
2704 flags,
2705 type,
2706 portId,
2707 startFrames);
2708}
2709
Glenn Kasten05997e22014-03-13 15:08:33 -07002710// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002711RecordTrack::RecordTrack(
2712 AudioFlinger::RecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002713 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002714 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002715 uint32_t sampleRate,
2716 audio_format_t format,
2717 audio_channel_mask_t channelMask,
2718 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002719 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002720 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002721 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002722 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002723 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002724 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002725 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002726 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002727 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002728 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002729 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002730 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002731 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002732 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002733 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002734 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002735 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002736 type, portId,
2737 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002738 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002739 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002740 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002741 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002742 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002743 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002744{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002745 if (mCblk == NULL) {
2746 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002747 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002748
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002749 if (!isDirect()) {
2750 mRecordBufferConverter = new RecordBufferConverter(
2751 thread->mChannelMask, thread->mFormat, thread->mSampleRate,
2752 channelMask, format, sampleRate);
2753 // Check if the RecordBufferConverter construction was successful.
2754 // If not, don't continue with construction.
2755 //
2756 // NOTE: It would be extremely rare that the record track cannot be created
2757 // for the current device, but a pending or future device change would make
2758 // the record track configuration valid.
2759 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002760 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002761 return;
2762 }
Andy Hung97a893e2015-03-29 01:03:07 -07002763 }
2764
Andy Hung6ae58432016-02-16 18:32:24 -08002765 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002766 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002767
Andy Hung97a893e2015-03-29 01:03:07 -07002768 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002769
Eric Laurent05067782016-06-01 18:27:28 -07002770 if (flags & AUDIO_INPUT_FLAG_FAST) {
Glenn Kastenc263ca02014-06-04 20:31:46 -07002771 ALOG_ASSERT(thread->mFastTrackAvail);
2772 thread->mFastTrackAvail = false;
Andy Hung000adb52018-06-01 15:43:26 -07002773 } else {
2774 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002775 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002776 }
Andy Hung8946a282018-04-19 20:04:56 -07002777#ifdef TEE_SINK
2778 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2779 + "_" + std::to_string(mId)
2780 + "_R");
2781#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002782
2783 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002784 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002785}
2786
Andy Hung3ff4b552023-06-26 19:20:57 -07002787RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002788{
Andy Hung9d84af52018-09-12 18:03:44 -07002789 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002790 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002791 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002792}
2793
Andy Hung3ff4b552023-06-26 19:20:57 -07002794status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002795{
2796 status_t status = TrackBase::initCheck();
2797 if (status == NO_ERROR && mServerProxy == 0) {
2798 status = BAD_VALUE;
2799 }
2800 return status;
2801}
2802
Eric Laurent81784c32012-11-19 14:55:58 -08002803// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002804status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002805{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002806 ServerProxy::Buffer buf;
2807 buf.mFrameCount = buffer->frameCount;
2808 status_t status = mServerProxy->obtainBuffer(&buf);
2809 buffer->frameCount = buf.mFrameCount;
2810 buffer->raw = buf.mRaw;
2811 if (buf.mFrameCount == 0) {
2812 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002813 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002814 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002815 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002816}
2817
Andy Hung3ff4b552023-06-26 19:20:57 -07002818status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002819 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002820{
Andy Hung3ff4b552023-06-26 19:20:57 -07002821 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002822 if (thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07002823 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Eric Laurent81784c32012-11-19 14:55:58 -08002824 return recordThread->start(this, event, triggerSession);
2825 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002826 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2827 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002828 }
2829}
2830
Andy Hung3ff4b552023-06-26 19:20:57 -07002831void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002832{
Andy Hung3ff4b552023-06-26 19:20:57 -07002833 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002834 if (thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07002835 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Eric Laurent83b88082014-06-20 18:31:16 -07002836 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002837 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002838 }
2839 }
2840}
2841
Andy Hung3ff4b552023-06-26 19:20:57 -07002842void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002843{
Andy Hung3ff4b552023-06-26 19:20:57 -07002844 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002845 sp<RecordTrack> keep(this);
2846 {
Andy Hungce685402018-10-05 17:23:27 -07002847 track_state priorState = mState;
Andy Hung3ff4b552023-06-26 19:20:57 -07002848 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002849 if (thread != 0) {
Eric Laurent81784c32012-11-19 14:55:58 -08002850 Mutex::Autolock _l(thread->mLock);
Andy Hung3ff4b552023-06-26 19:20:57 -07002851 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Andy Hungce685402018-10-05 17:23:27 -07002852 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002853 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002854 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002855 }
Andy Hungce685402018-10-05 17:23:27 -07002856 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2857 }
2858 // APM portid/client management done outside of lock.
2859 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2860 if (isExternalTrack()) {
2861 switch (priorState) {
2862 case ACTIVE: // invalidated while still active
2863 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2864 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2865 AudioSystem::stopInput(mPortId);
2866 break;
2867
2868 case STARTING_1: // invalidated/start-aborted and startInput not successful
2869 case PAUSED: // OK, not active
2870 case IDLE: // OK, not active
2871 break;
2872
2873 case STOPPED: // unexpected (destroyed)
2874 default:
2875 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2876 }
2877 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002878 }
2879 }
2880}
2881
Andy Hung3ff4b552023-06-26 19:20:57 -07002882void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002883{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002884 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002885 // FIXME should use proxy, and needs work
2886 audio_track_cblk_t* cblk = mCblk;
2887 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2888 android_atomic_release_store(0x40000000, &cblk->mFutex);
2889 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002890 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002891}
2892
Eric Laurent81784c32012-11-19 14:55:58 -08002893
Andy Hung3ff4b552023-06-26 19:20:57 -07002894void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002895{
Eric Laurent973db022018-11-20 14:54:31 -08002896 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002897 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002898 " Server FrmCnt FrmRdy Sil%s\n",
2899 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002900}
2901
Andy Hung3ff4b552023-06-26 19:20:57 -07002902void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002903{
Eric Laurent973db022018-11-20 14:54:31 -08002904 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002905 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002906 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002907 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002908 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002909 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002910 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002911 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002912 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002913 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002914 mCblk->mFlags,
2915
Eric Laurent81784c32012-11-19 14:55:58 -08002916 mFormat,
2917 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002918 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002919 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002920
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002921 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002922 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002923 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002924 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002925 );
Andy Hung000adb52018-06-01 15:43:26 -07002926 if (isServerLatencySupported()) {
2927 double latencyMs;
2928 bool fromTrack;
2929 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2930 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2931 // or 'k' if estimated from kernel (usually for debugging).
2932 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2933 } else {
2934 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2935 }
2936 }
2937 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002938}
2939
Andy Hung93bb5732023-05-04 21:16:34 -07002940// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002941void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002942 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002943{
Andy Hung93bb5732023-05-04 21:16:34 -07002944 size_t framesToDrop = 0;
Andy Hung3ff4b552023-06-26 19:20:57 -07002945 sp<AudioFlinger::ThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002946 if (threadBase != 0) {
2947 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2948 // from audio HAL
2949 framesToDrop = threadBase->mFrameCount * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002950 }
Andy Hung93bb5732023-05-04 21:16:34 -07002951
2952 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002953}
2954
Andy Hung3ff4b552023-06-26 19:20:57 -07002955void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002956{
Andy Hung93bb5732023-05-04 21:16:34 -07002957 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002958}
2959
Andy Hung3ff4b552023-06-26 19:20:57 -07002960void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002961 int64_t trackFramesReleased, int64_t sourceFramesRead,
2962 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2963{
Andy Hung30282562018-08-08 18:27:03 -07002964 // Make the kernel frametime available.
2965 const FrameTime ft{
2966 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2967 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2968 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2969 mKernelFrameTime.store(ft);
2970 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002971 // Stream is direct, return provided timestamp with no conversion
2972 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002973 return;
2974 }
2975
Andy Hung3f0c9022016-01-15 17:49:46 -08002976 ExtendedTimestamp local = timestamp;
2977
2978 // Convert HAL frames to server-side track frames at track sample rate.
2979 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2980 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2981 if (local.mTimeNs[i] != 0) {
2982 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2983 const int64_t relativeTrackFrames = relativeServerFrames
2984 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2985 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2986 }
2987 }
Andy Hung6ae58432016-02-16 18:32:24 -08002988 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002989
2990 // Compute latency info.
2991 const bool useTrackTimestamp = true; // use track unless debugging.
2992 const double latencyMs = - (useTrackTimestamp
2993 ? local.getOutputServerLatencyMs(sampleRate())
2994 : timestamp.getOutputServerLatencyMs(halSampleRate));
2995
2996 mServerLatencyFromTrack.store(useTrackTimestamp);
2997 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08002998}
Eric Laurent83b88082014-06-20 18:31:16 -07002999
Andy Hung3ff4b552023-06-26 19:20:57 -07003000status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003001 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003002{
Andy Hung3ff4b552023-06-26 19:20:57 -07003003 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003004 if (thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07003005 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
jiabin653cc0a2018-01-17 17:54:10 -08003006 return recordThread->getActiveMicrophones(activeMicrophones);
3007 } else {
3008 return BAD_VALUE;
3009 }
3010}
3011
Andy Hung3ff4b552023-06-26 19:20:57 -07003012status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003013 audio_microphone_direction_t direction) {
Andy Hung3ff4b552023-06-26 19:20:57 -07003014 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003015 if (thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07003016 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Paul McLean12340082019-03-19 09:35:05 -06003017 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003018 } else {
3019 return BAD_VALUE;
3020 }
3021}
3022
Andy Hung3ff4b552023-06-26 19:20:57 -07003023status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
3024 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003025 if (thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07003026 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Paul McLean12340082019-03-19 09:35:05 -06003027 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003028 } else {
3029 return BAD_VALUE;
3030 }
3031}
3032
Andy Hung3ff4b552023-06-26 19:20:57 -07003033status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003034 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3035
3036 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3037 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3038 if (callingUid != mUid || callingPid != mCreatorPid) {
3039 return PERMISSION_DENIED;
3040 }
3041
Svet Ganov33761132021-05-13 22:51:08 +00003042 AttributionSourceState attributionSource{};
3043 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3044 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3045 attributionSource.token = sp<BBinder>::make();
3046 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003047 return PERMISSION_DENIED;
3048 }
3049
Andy Hung3ff4b552023-06-26 19:20:57 -07003050 sp<AudioFlinger::ThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003051 if (thread != 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07003052 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
Eric Laurentec376dc2021-04-08 20:41:22 +02003053 status_t status = recordThread->shareAudioHistory(
3054 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3055 if (status == NO_ERROR) {
3056 mSharedAudioPackageName = sharedAudioPackageName;
3057 }
3058 return status;
3059 } else {
3060 return BAD_VALUE;
3061 }
3062}
3063
Andy Hung3ff4b552023-06-26 19:20:57 -07003064void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003065{
3066
3067 // Do not forward PatchRecord metadata with unspecified audio source
3068 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3069 return;
3070 }
3071
3072 // No track is invalid as this is called after prepareTrack_l in the same critical section
3073 record_track_metadata_v7_t metadata;
3074 metadata.base = {
3075 .source = mAttr.source,
3076 .gain = 1, // capture tracks do not have volumes
3077 };
3078 metadata.channel_mask = mChannelMask;
3079 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3080
3081 *backInserter++ = metadata;
3082}
Eric Laurentec376dc2021-04-08 20:41:22 +02003083
Andy Hung9d84af52018-09-12 18:03:44 -07003084// ----------------------------------------------------------------------------
3085#undef LOG_TAG
3086#define LOG_TAG "AF::PatchRecord"
3087
Andy Hung3ff4b552023-06-26 19:20:57 -07003088/* static */
3089sp<IAfPatchRecord> IAfPatchRecord::create(
3090 void* /* RecordThread */ recordThread, // TODO(b/288339104)
3091 uint32_t sampleRate,
3092 audio_channel_mask_t channelMask,
3093 audio_format_t format,
3094 size_t frameCount,
3095 void *buffer,
3096 size_t bufferSize,
3097 audio_input_flags_t flags,
3098 const Timeout& timeout,
3099 audio_source_t source)
3100{
3101 return sp<PatchRecord>::make(
3102 reinterpret_cast<AudioFlinger::RecordThread*>(recordThread),
3103 sampleRate,
3104 channelMask,
3105 format,
3106 frameCount,
3107 buffer,
3108 bufferSize,
3109 flags,
3110 timeout,
3111 source);
3112}
3113
3114PatchRecord::PatchRecord(AudioFlinger::RecordThread *recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003115 uint32_t sampleRate,
3116 audio_channel_mask_t channelMask,
3117 audio_format_t format,
3118 size_t frameCount,
3119 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003120 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003121 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003122 const Timeout& timeout,
3123 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003124 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003125 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003126 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003127 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003128 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003129 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3130 : nullptr,
Kevin Rocard45986c72018-12-18 18:22:59 -08003131 *recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003132{
Andy Hung9d84af52018-09-12 18:03:44 -07003133 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3134 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003135 (int)mPeerTimeout.tv_sec,
3136 (int)(mPeerTimeout.tv_nsec / 1000000));
3137}
3138
Andy Hung3ff4b552023-06-26 19:20:57 -07003139PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003140{
Andy Hungabfab202019-03-07 19:45:54 -08003141 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003142}
3143
Mikhail Naganov8296c252019-09-25 14:59:54 -07003144static size_t writeFramesHelper(
3145 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3146{
3147 AudioBufferProvider::Buffer patchBuffer;
3148 patchBuffer.frameCount = frameCount;
3149 auto status = dest->getNextBuffer(&patchBuffer);
3150 if (status != NO_ERROR) {
3151 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3152 __func__, status, strerror(-status));
3153 return 0;
3154 }
3155 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3156 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3157 size_t framesWritten = patchBuffer.frameCount;
3158 dest->releaseBuffer(&patchBuffer);
3159 return framesWritten;
3160}
3161
3162// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003163size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003164 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3165{
3166 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3167 // On buffer wrap, the buffer frame count will be less than requested,
3168 // when this happens a second buffer needs to be used to write the leftover audio
3169 const size_t framesLeft = frameCount - framesWritten;
3170 if (framesWritten != 0 && framesLeft != 0) {
3171 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3172 framesLeft, frameSize);
3173 }
3174 return framesWritten;
3175}
3176
Eric Laurent83b88082014-06-20 18:31:16 -07003177// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003178status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003179 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003180{
Andy Hung9d84af52018-09-12 18:03:44 -07003181 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003182 Proxy::Buffer buf;
3183 buf.mFrameCount = buffer->frameCount;
3184 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3185 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003186 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003187 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003188 if (ATRACE_ENABLED()) {
3189 std::string traceName("PRnObt");
3190 traceName += std::to_string(id());
3191 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3192 }
Eric Laurent83b88082014-06-20 18:31:16 -07003193 if (buf.mFrameCount == 0) {
3194 return WOULD_BLOCK;
3195 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003196 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003197 return status;
3198}
3199
Andy Hung3ff4b552023-06-26 19:20:57 -07003200void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003201{
Andy Hung9d84af52018-09-12 18:03:44 -07003202 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003203 Proxy::Buffer buf;
3204 buf.mFrameCount = buffer->frameCount;
3205 buf.mRaw = buffer->raw;
3206 mPeerProxy->releaseBuffer(&buf);
3207 TrackBase::releaseBuffer(buffer);
3208}
3209
Andy Hung3ff4b552023-06-26 19:20:57 -07003210status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003211 const struct timespec *timeOut)
3212{
3213 return mProxy->obtainBuffer(buffer, timeOut);
3214}
3215
Andy Hung3ff4b552023-06-26 19:20:57 -07003216void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003217{
3218 mProxy->releaseBuffer(buffer);
3219}
3220
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003221#undef LOG_TAG
3222#define LOG_TAG "AF::PthrPatchRecord"
3223
3224static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3225{
3226 void *ptr = nullptr;
3227 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003228 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003229}
3230
Andy Hung3ff4b552023-06-26 19:20:57 -07003231/* static */
3232sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
3233 void* /* RecordThread */ recordThread, // TODO(b/288339104)
3234 uint32_t sampleRate,
3235 audio_channel_mask_t channelMask,
3236 audio_format_t format,
3237 size_t frameCount,
3238 audio_input_flags_t flags,
3239 audio_source_t source)
3240{
3241 return sp<PassthruPatchRecord>::make(
3242 reinterpret_cast<AudioFlinger::RecordThread*>(recordThread),
3243 sampleRate,
3244 channelMask,
3245 format,
3246 frameCount,
3247 flags,
3248 source);
3249}
3250
3251PassthruPatchRecord::PassthruPatchRecord(
3252 AudioFlinger::RecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003253 uint32_t sampleRate,
3254 audio_channel_mask_t channelMask,
3255 audio_format_t format,
3256 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003257 audio_input_flags_t flags,
3258 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003259 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003260 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003261 mPatchRecordAudioBufferProvider(*this),
3262 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3263 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3264{
3265 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3266}
3267
Andy Hung3ff4b552023-06-26 19:20:57 -07003268sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
3269 sp<AudioFlinger::ThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003270{
3271 *thread = mThread.promote();
3272 if (!*thread) return nullptr;
Andy Hung3ff4b552023-06-26 19:20:57 -07003273 auto* const recordThread = static_cast<AudioFlinger::RecordThread*>((*thread).get());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003274 Mutex::Autolock _l(recordThread->mLock);
3275 return recordThread->mInput ? recordThread->mInput->stream : nullptr;
3276}
3277
3278// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003279status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003280 Proxy::Buffer* buffer, const struct timespec* timeOut)
3281{
3282 if (mUnconsumedFrames) {
3283 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3284 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3285 return PatchRecord::obtainBuffer(buffer, timeOut);
3286 }
3287
3288 // Otherwise, execute a read from HAL and write into the buffer.
3289 nsecs_t startTimeNs = 0;
3290 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3291 // Will need to correct timeOut by elapsed time.
3292 startTimeNs = systemTime();
3293 }
3294 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3295 buffer->mFrameCount = 0;
3296 buffer->mRaw = nullptr;
Andy Hung3ff4b552023-06-26 19:20:57 -07003297 sp<AudioFlinger::ThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003298 sp<StreamInHalInterface> stream = obtainStream(&thread);
3299 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3300
3301 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003302 size_t bytesRead = 0;
3303 {
3304 ATRACE_NAME("read");
3305 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3306 if (result != NO_ERROR) goto stream_error;
3307 if (bytesRead == 0) return NO_ERROR;
3308 }
3309
3310 {
3311 std::lock_guard<std::mutex> lock(mReadLock);
3312 mReadBytes += bytesRead;
3313 mReadError = NO_ERROR;
3314 }
3315 mReadCV.notify_one();
3316 // writeFrames handles wraparound and should write all the provided frames.
3317 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3318 buffer->mFrameCount = writeFrames(
3319 &mPatchRecordAudioBufferProvider,
3320 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3321 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3322 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3323 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003324 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003325 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003326 // Correct the timeout by elapsed time.
3327 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003328 if (newTimeOutNs < 0) newTimeOutNs = 0;
3329 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3330 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003331 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003332 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003333 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003334
3335stream_error:
3336 stream->standby();
3337 {
3338 std::lock_guard<std::mutex> lock(mReadLock);
3339 mReadError = result;
3340 }
3341 mReadCV.notify_one();
3342 return result;
3343}
3344
Andy Hung3ff4b552023-06-26 19:20:57 -07003345void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003346{
3347 if (buffer->mFrameCount <= mUnconsumedFrames) {
3348 mUnconsumedFrames -= buffer->mFrameCount;
3349 } else {
3350 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3351 buffer->mFrameCount, mUnconsumedFrames);
3352 mUnconsumedFrames = 0;
3353 }
3354 PatchRecord::releaseBuffer(buffer);
3355}
3356
3357// AudioBufferProvider and Source methods are called on RecordThread
3358// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3359// and 'releaseBuffer' are stubbed out and ignore their input.
3360// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3361// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003362status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003363 void* buffer, size_t bytes, size_t* read)
3364{
3365 bytes = std::min(bytes, mFrameCount * mFrameSize);
3366 {
3367 std::unique_lock<std::mutex> lock(mReadLock);
3368 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3369 if (mReadError != NO_ERROR) {
3370 mLastReadFrames = 0;
3371 return mReadError;
3372 }
3373 *read = std::min(bytes, mReadBytes);
3374 mReadBytes -= *read;
3375 }
3376 mLastReadFrames = *read / mFrameSize;
3377 memset(buffer, 0, *read);
3378 return 0;
3379}
3380
Andy Hung3ff4b552023-06-26 19:20:57 -07003381status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003382 int64_t* frames, int64_t* time)
3383{
Andy Hung3ff4b552023-06-26 19:20:57 -07003384 sp<AudioFlinger::ThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003385 sp<StreamInHalInterface> stream = obtainStream(&thread);
3386 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3387}
3388
Andy Hung3ff4b552023-06-26 19:20:57 -07003389status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003390{
3391 // RecordThread issues 'standby' command in two major cases:
3392 // 1. Error on read--this case is handled in 'obtainBuffer'.
3393 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3394 // output, this can only happen when the software patch
3395 // is being torn down. In this case, the RecordThread
3396 // will terminate and close the HAL stream.
3397 return 0;
3398}
3399
3400// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003401status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003402 AudioBufferProvider::Buffer* buffer)
3403{
3404 buffer->frameCount = mLastReadFrames;
3405 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3406 return NO_ERROR;
3407}
3408
Andy Hung3ff4b552023-06-26 19:20:57 -07003409void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003410 AudioBufferProvider::Buffer* buffer)
3411{
3412 buffer->frameCount = 0;
3413 buffer->raw = nullptr;
3414}
3415
Andy Hung9d84af52018-09-12 18:03:44 -07003416// ----------------------------------------------------------------------------
3417#undef LOG_TAG
3418#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003419
Andy Hung3ff4b552023-06-26 19:20:57 -07003420/* static */
3421sp<IAfMmapTrack> IAfMmapTrack::create(void* /* AudioFlinger::ThreadBase */ thread,
3422 const audio_attributes_t& attr,
3423 uint32_t sampleRate,
3424 audio_format_t format,
3425 audio_channel_mask_t channelMask,
3426 audio_session_t sessionId,
3427 bool isOut,
3428 const android::content::AttributionSourceState& attributionSource,
3429 pid_t creatorPid,
3430 audio_port_handle_t portId)
3431{
3432 return sp<MmapTrack>::make(
3433 reinterpret_cast<AudioFlinger::ThreadBase*>(thread),
3434 attr,
3435 sampleRate,
3436 format,
3437 channelMask,
3438 sessionId,
3439 isOut,
3440 attributionSource,
3441 creatorPid,
3442 portId);
3443}
3444
3445MmapTrack::MmapTrack(AudioFlinger::ThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003446 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003447 uint32_t sampleRate,
3448 audio_format_t format,
3449 audio_channel_mask_t channelMask,
3450 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003451 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003452 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003453 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003454 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003455 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003456 channelMask, (size_t)0 /* frameCount */,
3457 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003458 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003459 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003460 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003461 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003462 TYPE_DEFAULT, portId,
3463 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003464 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003465 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003466{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003467 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003468 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003469}
3470
Andy Hung3ff4b552023-06-26 19:20:57 -07003471MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003472{
3473}
3474
Andy Hung3ff4b552023-06-26 19:20:57 -07003475status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003476{
3477 return NO_ERROR;
3478}
3479
Andy Hung3ff4b552023-06-26 19:20:57 -07003480status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003481 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003482{
3483 return NO_ERROR;
3484}
3485
Andy Hung3ff4b552023-06-26 19:20:57 -07003486void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003487{
3488}
3489
3490// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003491status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003492{
3493 buffer->frameCount = 0;
3494 buffer->raw = nullptr;
3495 return INVALID_OPERATION;
3496}
3497
3498// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003499size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003500 return 0;
3501}
3502
Andy Hung3ff4b552023-06-26 19:20:57 -07003503int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003504{
3505 return 0;
3506}
3507
Andy Hung3ff4b552023-06-26 19:20:57 -07003508void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003509{
3510}
3511
Andy Hung3ff4b552023-06-26 19:20:57 -07003512void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003513{
3514 if (mMuteState == muteState) {
3515 // mute state did not change, do nothing
3516 return;
3517 }
3518
3519 status_t result = UNKNOWN_ERROR;
3520 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3521 if (mMuteEventExtras == nullptr) {
3522 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3523 }
3524 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3525 static_cast<int>(muteState));
3526
3527 result = audioManager->portEvent(mPortId,
3528 PLAYER_UPDATE_MUTED,
3529 mMuteEventExtras);
3530 }
3531
3532 if (result == OK) {
3533 mMuteState = muteState;
3534 } else {
3535 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3536 __func__,
3537 id(),
3538 mPortId,
3539 result);
3540 }
3541}
3542
Andy Hung3ff4b552023-06-26 19:20:57 -07003543void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003544{
Eric Laurent973db022018-11-20 14:54:31 -08003545 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003546 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003547}
3548
Andy Hung3ff4b552023-06-26 19:20:57 -07003549void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003550{
Eric Laurent973db022018-11-20 14:54:31 -08003551 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003552 mPid,
3553 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003554 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003555 mFormat,
3556 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003557 mSampleRate,
3558 mAttr.flags);
3559 if (isOut()) {
3560 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3561 } else {
3562 result.appendFormat("%6x", mAttr.source);
3563 }
3564 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003565}
3566
Glenn Kasten63238ef2015-03-02 15:50:29 -08003567} // namespace android