blob: 257f9e4e057e68bf1247568dd1e61c7838d02564 [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070021#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080022
Glenn Kasten153b9fe2013-07-15 11:23:36 -070023#include "Configuration.h"
Glenn Kastenad8510a2015-02-17 16:24:07 -080024#include <linux/futex.h>
Eric Laurent81784c32012-11-19 14:55:58 -080025#include <math.h>
Elliott Hughesee499292014-05-21 17:55:51 -070026#include <sys/syscall.h>
Eric Laurent81784c32012-11-19 14:55:58 -080027#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070028#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080029
30#include <private/media/AudioTrackShared.h>
31
Eric Laurent81784c32012-11-19 14:55:58 -080032#include "AudioFlinger.h"
Andy Hung8d31fd22023-06-26 19:20:57 -070033#include "TrackBase.h"
34#include "PlaybackTracks.h"
35#include "RecordTracks.h"
36#include "MmapTracks.h"
Eric Laurent81784c32012-11-19 14:55:58 -080037
Glenn Kastenda6ef132013-01-10 12:31:01 -080038#include <media/nbaio/Pipe.h>
39#include <media/nbaio/PipeReader.h>
Kuowei Lid4adbdb2020-08-13 14:44:25 +080040#include <media/AudioValidator.h>
Andy Hung89816052017-01-11 17:08:23 -080041#include <media/RecordBufferConverter.h>
Andy Hungab7ef302018-05-15 19:35:29 -070042#include <mediautils/ServiceUtilities.h>
Glenn Kastenc56f3422014-03-21 17:53:17 -070043#include <audio_utils/minifloat.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080044
Eric Laurent81784c32012-11-19 14:55:58 -080045// ----------------------------------------------------------------------------
46
47// Note: the following macro is used for extremely verbose logging message. In
48// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
49// 0; but one side effect of this is to turn all LOGV's as well. Some messages
50// are so verbose that we want to suppress them even when we have ALOG_ASSERT
51// turned on. Do not uncomment the #def below unless you really know what you
52// are doing and want to see all of the extremely verbose messages.
53//#define VERY_VERY_VERBOSE_LOGGING
54#ifdef VERY_VERY_VERBOSE_LOGGING
55#define ALOGVV ALOGV
56#else
57#define ALOGVV(a...) do { } while(0)
58#endif
59
Kuowei Lid4adbdb2020-08-13 14:44:25 +080060// TODO: Remove when this is put into AidlConversionUtil.h
61#define VALUE_OR_RETURN_BINDER_STATUS(x) \
62 ({ \
63 auto _tmp = (x); \
64 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
65 std::move(_tmp.value()); \
66 })
67
Eric Laurent81784c32012-11-19 14:55:58 -080068namespace android {
69
Kuowei Lid4adbdb2020-08-13 14:44:25 +080070using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080071using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000072using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070073using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080074// ----------------------------------------------------------------------------
75// TrackBase
76// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070077#undef LOG_TAG
78#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080079
Glenn Kastenda6ef132013-01-10 12:31:01 -080080static volatile int32_t nextTrackId = 55;
81
Eric Laurent81784c32012-11-19 14:55:58 -080082// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -070083TrackBase::TrackBase(
Andy Hung87c693c2023-07-06 20:56:16 -070084 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080085 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070086 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080087 uint32_t sampleRate,
88 audio_format_t format,
89 audio_channel_mask_t channelMask,
90 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070091 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070092 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080093 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070094 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080095 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070096 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070097 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080098 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -080099 audio_port_handle_t portId,
100 std::string metricsId)
Andy Hungd29af632023-06-23 19:27:19 -0700101 :
Eric Laurent81784c32012-11-19 14:55:58 -0800102 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700103 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800104 mClient(client),
105 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700106 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800107 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700108 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800109 mSampleRate(sampleRate),
110 mFormat(format),
111 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700112 mChannelCount(isOut ?
113 audio_channel_count_from_out_mask(channelMask) :
114 audio_channel_count_from_in_mask(channelMask)),
Phil Burkfdb3c072016-02-09 10:47:02 -0800115 mFrameSize(audio_has_proportional_frames(format) ?
Eric Laurent81784c32012-11-19 14:55:58 -0800116 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung8d31fd22023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung8d31fd22023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung47c01172023-07-17 12:40:43 -0700279 Mutex::Autolock _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung8d31fd22023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung8d31fd22023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung8d31fd22023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700318 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700325 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
326 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung8d31fd22023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hunga5a7fc92023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hungd29af632023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hungd29af632023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hungd29af632023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hung225aef62022-12-06 16:33:20 -0800391 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800392}
393
Andy Hunga5a7fc92023-06-23 19:27:19 -0700394TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800395 // just stop the track on deletion, associated resources
396 // will be freed from the main thread once all pending buffers have
397 // been played. Unless it's not in the active track list, in which
398 // case we free everything now...
399 mTrack->destroy();
400}
401
Andy Hunga5a7fc92023-06-23 19:27:19 -0700402Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800403 std::optional<media::SharedFileRegion>* _aidl_return) {
404 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
405 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800406}
407
Andy Hunga5a7fc92023-06-23 19:27:19 -0700408Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800409 *_aidl_return = mTrack->start();
410 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800411}
412
Andy Hunga5a7fc92023-06-23 19:27:19 -0700413Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800414 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800415 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800416}
417
Andy Hunga5a7fc92023-06-23 19:27:19 -0700418Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800419 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800420 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800421}
422
Andy Hunga5a7fc92023-06-23 19:27:19 -0700423Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800424 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800425 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800426}
427
Andy Hunga5a7fc92023-06-23 19:27:19 -0700428Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800429 int32_t* _aidl_return) {
430 *_aidl_return = mTrack->attachAuxEffect(effectId);
431 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800432}
433
Andy Hunga5a7fc92023-06-23 19:27:19 -0700434Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800435 int32_t* _aidl_return) {
436 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
437 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700438}
439
Andy Hunga5a7fc92023-06-23 19:27:19 -0700440Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800441 int32_t* _aidl_return) {
442 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
443 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800444}
445
Andy Hunga5a7fc92023-06-23 19:27:19 -0700446Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800447 int32_t* _aidl_return) {
448 AudioTimestamp legacy;
449 *_aidl_return = mTrack->getTimestamp(legacy);
450 if (*_aidl_return != OK) {
451 return Status::ok();
452 }
Andy Hung973638a2020-12-08 20:47:45 -0800453 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800454 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800455}
456
Andy Hunga5a7fc92023-06-23 19:27:19 -0700457Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800458 mTrack->signal();
459 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800460}
461
Andy Hunga5a7fc92023-06-23 19:27:19 -0700462Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800463 const media::VolumeShaperConfiguration& configuration,
464 const media::VolumeShaperOperation& operation,
465 int32_t* _aidl_return) {
466 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
467 *_aidl_return = conf->readFromParcelable(configuration);
468 if (*_aidl_return != OK) {
469 return Status::ok();
470 }
471
472 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
473 *_aidl_return = op->readFromParcelable(operation);
474 if (*_aidl_return != OK) {
475 return Status::ok();
476 }
477
478 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
479 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700480}
481
Andy Hunga5a7fc92023-06-23 19:27:19 -0700482Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800483 int32_t id,
484 std::optional<media::VolumeShaperState>* _aidl_return) {
485 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
486 if (legacy == nullptr) {
487 _aidl_return->reset();
488 return Status::ok();
489 }
490 media::VolumeShaperState aidl;
491 legacy->writeToParcelable(&aidl);
492 *_aidl_return = aidl;
493 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800494}
495
Andy Hunga5a7fc92023-06-23 19:27:19 -0700496Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000497 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800498{
499 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
500 const status_t status = mTrack->getDualMonoMode(&mode)
501 ?: AudioValidator::validateDualMonoMode(mode);
502 if (status == OK) {
503 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
504 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
505 }
506 return binderStatusFromStatusT(status);
507}
508
Andy Hunga5a7fc92023-06-23 19:27:19 -0700509Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000510 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800511{
512 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
513 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
514 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
515 ?: mTrack->setDualMonoMode(localMonoMode));
516}
517
Andy Hunga5a7fc92023-06-23 19:27:19 -0700518Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800519{
520 float leveldB = -std::numeric_limits<float>::infinity();
521 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
522 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
523 if (status == OK) *_aidl_return = leveldB;
524 return binderStatusFromStatusT(status);
525}
526
Andy Hunga5a7fc92023-06-23 19:27:19 -0700527Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800528{
529 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
530 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
531}
532
Andy Hunga5a7fc92023-06-23 19:27:19 -0700533Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000534 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800535{
536 audio_playback_rate_t localPlaybackRate{};
537 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
538 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
539 if (status == NO_ERROR) {
540 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
541 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
542 }
543 return binderStatusFromStatusT(status);
544}
545
Andy Hunga5a7fc92023-06-23 19:27:19 -0700546Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000547 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800548{
549 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
550 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
551 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
552 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
553}
554
Eric Laurent81784c32012-11-19 14:55:58 -0800555// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800556// AppOp for audio playback
557// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700558
559// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700560sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700561 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000562 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700563 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800564{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700565 Vector<String16> packages;
566 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000567 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700568 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700569 if (packages.isEmpty()) {
570 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
571 id,
572 attr.usage,
573 uid);
574 return nullptr;
575 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800576 }
577 // stream type has been filtered by audio policy to indicate whether it can be muted
578 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700579 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700580 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800581 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700582 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
583 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
584 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
585 id, attr.flags);
586 return nullptr;
587 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700588 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700589}
590
Andy Hung87c693c2023-07-06 20:56:16 -0700591OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700592 const AttributionSourceState& attributionSource,
593 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700594 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700595 mHasOpPlayAudio(true),
596 mAttributionSource(attributionSource),
597 mUsage((int32_t)usage),
598 mId(id),
599 mUid(uid),
600 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
601 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800602
Andy Hung8d31fd22023-06-26 19:20:57 -0700603OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800604{
605 if (mOpCallback != 0) {
606 mAppOpsManager.stopWatchingMode(mOpCallback);
607 }
608 mOpCallback.clear();
609}
610
Andy Hung8d31fd22023-06-26 19:20:57 -0700611void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700612{
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700613 checkPlayAudioForUsage();
Svet Ganov33761132021-05-13 22:51:08 +0000614 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700615 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700616 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700617 mPackageName, mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700618 }
619}
620
Andy Hung8d31fd22023-06-26 19:20:57 -0700621bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800622 return mHasOpPlayAudio.load();
623}
624
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700625// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800626// - not called from constructor due to check on UID,
627// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung8d31fd22023-06-26 19:20:57 -0700628void OpPlayAudioMonitor::checkPlayAudioForUsage()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800629{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700630 const bool hasAppOps = mAttributionSource.packageName.has_value()
631 && mAppOpsManager.checkAudioOpNoThrow(
632 AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
633 AppOpsManager::MODE_ALLOWED;
634
635 bool shouldChange = !hasAppOps; // check if we need to update.
636 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
637 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
638 auto thread = mThread.promote();
Andy Hungee58e4a2023-07-07 13:47:37 -0700639 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700640 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87c693c2023-07-06 20:56:16 -0700641 Mutex::Autolock _l(thread->mutex());
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700642 thread->broadcast_l();
643 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800644 }
645}
646
Andy Hung8d31fd22023-06-26 19:20:57 -0700647OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800648 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
649{ }
650
Andy Hung8d31fd22023-06-26 19:20:57 -0700651void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800652 const String16& packageName) {
653 // we only have uid, so we need to check all package names anyway
654 UNUSED(packageName);
655 if (op != AppOpsManager::OP_PLAY_AUDIO) {
656 return;
657 }
658 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
659 if (monitor != NULL) {
660 monitor->checkPlayAudioForUsage();
661 }
662}
663
Eric Laurent9066ad32019-05-20 14:40:10 -0700664// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700665void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700666 uid_t uid, Vector<String16>& packages)
667{
668 PermissionController permissionController;
669 permissionController.getPackagesForUid(uid, packages);
670}
671
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800672// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700673#undef LOG_TAG
674#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800675
Andy Hung8d31fd22023-06-26 19:20:57 -0700676/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700677sp<IAfTrack> IAfTrack::create(
678 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700679 const sp<Client>& client,
680 audio_stream_type_t streamType,
681 const audio_attributes_t& attr,
682 uint32_t sampleRate,
683 audio_format_t format,
684 audio_channel_mask_t channelMask,
685 size_t frameCount,
686 void *buffer,
687 size_t bufferSize,
688 const sp<IMemory>& sharedBuffer,
689 audio_session_t sessionId,
690 pid_t creatorPid,
691 const AttributionSourceState& attributionSource,
692 audio_output_flags_t flags,
693 track_type type,
694 audio_port_handle_t portId,
695 /** default behaviour is to start when there are as many frames
696 * ready as possible (aka. Buffer is full). */
697 size_t frameCountToBeReady,
698 float speed,
699 bool isSpatialized,
700 bool isBitPerfect) {
Andy Hung87c693c2023-07-06 20:56:16 -0700701 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700702 client,
703 streamType,
704 attr,
705 sampleRate,
706 format,
707 channelMask,
708 frameCount,
709 buffer,
710 bufferSize,
711 sharedBuffer,
712 sessionId,
713 creatorPid,
714 attributionSource,
715 flags,
716 type,
717 portId,
718 frameCountToBeReady,
719 speed,
720 isSpatialized,
721 isBitPerfect);
722}
723
Eric Laurent81784c32012-11-19 14:55:58 -0800724// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700725Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700726 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800727 const sp<Client>& client,
728 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700729 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800730 uint32_t sampleRate,
731 audio_format_t format,
732 audio_channel_mask_t channelMask,
733 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700734 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700735 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800736 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800737 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700738 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000739 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700740 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800741 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100742 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000743 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200744 float speed,
jiabinc658e452022-10-21 20:52:21 +0000745 bool isSpatialized,
746 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700747 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700748 // TODO: Using unsecurePointer() has some associated security pitfalls
749 // (see declaration for details).
750 // Either document why it is safe in this case or address the
751 // issue (e.g. by copying).
752 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700753 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700754 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000755 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700756 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800757 type,
758 portId,
759 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700760 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800761 // mRetryCount initialized later when needed
762 mSharedBuffer(sharedBuffer),
763 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700764 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800765 mAuxBuffer(NULL),
766 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700767 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700768 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700769 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700770 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700771 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800772 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800773 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700774 /* The track might not play immediately after being active, similarly as if its volume was 0.
775 * When the track starts playing, its volume will be computed. */
776 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800777 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700778 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000779 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200780 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000781 mIsSpatialized(isSpatialized),
782 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800783{
Eric Laurent83b88082014-06-20 18:31:16 -0700784 // client == 0 implies sharedBuffer == 0
785 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
786
Andy Hung9d84af52018-09-12 18:03:44 -0700787 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700788 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700789
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700790 if (mCblk == NULL) {
791 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800792 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700793
Svet Ganov33761132021-05-13 22:51:08 +0000794 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700795 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
796 ALOGE("%s(%d): no more tracks available", __func__, mId);
797 releaseCblk(); // this makes the track invalid.
798 return;
799 }
800
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700801 if (sharedBuffer == 0) {
802 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700803 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700804 } else {
805 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100806 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700807 }
808 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700809 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700810
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700811 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700812 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700813 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
814 // race with setSyncEvent(). However, if we call it, we cannot properly start
815 // static fast tracks (SoundPool) immediately after stopping.
816 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700817 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
818 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700819 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700820 // FIXME This is too eager. We allocate a fast track index before the
821 // fast track becomes active. Since fast tracks are a scarce resource,
822 // this means we are potentially denying other more important fast tracks from
823 // being created. It would be better to allocate the index dynamically.
824 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700825 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700826 }
Andy Hung8946a282018-04-19 20:04:56 -0700827
Dean Wheatley7b036912020-06-18 16:22:11 +1000828 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700829#ifdef TEE_SINK
830 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800831 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700832#endif
jiabin57303cc2018-12-18 15:45:57 -0800833
jiabineb3bda02020-06-30 14:07:03 -0700834 if (thread->supportsHapticPlayback()) {
835 // If the track is attached to haptic playback thread, it is potentially to have
836 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
837 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800838 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000839 std::string packageName = attributionSource.packageName.has_value() ?
840 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800841 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700842 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800843 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800844
845 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700846 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800847 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800848}
849
Andy Hung8d31fd22023-06-26 19:20:57 -0700850Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800851{
Andy Hung9d84af52018-09-12 18:03:44 -0700852 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700853
854 // The destructor would clear mSharedBuffer,
855 // but it will not push the decremented reference count,
856 // leaving the client's IMemory dangling indefinitely.
857 // This prevents that leak.
858 if (mSharedBuffer != 0) {
859 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700860 }
Eric Laurent81784c32012-11-19 14:55:58 -0800861}
862
Andy Hung8d31fd22023-06-26 19:20:57 -0700863status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700864{
865 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700866 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700867 status = NO_MEMORY;
868 }
869 return status;
870}
871
Andy Hung8d31fd22023-06-26 19:20:57 -0700872void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800873{
874 // NOTE: destroyTrack_l() can remove a strong reference to this Track
875 // by removing it from mTracks vector, so there is a risk that this Tracks's
876 // destructor is called. As the destructor needs to lock mLock,
877 // we must acquire a strong reference on this Track before locking mLock
878 // here so that the destructor is called only when exiting this function.
879 // On the other hand, as long as Track::destroy() is only called by
880 // TrackHandle destructor, the TrackHandle still holds a strong ref on
881 // this Track with its member mTrack.
882 sp<Track> keep(this);
883 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700884 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700885 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800886 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -0700887 Mutex::Autolock _l(thread->mutex());
888 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700889 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000890 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700891 }
892 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700893 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800894 }
895 }
896}
897
Andy Hung8d31fd22023-06-26 19:20:57 -0700898void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800899{
Eric Laurent973db022018-11-20 14:54:31 -0800900 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700901 " Format Chn mask SRate "
902 "ST Usg CT "
903 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000904 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700905 "%s\n",
906 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800907}
908
Andy Hung8d31fd22023-06-26 19:20:57 -0700909void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800910{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700911 char trackType;
912 switch (mType) {
913 case TYPE_DEFAULT:
914 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700915 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700916 trackType = 'S'; // static
917 } else {
918 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800919 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700920 break;
921 case TYPE_PATCH:
922 trackType = 'P';
923 break;
924 default:
925 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800926 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700927
928 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700929 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700930 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700931 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700932 }
933
Eric Laurent81784c32012-11-19 14:55:58 -0800934 char nowInUnderrun;
935 switch (mObservedUnderruns.mBitFields.mMostRecent) {
936 case UNDERRUN_FULL:
937 nowInUnderrun = ' ';
938 break;
939 case UNDERRUN_PARTIAL:
940 nowInUnderrun = '<';
941 break;
942 case UNDERRUN_EMPTY:
943 nowInUnderrun = '*';
944 break;
945 default:
946 nowInUnderrun = '?';
947 break;
948 }
Andy Hungda540db2017-04-20 14:06:17 -0700949
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700950 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700951 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700952 case FS_INVALID:
953 fillingStatus = 'I';
954 break;
955 case FS_FILLING:
956 fillingStatus = 'f';
957 break;
958 case FS_FILLED:
959 fillingStatus = 'F';
960 break;
961 case FS_ACTIVE:
962 fillingStatus = 'A';
963 break;
964 default:
965 fillingStatus = '?';
966 break;
967 }
968
969 // clip framesReadySafe to max representation in dump
970 const size_t framesReadySafe =
971 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
972
973 // obtain volumes
974 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
975 const std::pair<float /* volume */, bool /* active */> vsVolume =
976 mVolumeHandler->getLastVolume();
977
978 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
979 // as it may be reduced by the application.
980 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
981 // Check whether the buffer size has been modified by the app.
982 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
983 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
984 ? 'e' /* error */ : ' ' /* identical */;
985
Eric Laurent973db022018-11-20 14:54:31 -0800986 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700987 "%08X %08X %6u "
988 "%2u %3x %2x "
989 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000990 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800991 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700992 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700993 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -0800994 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -0800995 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700996 mCblk->mFlags,
997
Eric Laurent81784c32012-11-19 14:55:58 -0800998 mFormat,
999 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001000 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001001
1002 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001003 mAttr.usage,
1004 mAttr.content_type,
1005
1006 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001007 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1008 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001009 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1010 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001011
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001012 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001013 bufferSizeInFrames,
1014 modifiedBufferChar,
1015 framesReadySafe,
1016 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001017 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001018 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001019 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1020 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001021 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001022
1023 if (isServerLatencySupported()) {
1024 double latencyMs;
1025 bool fromTrack;
1026 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1027 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1028 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1029 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001030 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001031 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001032 }
1033 }
1034 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001035}
1036
Andy Hung8d31fd22023-06-26 19:20:57 -07001037uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001038 return mAudioTrackServerProxy->getSampleRate();
1039}
1040
Eric Laurent81784c32012-11-19 14:55:58 -08001041// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001042status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001043{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001044 ServerProxy::Buffer buf;
1045 size_t desiredFrames = buffer->frameCount;
1046 buf.mFrameCount = desiredFrames;
1047 status_t status = mServerProxy->obtainBuffer(&buf);
1048 buffer->frameCount = buf.mFrameCount;
1049 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001050 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001051 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001052 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001053 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001054 } else {
1055 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001056 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001057 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001058}
1059
Andy Hung8d31fd22023-06-26 19:20:57 -07001060void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001061{
1062 interceptBuffer(*buffer);
1063 TrackBase::releaseBuffer(buffer);
1064}
1065
1066// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001067void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001068 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001069 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001070 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001071 if (frameCount == 0) {
1072 return; // No audio to intercept.
1073 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1074 // does not allow 0 frame size request contrary to getNextBuffer
1075 }
1076 for (auto& teePatch : mTeePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001077 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001078 const size_t framesWritten = patchRecord->writeFrames(
1079 sourceBuffer.i8, frameCount, mFrameSize);
1080 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001081 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001082 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001083 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001084 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001085 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1086 using namespace std::chrono_literals;
1087 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001088 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001089 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001090}
1091
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001092// ExtendedAudioBufferProvider interface
1093
Andy Hung27876c02014-09-09 18:07:55 -07001094// framesReady() may return an approximation of the number of frames if called
1095// from a different thread than the one calling Proxy->obtainBuffer() and
1096// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1097// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001098size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001099 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1100 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1101 // The remainder of the buffer is not drained.
1102 return 0;
1103 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001104 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001105}
1106
Andy Hung8d31fd22023-06-26 19:20:57 -07001107int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001108{
1109 return mAudioTrackServerProxy->framesReleased();
1110}
1111
Andy Hung8d31fd22023-06-26 19:20:57 -07001112void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001113{
1114 // This call comes from a FastTrack and should be kept lockless.
1115 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001116 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001117
Andy Hung818e7a32016-02-16 18:08:07 -08001118 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001119
1120 // Compute latency.
1121 // TODO: Consider whether the server latency may be passed in by FastMixer
1122 // as a constant for all active FastTracks.
1123 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1124 mServerLatencyFromTrack.store(true);
1125 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001126}
1127
Eric Laurent81784c32012-11-19 14:55:58 -08001128// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001129bool Track::isReady() const {
1130 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001131 return true;
1132 }
1133
Eric Laurent16498512014-03-17 17:22:08 -07001134 if (isStopping()) {
1135 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001136 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001137 }
Eric Laurent81784c32012-11-19 14:55:58 -08001138 return true;
1139 }
1140
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001141 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001142 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1143 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1144 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1145 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001146
1147 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1148 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1149 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001150 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001151 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001152 return true;
1153 }
1154 return false;
1155}
1156
Andy Hung8d31fd22023-06-26 19:20:57 -07001157status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001158 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001159{
1160 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001161 ALOGV("%s(%d): calling pid %d session %d",
1162 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001163
Andy Hung87c693c2023-07-06 20:56:16 -07001164 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001165 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001166 if (isOffloaded()) {
Andy Hung583043b2023-07-17 17:05:00 -07001167 Mutex::Autolock _laf(thread->afThreadCallback()->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001168 Mutex::Autolock _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001169 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung583043b2023-07-17 17:05:00 -07001170 if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001171 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001172 invalidate();
1173 return PERMISSION_DENIED;
1174 }
1175 }
Andy Hung87c693c2023-07-06 20:56:16 -07001176 Mutex::Autolock _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001177 track_state state = mState;
1178 // here the track could be either new, or restarted
1179 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001180
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001181 // initial state-stopping. next state-pausing.
1182 // What if resume is called ?
1183
Zhou Song1ed46a22020-08-17 15:36:56 +08001184 if (state == FLUSHED) {
1185 // avoid underrun glitches when starting after flush
1186 reset();
1187 }
1188
kuowei.li576f1362021-05-11 18:02:32 +08001189 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1190 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001191 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001192 if (mResumeToStopping) {
1193 // happened we need to resume to STOPPING_1
1194 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001195 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1196 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001197 } else {
1198 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001199 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1200 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001201 }
Eric Laurent81784c32012-11-19 14:55:58 -08001202 } else {
1203 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001204 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1205 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001206 }
1207
Andy Hung87c693c2023-07-06 20:56:16 -07001208 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001209
1210 // states to reset position info for pcm tracks
1211 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001212 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1213 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001214
1215 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1216 // Start point of track -> sink frame map. If the HAL returns a
1217 // frame position smaller than the first written frame in
1218 // updateTrackFrameInfo, the timestamp can be interpolated
1219 // instead of using a larger value.
1220 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1221 playbackThread->framesWritten());
1222 }
Andy Hunge10393e2015-06-12 13:59:33 -07001223 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001224 if (isFastTrack()) {
1225 // refresh fast track underruns on start because that field is never cleared
1226 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1227 // after stop.
1228 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1229 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001230 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001231 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001232 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001233 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001234 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001235 mState = state;
1236 }
1237 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001238
Andy Hungb68f5eb2019-12-03 16:49:17 -08001239 // Audio timing metrics are computed a few mix cycles after starting.
1240 {
1241 mLogStartCountdown = LOG_START_COUNTDOWN;
1242 mLogStartTimeNs = systemTime();
1243 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001244 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1245 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001246 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001247 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001248
Andy Hung1d3556d2018-03-29 16:30:14 -07001249 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1250 // for streaming tracks, remove the buffer read stop limit.
1251 mAudioTrackServerProxy->start();
1252 }
1253
Eric Laurentbfb1b832013-01-07 09:53:42 -08001254 // track was already in the active list, not a problem
1255 if (status == ALREADY_EXISTS) {
1256 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001257 } else {
1258 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1259 // It is usually unsafe to access the server proxy from a binder thread.
1260 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1261 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1262 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001263 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001264 ServerProxy::Buffer buffer;
1265 buffer.mFrameCount = 1;
1266 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001267 }
jiabin7434e812023-06-27 18:22:35 +00001268 if (status == NO_ERROR) {
1269 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1270 }
Eric Laurent81784c32012-11-19 14:55:58 -08001271 } else {
1272 status = BAD_VALUE;
1273 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001274 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001275 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001276 const sp<IAudioManager> audioManager =
1277 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001278 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1279 std::unique_ptr<os::PersistableBundle> bundle =
1280 std::make_unique<os::PersistableBundle>();
1281 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1282 isSpatialized());
1283 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1284 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1285 status_t result = audioManager->portEvent(mPortId,
1286 PLAYER_UPDATE_FORMAT, bundle);
1287 if (result != OK) {
1288 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1289 __func__, mPortId, result);
1290 }
1291 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001292 }
Eric Laurent81784c32012-11-19 14:55:58 -08001293 return status;
1294}
1295
Andy Hung8d31fd22023-06-26 19:20:57 -07001296void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001297{
Andy Hungc0691382018-09-12 18:01:57 -07001298 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001299 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001300 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001301 Mutex::Autolock _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001302 track_state state = mState;
1303 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1304 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001305 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1306 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001307 reset();
1308 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001309 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001310 mState = STOPPED;
1311 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001312 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1313 // presentation is complete
1314 // For an offloaded track this starts a drain and state will
1315 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001316 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001317 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001318 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001319 }
Eric Laurent81784c32012-11-19 14:55:58 -08001320 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001321 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001322 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1323 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001324 }
jiabin7434e812023-06-27 18:22:35 +00001325 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001326 }
1327}
1328
Andy Hung8d31fd22023-06-26 19:20:57 -07001329void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001330{
Andy Hungc0691382018-09-12 18:01:57 -07001331 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001332 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001333 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001334 Mutex::Autolock _l(thread->mutex());
1335 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001336 switch (mState) {
1337 case STOPPING_1:
1338 case STOPPING_2:
1339 if (!isOffloaded()) {
1340 /* nothing to do if track is not offloaded */
1341 break;
1342 }
1343
1344 // Offloaded track was draining, we need to carry on draining when resumed
1345 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001346 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001347 case ACTIVE:
1348 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001349 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001350 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1351 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001352 if (isOffloadedOrDirect()) {
1353 mPauseHwPending = true;
1354 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001355 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001356 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001357
Eric Laurentbfb1b832013-01-07 09:53:42 -08001358 default:
1359 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001360 }
jiabin7434e812023-06-27 18:22:35 +00001361 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1362 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001363 }
1364}
1365
Andy Hung8d31fd22023-06-26 19:20:57 -07001366void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001367{
Andy Hungc0691382018-09-12 18:01:57 -07001368 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001369 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001370 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001371 Mutex::Autolock _l(thread->mutex());
1372 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001373
Phil Burk4bb650b2016-09-09 12:11:17 -07001374 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1375 // Otherwise the flush would not be done until the track is resumed.
1376 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001377 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001378 (void)mServerProxy->flushBufferIfNeeded();
1379 }
1380
Eric Laurentbfb1b832013-01-07 09:53:42 -08001381 if (isOffloaded()) {
1382 // If offloaded we allow flush during any state except terminated
1383 // and keep the track active to avoid problems if user is seeking
1384 // rapidly and underlying hardware has a significant delay handling
1385 // a pause
1386 if (isTerminated()) {
1387 return;
1388 }
1389
Andy Hung9d84af52018-09-12 18:03:44 -07001390 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001391 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001392
1393 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001394 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1395 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001396 mState = ACTIVE;
1397 }
1398
Haynes Mathew George7844f672014-01-15 12:32:55 -08001399 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001400 mResumeToStopping = false;
1401 } else {
1402 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1403 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1404 return;
1405 }
1406 // No point remaining in PAUSED state after a flush => go to
1407 // FLUSHED state
1408 mState = FLUSHED;
1409 // do not reset the track if it is still in the process of being stopped or paused.
1410 // this will be done by prepareTracks_l() when the track is stopped.
1411 // prepareTracks_l() will see mState == FLUSHED, then
1412 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001413 if (isDirect()) {
1414 mFlushHwPending = true;
1415 }
Andy Hung87c693c2023-07-06 20:56:16 -07001416 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001417 reset();
1418 }
Eric Laurent81784c32012-11-19 14:55:58 -08001419 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001420 // Prevent flush being lost if the track is flushed and then resumed
1421 // before mixer thread can run. This is important when offloading
1422 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001423 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001424 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1425 // new data
1426 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001427 }
1428}
1429
Haynes Mathew George7844f672014-01-15 12:32:55 -08001430// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001431void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001432{
Andy Hung920f6572022-10-06 12:09:49 -07001433 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001434 return;
Andy Hung920f6572022-10-06 12:09:49 -07001435 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001436
Phil Burk4bb650b2016-09-09 12:11:17 -07001437 // Clear the client ring buffer so that the app can prime the buffer while paused.
1438 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1439 mServerProxy->flushBufferIfNeeded();
1440
Haynes Mathew George7844f672014-01-15 12:32:55 -08001441 mFlushHwPending = false;
1442}
1443
Andy Hung8d31fd22023-06-26 19:20:57 -07001444void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001445{
1446 mPauseHwPending = false;
1447}
1448
Andy Hung8d31fd22023-06-26 19:20:57 -07001449void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001450{
1451 // Do not reset twice to avoid discarding data written just after a flush and before
1452 // the audioflinger thread detects the track is stopped.
1453 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001454 // Force underrun condition to avoid false underrun callback until first data is
1455 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001456 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001457 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001458 mResetDone = true;
1459 if (mState == FLUSHED) {
1460 mState = IDLE;
1461 }
1462 }
1463}
1464
Andy Hung8d31fd22023-06-26 19:20:57 -07001465status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001466{
Andy Hung87c693c2023-07-06 20:56:16 -07001467 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001468 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001469 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001470 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001471 } else if (thread->type() == IAfThreadBase::DIRECT
1472 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001473 return thread->setParameters(keyValuePairs);
1474 } else {
1475 return PERMISSION_DENIED;
1476 }
1477}
1478
Andy Hung8d31fd22023-06-26 19:20:57 -07001479status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001480 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001481 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001482 if (thread == 0) {
1483 ALOGE("thread is dead");
1484 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001485 } else if (thread->type() == IAfThreadBase::DIRECT
1486 || thread->type() == IAfThreadBase::OFFLOAD) {
1487 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001488 return directOutputThread->selectPresentation(presentationId, programId);
1489 }
1490 return INVALID_OPERATION;
1491}
1492
Andy Hung8d31fd22023-06-26 19:20:57 -07001493VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001494 const sp<VolumeShaper::Configuration>& configuration,
1495 const sp<VolumeShaper::Operation>& operation)
1496{
Andy Hung398ffa22022-12-13 19:19:53 -08001497 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001498
1499 if (isOffloadedOrDirect()) {
1500 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001501 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001502 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001503 Mutex::Autolock _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001504 thread->broadcast_l();
1505 }
1506 }
1507 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001508}
1509
Andy Hung8d31fd22023-06-26 19:20:57 -07001510sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001511{
1512 // Note: We don't check if Thread exists.
1513
1514 // mVolumeHandler is thread safe.
1515 return mVolumeHandler->getVolumeShaperState(id);
1516}
1517
Andy Hung8d31fd22023-06-26 19:20:57 -07001518void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001519{
jiabin76d94692022-12-15 21:51:21 +00001520 mFinalVolumeLeft = volumeLeft;
1521 mFinalVolumeRight = volumeRight;
1522 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001523 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1524 mFinalVolume = volume;
1525 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001526 mLogForceVolumeUpdate = true;
1527 }
1528 if (mLogForceVolumeUpdate) {
1529 mLogForceVolumeUpdate = false;
1530 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001531 }
1532}
1533
Andy Hung8d31fd22023-06-26 19:20:57 -07001534void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001535{
Eric Laurent49e39282022-06-24 18:42:45 +02001536 // Do not forward metadata for PatchTrack with unspecified stream type
1537 if (mStreamType == AUDIO_STREAM_PATCH) {
1538 return;
1539 }
1540
Eric Laurent94579172020-11-20 18:41:04 +01001541 playback_track_metadata_v7_t metadata;
1542 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001543 .usage = mAttr.usage,
1544 .content_type = mAttr.content_type,
1545 .gain = mFinalVolume,
1546 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001547
1548 // When attributes are undefined, derive default values from stream type.
1549 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1550 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1551 switch (mStreamType) {
1552 case AUDIO_STREAM_VOICE_CALL:
1553 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1554 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1555 break;
1556 case AUDIO_STREAM_SYSTEM:
1557 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1558 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1559 break;
1560 case AUDIO_STREAM_RING:
1561 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1562 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1563 break;
1564 case AUDIO_STREAM_MUSIC:
1565 metadata.base.usage = AUDIO_USAGE_MEDIA;
1566 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1567 break;
1568 case AUDIO_STREAM_ALARM:
1569 metadata.base.usage = AUDIO_USAGE_ALARM;
1570 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1571 break;
1572 case AUDIO_STREAM_NOTIFICATION:
1573 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1574 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1575 break;
1576 case AUDIO_STREAM_DTMF:
1577 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1578 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1579 break;
1580 case AUDIO_STREAM_ACCESSIBILITY:
1581 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1582 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1583 break;
1584 case AUDIO_STREAM_ASSISTANT:
1585 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1586 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1587 break;
1588 case AUDIO_STREAM_REROUTING:
1589 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1590 // unknown content type
1591 break;
1592 case AUDIO_STREAM_CALL_ASSISTANT:
1593 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1594 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1595 break;
1596 default:
1597 break;
1598 }
1599 }
1600
Eric Laurent78b07302022-10-07 16:20:34 +02001601 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001602 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1603 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001604}
1605
Andy Hung8d31fd22023-06-26 19:20:57 -07001606void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001607 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001608 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001609 mTeePatches = mTeePatchesToUpdate.value();
1610 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1611 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001612 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001613 }
1614 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001615 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001616}
1617
Andy Hung16ed0da2023-07-14 11:45:38 -07001618void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001619 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1620 "%s, existing tee patches to update will be ignored", __func__);
1621 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1622}
1623
Vlad Popae8d99472022-06-30 16:02:48 +02001624// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001625void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001626 IAudioManager>& audioManager, mute_state_t muteState)
1627{
1628 if (mMuteState == muteState) {
1629 // mute state did not change, do nothing
1630 return;
1631 }
1632
1633 status_t result = UNKNOWN_ERROR;
1634 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1635 if (mMuteEventExtras == nullptr) {
1636 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1637 }
1638 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1639 static_cast<int>(muteState));
1640
1641 result = audioManager->portEvent(mPortId,
1642 PLAYER_UPDATE_MUTED,
1643 mMuteEventExtras);
1644 }
1645
1646 if (result == OK) {
1647 mMuteState = muteState;
1648 } else {
1649 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1650 __func__,
1651 id(),
1652 mPortId,
1653 result);
1654 }
1655}
1656
Andy Hung8d31fd22023-06-26 19:20:57 -07001657status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001658{
Andy Hung818e7a32016-02-16 18:08:07 -08001659 if (!isOffloaded() && !isDirect()) {
1660 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001661 }
Andy Hung87c693c2023-07-06 20:56:16 -07001662 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001663 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001664 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001665 }
Phil Burk6140c792015-03-19 14:30:21 -07001666
Andy Hung87c693c2023-07-06 20:56:16 -07001667 Mutex::Autolock _l(thread->mutex());
1668 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001669 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001670}
1671
Andy Hung8d31fd22023-06-26 19:20:57 -07001672status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001673{
Andy Hung87c693c2023-07-06 20:56:16 -07001674 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001675 if (thread == nullptr) {
1676 return DEAD_OBJECT;
1677 }
Eric Laurent81784c32012-11-19 14:55:58 -08001678
Andy Hung87c693c2023-07-06 20:56:16 -07001679 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001680 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001681 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001682 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001683 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001684
Eric Laurent6c796322019-04-09 14:13:17 -07001685 if (EffectId != 0 && status == NO_ERROR) {
1686 status = dstThread->attachAuxEffect(this, EffectId);
1687 if (status == NO_ERROR) {
1688 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001689 }
Eric Laurent6c796322019-04-09 14:13:17 -07001690 }
1691
1692 if (status != NO_ERROR && srcThread != nullptr) {
1693 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001694 }
1695 return status;
1696}
1697
Andy Hung8d31fd22023-06-26 19:20:57 -07001698void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001699{
1700 mAuxEffectId = EffectId;
1701 mAuxBuffer = buffer;
1702}
1703
Andy Hung59de4262021-06-14 10:53:54 -07001704// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001705bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001706 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001707{
Andy Hung818e7a32016-02-16 18:08:07 -08001708 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1709 // This assists in proper timestamp computation as well as wakelock management.
1710
Eric Laurent81784c32012-11-19 14:55:58 -08001711 // a track is considered presented when the total number of frames written to audio HAL
1712 // corresponds to the number of frames written when presentationComplete() is called for the
1713 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001714 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1715 // to detect when all frames have been played. In this case framesWritten isn't
1716 // useful because it doesn't always reflect whether there is data in the h/w
1717 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001718 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1719 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001720 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001721 if (mPresentationCompleteFrames == 0) {
1722 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001723 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001724 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1725 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001726 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001727 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001728
Andy Hungc54b1ff2016-02-23 14:07:07 -08001729 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001730 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001731 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001732 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1733 __func__, mId, (complete ? "complete" : "waiting"),
1734 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001735 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001736 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001737 && mAudioTrackServerProxy->isDrained();
1738 }
1739
1740 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001741 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001742 return true;
1743 }
1744 return false;
1745}
1746
Andy Hung59de4262021-06-14 10:53:54 -07001747// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001748bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001749{
1750 // For Offloaded or Direct tracks.
1751
1752 // For a direct track, we incorporated time based testing for presentationComplete.
1753
1754 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1755 // to detect when all frames have been played. In this case latencyMs isn't
1756 // useful because it doesn't always reflect whether there is data in the h/w
1757 // buffers, particularly if a track has been paused and resumed during draining
1758
1759 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1760 if (mPresentationCompleteTimeNs == 0) {
1761 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1762 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1763 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1764 }
1765
1766 bool complete;
1767 if (isOffloaded()) {
1768 complete = true;
1769 } else { // Direct
1770 complete = systemTime() >= mPresentationCompleteTimeNs;
1771 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1772 }
1773 if (complete) {
1774 notifyPresentationComplete();
1775 return true;
1776 }
1777 return false;
1778}
1779
Andy Hung8d31fd22023-06-26 19:20:57 -07001780void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001781{
1782 // This only triggers once. TODO: should we enforce this?
1783 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1784 mAudioTrackServerProxy->setStreamEndDone();
1785}
1786
Andy Hung8d31fd22023-06-26 19:20:57 -07001787void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001788{
Andy Hung068e08e2023-05-15 19:02:55 -07001789 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1790 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001791 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001792 (*it)->trigger();
1793 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001794 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001795 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001796 }
1797 }
1798}
1799
1800// implement VolumeBufferProvider interface
1801
Andy Hung8d31fd22023-06-26 19:20:57 -07001802gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001803{
1804 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1805 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001806 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1807 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1808 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001809 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001810 if (vl > GAIN_FLOAT_UNITY) {
1811 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001812 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001813 if (vr > GAIN_FLOAT_UNITY) {
1814 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001815 }
1816 // now apply the cached master volume and stream type volume;
1817 // this is trusted but lacks any synchronization or barrier so may be stale
1818 float v = mCachedVolume;
1819 vl *= v;
1820 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001821 // re-combine into packed minifloat
1822 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001823 // FIXME look at mute, pause, and stop flags
1824 return vlr;
1825}
1826
Andy Hung8d31fd22023-06-26 19:20:57 -07001827status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001828 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001829{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001830 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001831 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1832 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001833 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1834 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001835 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001836 event->cancel();
1837 return INVALID_OPERATION;
1838 }
1839 (void) TrackBase::setSyncEvent(event);
1840 return NO_ERROR;
1841}
1842
Andy Hung8d31fd22023-06-26 19:20:57 -07001843void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001844{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001845 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001846 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001847}
1848
Andy Hung8d31fd22023-06-26 19:20:57 -07001849void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001850{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001851 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001852 signalClientFlag(CBLK_DISABLED);
1853}
1854
Andy Hung8d31fd22023-06-26 19:20:57 -07001855void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001856{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001857 // FIXME should use proxy, and needs work
1858 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001859 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001860 android_atomic_release_store(0x40000000, &cblk->mFutex);
1861 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001862 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001863}
1864
Andy Hung8d31fd22023-06-26 19:20:57 -07001865void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001866{
Andy Hung87c693c2023-07-06 20:56:16 -07001867 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001868 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001869 auto* const t = thread->asIAfPlaybackThread().get();
1870 Mutex::Autolock _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001871 t->broadcast_l();
1872 }
1873}
1874
Andy Hung8d31fd22023-06-26 19:20:57 -07001875status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001876{
1877 status_t status = INVALID_OPERATION;
1878 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001879 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001880 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001881 auto* const t = thread->asIAfPlaybackThread().get();
1882 Mutex::Autolock _l(t->mutex());
1883 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001884 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1885 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1886 }
1887 }
1888 return status;
1889}
1890
Andy Hung8d31fd22023-06-26 19:20:57 -07001891status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001892{
1893 status_t status = INVALID_OPERATION;
1894 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001895 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001896 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001897 auto* const t = thread->asIAfPlaybackThread().get();
1898 Mutex::Autolock lock(t->mutex());
1899 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001900 if (status == NO_ERROR) {
1901 mDualMonoMode = mode;
1902 }
1903 }
1904 }
1905 return status;
1906}
1907
Andy Hung8d31fd22023-06-26 19:20:57 -07001908status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001909{
1910 status_t status = INVALID_OPERATION;
1911 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001912 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001913 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001914 auto* const t = thread->asIAfPlaybackThread().get();
1915 Mutex::Autolock lock(t->mutex());
1916 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001917 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1918 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1919 }
1920 }
1921 return status;
1922}
1923
Andy Hung8d31fd22023-06-26 19:20:57 -07001924status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001925{
1926 status_t status = INVALID_OPERATION;
1927 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001928 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001929 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001930 auto* const t = thread->asIAfPlaybackThread().get();
1931 Mutex::Autolock lock(t->mutex());
1932 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001933 if (status == NO_ERROR) {
1934 mAudioDescriptionMixLevel = leveldB;
1935 }
1936 }
1937 }
1938 return status;
1939}
1940
Andy Hung8d31fd22023-06-26 19:20:57 -07001941status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001942 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001943{
1944 status_t status = INVALID_OPERATION;
1945 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001946 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001947 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001948 auto* const t = thread->asIAfPlaybackThread().get();
1949 Mutex::Autolock lock(t->mutex());
1950 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001951 ALOGD_IF((status == NO_ERROR) &&
1952 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1953 "%s: playbackRate inconsistent", __func__);
1954 }
1955 }
1956 return status;
1957}
1958
Andy Hung8d31fd22023-06-26 19:20:57 -07001959status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001960 const audio_playback_rate_t& playbackRate)
1961{
1962 status_t status = INVALID_OPERATION;
1963 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001964 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001965 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001966 auto* const t = thread->asIAfPlaybackThread().get();
1967 Mutex::Autolock lock(t->mutex());
1968 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001969 if (status == NO_ERROR) {
1970 mPlaybackRateParameters = playbackRate;
1971 }
1972 }
1973 }
1974 return status;
1975}
1976
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001977//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001978bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07001979 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001980 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001981 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001982 /* Resume is pending if track was stopping before pause was called */
1983 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07001984 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001985 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001986 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001987
1988 return false;
1989}
1990
1991//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001992void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07001993 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001994 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07001995 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001996
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001997 // Other possibility of pending resume is stopping_1 state
1998 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001999 // drain being called.
2000 if (mState == STOPPING_1) {
2001 mResumeToStopping = false;
2002 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002003}
Andy Hunge10393e2015-06-12 13:59:33 -07002004
2005//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002006void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002007 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002008 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002009 // Make the kernel frametime available.
2010 const FrameTime ft{
2011 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2012 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2013 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2014 mKernelFrameTime.store(ft);
2015 if (!audio_is_linear_pcm(mFormat)) {
2016 return;
2017 }
2018
Andy Hung818e7a32016-02-16 18:08:07 -08002019 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002020 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002021
2022 // adjust server times and set drained state.
2023 //
2024 // Our timestamps are only updated when the track is on the Thread active list.
2025 // We need to ensure that tracks are not removed before full drain.
2026 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002027 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002028 bool checked = false;
2029 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2030 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2031 // Lookup the track frame corresponding to the sink frame position.
2032 if (local.mTimeNs[i] > 0) {
2033 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2034 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002035 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002036 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002037 checked = true;
2038 }
2039 }
Andy Hunge10393e2015-06-12 13:59:33 -07002040 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002041
Andy Hung93bb5732023-05-04 21:16:34 -07002042 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2043 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002044 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002045 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002046 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002047 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002048
2049 // Compute latency info.
2050 const bool useTrackTimestamp = !drained;
2051 const double latencyMs = useTrackTimestamp
2052 ? local.getOutputServerLatencyMs(sampleRate())
2053 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2054
2055 mServerLatencyFromTrack.store(useTrackTimestamp);
2056 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002057
Andy Hung62921122020-05-18 10:47:31 -07002058 if (mLogStartCountdown > 0
2059 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2060 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2061 {
2062 if (mLogStartCountdown > 1) {
2063 --mLogStartCountdown;
2064 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2065 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002066 // startup is the difference in times for the current timestamp and our start
2067 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002068 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002069 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002070 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2071 * 1e3 / mSampleRate;
2072 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2073 " localTime:%lld startTime:%lld"
2074 " localPosition:%lld startPosition:%lld",
2075 __func__, latencyMs, startUpMs,
2076 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002077 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002078 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002079 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002080 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002081 }
Andy Hung62921122020-05-18 10:47:31 -07002082 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002083 }
Andy Hunge10393e2015-06-12 13:59:33 -07002084}
2085
Andy Hung8d31fd22023-06-26 19:20:57 -07002086bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002087 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002088 if (thread != 0) {
2089 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87c693c2023-07-06 20:56:16 -07002090 Mutex::Autolock _l(thread->mutex());
2091 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002092 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002093 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002094 ALOGD("%s, haptic playback was %s for track %d",
2095 __func__, muted ? "muted" : "unmuted", mTrack->id());
2096 mTrack->setHapticPlaybackEnabled(!muted);
2097 return true;
jiabin57303cc2018-12-18 15:45:57 -08002098 }
2099 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002100 return false;
2101}
2102
Andy Hung8d31fd22023-06-26 19:20:57 -07002103binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002104 /*out*/ bool *ret) {
2105 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002106 return binder::Status::ok();
2107}
2108
Andy Hung8d31fd22023-06-26 19:20:57 -07002109binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002110 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002111 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002112 return binder::Status::ok();
2113}
2114
Eric Laurent81784c32012-11-19 14:55:58 -08002115// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002116#undef LOG_TAG
2117#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002118
Andy Hung8d31fd22023-06-26 19:20:57 -07002119/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002120sp<IAfOutputTrack> IAfOutputTrack::create(
2121 IAfPlaybackThread* playbackThread,
2122 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002123 uint32_t sampleRate,
2124 audio_format_t format,
2125 audio_channel_mask_t channelMask,
2126 size_t frameCount,
2127 const AttributionSourceState& attributionSource) {
2128 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002129 playbackThread,
2130 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002131 sampleRate,
2132 format,
2133 channelMask,
2134 frameCount,
2135 attributionSource);
2136}
2137
2138OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002139 IAfPlaybackThread* playbackThread,
2140 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002141 uint32_t sampleRate,
2142 audio_format_t format,
2143 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002144 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002145 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002146 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002147 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002148 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002149 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002150 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002151 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002152 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002153{
2154
2155 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002156 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002157 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002158 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002159 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002160 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002161 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002162 // since client and server are in the same process,
2163 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002164 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2165 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002166 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002167 mClientProxy->setSendLevel(0.0);
2168 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002169 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002170 ALOGW("%s(%d): Error creating output track on thread %d",
2171 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002172 }
2173}
2174
Andy Hung8d31fd22023-06-26 19:20:57 -07002175OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002176{
2177 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002178 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002179}
2180
Andy Hung8d31fd22023-06-26 19:20:57 -07002181status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002182 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002183{
2184 status_t status = Track::start(event, triggerSession);
2185 if (status != NO_ERROR) {
2186 return status;
2187 }
2188
2189 mActive = true;
2190 mRetryCount = 127;
2191 return status;
2192}
2193
Andy Hung8d31fd22023-06-26 19:20:57 -07002194void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002195{
2196 Track::stop();
2197 clearBufferQueue();
2198 mOutBuffer.frameCount = 0;
2199 mActive = false;
2200}
2201
Andy Hung8d31fd22023-06-26 19:20:57 -07002202ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002203{
Eric Laurent19952e12023-04-20 10:08:29 +02002204 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002205 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002206 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002207 // preload one silent buffer to trigger mixer on start()
2208 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2209 status_t status = mClientProxy->obtainBuffer(&buf);
2210 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2211 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2212 return 0;
2213 }
2214 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2215 mClientProxy->releaseBuffer(&buf);
2216
2217 (void) start();
2218
2219 // wait for HAL stream to start before sending actual audio. Doing this on each
2220 // OutputTrack makes that playback start on all output streams is synchronized.
2221 // If another OutputTrack has already started it can underrun but this is OK
2222 // as only silence has been played so far and the retry count is very high on
2223 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002224 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002225 if (!pt->waitForHalStart()) {
2226 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2227 stop();
2228 return 0;
2229 }
2230
2231 // enqueue the first buffer and exit so that other OutputTracks will also start before
2232 // write() is called again and this buffer actually consumed.
2233 Buffer firstBuffer;
2234 firstBuffer.frameCount = frames;
2235 firstBuffer.raw = data;
2236 queueBuffer(firstBuffer);
2237 return frames;
2238 } else {
2239 (void) start();
2240 }
2241 }
2242
Eric Laurent81784c32012-11-19 14:55:58 -08002243 Buffer *pInBuffer;
2244 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002245 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002246 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002247 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002248 while (waitTimeLeftMs) {
2249 // First write pending buffers, then new data
2250 if (mBufferQueue.size()) {
2251 pInBuffer = mBufferQueue.itemAt(0);
2252 } else {
2253 pInBuffer = &inBuffer;
2254 }
2255
2256 if (pInBuffer->frameCount == 0) {
2257 break;
2258 }
2259
2260 if (mOutBuffer.frameCount == 0) {
2261 mOutBuffer.frameCount = pInBuffer->frameCount;
2262 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002263 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002264 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002265 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2266 __func__, mId,
2267 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002268 break;
2269 }
2270 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2271 if (waitTimeLeftMs >= waitTimeMs) {
2272 waitTimeLeftMs -= waitTimeMs;
2273 } else {
2274 waitTimeLeftMs = 0;
2275 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002276 if (status == NOT_ENOUGH_DATA) {
2277 restartIfDisabled();
2278 continue;
2279 }
Eric Laurent81784c32012-11-19 14:55:58 -08002280 }
2281
2282 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2283 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002284 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002285 Proxy::Buffer buf;
2286 buf.mFrameCount = outFrames;
2287 buf.mRaw = NULL;
2288 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002289 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002290 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002291 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002292 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002293 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002294
2295 if (pInBuffer->frameCount == 0) {
2296 if (mBufferQueue.size()) {
2297 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002298 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002299 if (pInBuffer != &inBuffer) {
2300 delete pInBuffer;
2301 }
Andy Hung9d84af52018-09-12 18:03:44 -07002302 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2303 __func__, mId,
2304 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002305 } else {
2306 break;
2307 }
2308 }
2309 }
2310
2311 // If we could not write all frames, allocate a buffer and queue it for next time.
2312 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002313 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002314 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002315 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002316 }
2317 }
2318
Andy Hungc25b84a2015-01-14 19:04:10 -08002319 // Calling write() with a 0 length buffer means that no more data will be written:
2320 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2321 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2322 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002323 }
2324
Andy Hung1c86ebe2018-05-29 20:29:08 -07002325 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002326}
2327
Andy Hung8d31fd22023-06-26 19:20:57 -07002328void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002329
2330 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2331 Buffer *pInBuffer = new Buffer;
2332 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2333 pInBuffer->mBuffer = malloc(bufferSize);
2334 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2335 "%s: Unable to malloc size %zu", __func__, bufferSize);
2336 pInBuffer->frameCount = inBuffer.frameCount;
2337 pInBuffer->raw = pInBuffer->mBuffer;
2338 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2339 mBufferQueue.add(pInBuffer);
2340 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2341 (int)mThreadIoHandle, mBufferQueue.size());
2342 // audio data is consumed (stored locally); set frameCount to 0.
2343 inBuffer.frameCount = 0;
2344 } else {
2345 ALOGW("%s(%d): thread %d no more overflow buffers",
2346 __func__, mId, (int)mThreadIoHandle);
2347 // TODO: return error for this.
2348 }
2349}
2350
Andy Hung8d31fd22023-06-26 19:20:57 -07002351void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002352{
2353 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2354 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2355}
2356
Andy Hung8d31fd22023-06-26 19:20:57 -07002357void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002358 {
2359 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2360 mTrackMetadatas = metadatas;
2361 }
2362 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2363 setMetadataHasChanged();
2364}
2365
Andy Hung8d31fd22023-06-26 19:20:57 -07002366status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002367 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2368{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002369 ClientProxy::Buffer buf;
2370 buf.mFrameCount = buffer->frameCount;
2371 struct timespec timeout;
2372 timeout.tv_sec = waitTimeMs / 1000;
2373 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2374 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2375 buffer->frameCount = buf.mFrameCount;
2376 buffer->raw = buf.mRaw;
2377 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002378}
2379
Andy Hung8d31fd22023-06-26 19:20:57 -07002380void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002381{
2382 size_t size = mBufferQueue.size();
2383
2384 for (size_t i = 0; i < size; i++) {
2385 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002386 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002387 delete pBuffer;
2388 }
2389 mBufferQueue.clear();
2390}
2391
Andy Hung8d31fd22023-06-26 19:20:57 -07002392void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002393{
2394 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2395 if (mActive && (flags & CBLK_DISABLED)) {
2396 start();
2397 }
2398}
Eric Laurent81784c32012-11-19 14:55:58 -08002399
Andy Hung9d84af52018-09-12 18:03:44 -07002400// ----------------------------------------------------------------------------
2401#undef LOG_TAG
2402#define LOG_TAG "AF::PatchTrack"
2403
Andy Hung8d31fd22023-06-26 19:20:57 -07002404/* static */
2405sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002406 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002407 audio_stream_type_t streamType,
2408 uint32_t sampleRate,
2409 audio_channel_mask_t channelMask,
2410 audio_format_t format,
2411 size_t frameCount,
2412 void* buffer,
2413 size_t bufferSize,
2414 audio_output_flags_t flags,
2415 const Timeout& timeout,
2416 size_t frameCountToBeReady /** Default behaviour is to start
2417 * as soon as possible to have
2418 * the lowest possible latency
2419 * even if it might glitch. */)
2420{
2421 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002422 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002423 streamType,
2424 sampleRate,
2425 channelMask,
2426 format,
2427 frameCount,
2428 buffer,
2429 bufferSize,
2430 flags,
2431 timeout,
2432 frameCountToBeReady);
2433}
2434
Andy Hung87c693c2023-07-06 20:56:16 -07002435PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002436 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002437 uint32_t sampleRate,
2438 audio_channel_mask_t channelMask,
2439 audio_format_t format,
2440 size_t frameCount,
2441 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002442 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002443 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002444 const Timeout& timeout,
2445 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002446 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002447 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002448 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002449 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002450 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002451 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002452 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2453 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002454 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002455{
Andy Hung9d84af52018-09-12 18:03:44 -07002456 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2457 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002458 (int)mPeerTimeout.tv_sec,
2459 (int)(mPeerTimeout.tv_nsec / 1000000));
2460}
2461
Andy Hung8d31fd22023-06-26 19:20:57 -07002462PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002463{
Andy Hungabfab202019-03-07 19:45:54 -08002464 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002465}
2466
Andy Hung8d31fd22023-06-26 19:20:57 -07002467size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002468{
2469 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2470 return std::numeric_limits<size_t>::max();
2471 } else {
2472 return Track::framesReady();
2473 }
2474}
2475
Andy Hung8d31fd22023-06-26 19:20:57 -07002476status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002477 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002478{
2479 status_t status = Track::start(event, triggerSession);
2480 if (status != NO_ERROR) {
2481 return status;
2482 }
2483 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2484 return status;
2485}
2486
Eric Laurent83b88082014-06-20 18:31:16 -07002487// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002488status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002489 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002490{
Andy Hung9d84af52018-09-12 18:03:44 -07002491 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002492 Proxy::Buffer buf;
2493 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002494 if (ATRACE_ENABLED()) {
2495 std::string traceName("PTnReq");
2496 traceName += std::to_string(id());
2497 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2498 }
Eric Laurent83b88082014-06-20 18:31:16 -07002499 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002500 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002501 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002502 if (ATRACE_ENABLED()) {
2503 std::string traceName("PTnObt");
2504 traceName += std::to_string(id());
2505 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2506 }
Eric Laurent83b88082014-06-20 18:31:16 -07002507 if (buf.mFrameCount == 0) {
2508 return WOULD_BLOCK;
2509 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002510 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002511 return status;
2512}
2513
Andy Hung8d31fd22023-06-26 19:20:57 -07002514void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002515{
Andy Hung9d84af52018-09-12 18:03:44 -07002516 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002517 Proxy::Buffer buf;
2518 buf.mFrameCount = buffer->frameCount;
2519 buf.mRaw = buffer->raw;
2520 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002521 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002522}
2523
Andy Hung8d31fd22023-06-26 19:20:57 -07002524status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002525 const struct timespec *timeOut)
2526{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002527 status_t status = NO_ERROR;
2528 static const int32_t kMaxTries = 5;
2529 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002530 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002531 do {
2532 if (status == NOT_ENOUGH_DATA) {
2533 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002534 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002535 }
2536 status = mProxy->obtainBuffer(buffer, timeOut);
2537 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2538 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002539}
2540
Andy Hung8d31fd22023-06-26 19:20:57 -07002541void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002542{
2543 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002544 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002545
2546 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2547 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2548 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2549 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002550 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002551 && audio_is_linear_pcm(mFormat)
2552 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002553 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002554 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002555 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002556 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2557 / playbackThread->sampleRate();
2558 if (framesReady() < frameCount) {
2559 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002560 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002561 }
2562 }
2563 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002564}
2565
Andy Hung8d31fd22023-06-26 19:20:57 -07002566void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002567{
Eric Laurent83b88082014-06-20 18:31:16 -07002568 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002569 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002570 start();
2571 }
Eric Laurent83b88082014-06-20 18:31:16 -07002572}
2573
Eric Laurent81784c32012-11-19 14:55:58 -08002574// ----------------------------------------------------------------------------
2575// Record
2576// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002577
2578
Andy Hung9d84af52018-09-12 18:03:44 -07002579#undef LOG_TAG
2580#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002581
Andy Hunga5a7fc92023-06-23 19:27:19 -07002582class RecordHandle : public android::media::BnAudioRecord {
2583public:
Andy Hungd29af632023-06-23 19:27:19 -07002584 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002585 ~RecordHandle() override;
2586 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2587 int /*audio_session_t*/ triggerSession) final;
2588 binder::Status stop() final;
2589 binder::Status getActiveMicrophones(
2590 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2591 binder::Status setPreferredMicrophoneDirection(
2592 int /*audio_microphone_direction_t*/ direction) final;
2593 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2594 binder::Status shareAudioHistory(
2595 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2596
2597private:
Andy Hungd29af632023-06-23 19:27:19 -07002598 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002599
2600 // for use from destructor
2601 void stop_nonvirtual();
2602};
2603
2604/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002605sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2606 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002607 return sp<RecordHandle>::make(recordTrack);
2608}
2609
2610RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002611 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002612 : BnAudioRecord(),
2613 mRecordTrack(recordTrack)
2614{
Andy Hung225aef62022-12-06 16:33:20 -08002615 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002616}
2617
Andy Hunga5a7fc92023-06-23 19:27:19 -07002618RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002619 stop_nonvirtual();
2620 mRecordTrack->destroy();
2621}
2622
Andy Hunga5a7fc92023-06-23 19:27:19 -07002623binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002624 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002625 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002626 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002627 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002628}
2629
Andy Hunga5a7fc92023-06-23 19:27:19 -07002630binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002631 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002632 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002633}
2634
Andy Hunga5a7fc92023-06-23 19:27:19 -07002635void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002636 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002637 mRecordTrack->stop();
2638}
2639
Andy Hunga5a7fc92023-06-23 19:27:19 -07002640binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002641 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002642 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002643 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002644}
2645
Andy Hunga5a7fc92023-06-23 19:27:19 -07002646binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002647 int /*audio_microphone_direction_t*/ direction) {
2648 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002649 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002650 static_cast<audio_microphone_direction_t>(direction)));
2651}
2652
Andy Hunga5a7fc92023-06-23 19:27:19 -07002653binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002654 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002655 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002656}
2657
Andy Hunga5a7fc92023-06-23 19:27:19 -07002658binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002659 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2660 return binderStatusFromStatusT(
2661 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2662}
2663
Eric Laurent81784c32012-11-19 14:55:58 -08002664// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002665#undef LOG_TAG
2666#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002667
Andy Hung8d31fd22023-06-26 19:20:57 -07002668
Andy Hung99b1ba62023-07-14 11:00:08 -07002669/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002670sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002671 const sp<Client>& client,
2672 const audio_attributes_t& attr,
2673 uint32_t sampleRate,
2674 audio_format_t format,
2675 audio_channel_mask_t channelMask,
2676 size_t frameCount,
2677 void* buffer,
2678 size_t bufferSize,
2679 audio_session_t sessionId,
2680 pid_t creatorPid,
2681 const AttributionSourceState& attributionSource,
2682 audio_input_flags_t flags,
2683 track_type type,
2684 audio_port_handle_t portId,
2685 int32_t startFrames)
2686{
2687 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002688 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002689 client,
2690 attr,
2691 sampleRate,
2692 format,
2693 channelMask,
2694 frameCount,
2695 buffer,
2696 bufferSize,
2697 sessionId,
2698 creatorPid,
2699 attributionSource,
2700 flags,
2701 type,
2702 portId,
2703 startFrames);
2704}
2705
Glenn Kasten05997e22014-03-13 15:08:33 -07002706// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002707RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002708 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002709 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002710 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002711 uint32_t sampleRate,
2712 audio_format_t format,
2713 audio_channel_mask_t channelMask,
2714 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002715 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002716 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002717 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002718 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002719 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002720 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002721 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002722 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002723 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002724 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002725 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002726 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002727 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002728 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002729 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002730 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002731 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002732 type, portId,
2733 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002734 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002735 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002736 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002737 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002738 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002739 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002740{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002741 if (mCblk == NULL) {
2742 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002743 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002744
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002745 if (!isDirect()) {
2746 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002747 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002748 channelMask, format, sampleRate);
2749 // Check if the RecordBufferConverter construction was successful.
2750 // If not, don't continue with construction.
2751 //
2752 // NOTE: It would be extremely rare that the record track cannot be created
2753 // for the current device, but a pending or future device change would make
2754 // the record track configuration valid.
2755 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002756 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002757 return;
2758 }
Andy Hung97a893e2015-03-29 01:03:07 -07002759 }
2760
Andy Hung6ae58432016-02-16 18:32:24 -08002761 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002762 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002763
Andy Hung97a893e2015-03-29 01:03:07 -07002764 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002765
Eric Laurent05067782016-06-01 18:27:28 -07002766 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002767 ALOG_ASSERT(thread->fastTrackAvailable());
2768 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002769 } else {
2770 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002771 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002772 }
Andy Hung8946a282018-04-19 20:04:56 -07002773#ifdef TEE_SINK
2774 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2775 + "_" + std::to_string(mId)
2776 + "_R");
2777#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002778
2779 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002780 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002781}
2782
Andy Hung8d31fd22023-06-26 19:20:57 -07002783RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002784{
Andy Hung9d84af52018-09-12 18:03:44 -07002785 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002786 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002787 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002788}
2789
Andy Hung8d31fd22023-06-26 19:20:57 -07002790status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002791{
2792 status_t status = TrackBase::initCheck();
2793 if (status == NO_ERROR && mServerProxy == 0) {
2794 status = BAD_VALUE;
2795 }
2796 return status;
2797}
2798
Eric Laurent81784c32012-11-19 14:55:58 -08002799// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002800status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002801{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002802 ServerProxy::Buffer buf;
2803 buf.mFrameCount = buffer->frameCount;
2804 status_t status = mServerProxy->obtainBuffer(&buf);
2805 buffer->frameCount = buf.mFrameCount;
2806 buffer->raw = buf.mRaw;
2807 if (buf.mFrameCount == 0) {
2808 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002809 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002810 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002811 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002812}
2813
Andy Hung8d31fd22023-06-26 19:20:57 -07002814status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002815 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002816{
Andy Hung87c693c2023-07-06 20:56:16 -07002817 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002818 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002819 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002820 return recordThread->start(this, event, triggerSession);
2821 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002822 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2823 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002824 }
2825}
2826
Andy Hung8d31fd22023-06-26 19:20:57 -07002827void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002828{
Andy Hung87c693c2023-07-06 20:56:16 -07002829 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002830 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002831 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002832 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002833 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002834 }
2835 }
2836}
2837
Andy Hung8d31fd22023-06-26 19:20:57 -07002838void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002839{
Andy Hung8d31fd22023-06-26 19:20:57 -07002840 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002841 sp<RecordTrack> keep(this);
2842 {
Andy Hungce685402018-10-05 17:23:27 -07002843 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002844 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002845 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002846 Mutex::Autolock _l(thread->mutex());
2847 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002848 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002849 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002850 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002851 }
Andy Hungce685402018-10-05 17:23:27 -07002852 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2853 }
2854 // APM portid/client management done outside of lock.
2855 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2856 if (isExternalTrack()) {
2857 switch (priorState) {
2858 case ACTIVE: // invalidated while still active
2859 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2860 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2861 AudioSystem::stopInput(mPortId);
2862 break;
2863
2864 case STARTING_1: // invalidated/start-aborted and startInput not successful
2865 case PAUSED: // OK, not active
2866 case IDLE: // OK, not active
2867 break;
2868
2869 case STOPPED: // unexpected (destroyed)
2870 default:
2871 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2872 }
2873 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002874 }
2875 }
2876}
2877
Andy Hung8d31fd22023-06-26 19:20:57 -07002878void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002879{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002880 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002881 // FIXME should use proxy, and needs work
2882 audio_track_cblk_t* cblk = mCblk;
2883 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2884 android_atomic_release_store(0x40000000, &cblk->mFutex);
2885 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002886 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002887}
2888
Eric Laurent81784c32012-11-19 14:55:58 -08002889
Andy Hung8d31fd22023-06-26 19:20:57 -07002890void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002891{
Eric Laurent973db022018-11-20 14:54:31 -08002892 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002893 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002894 " Server FrmCnt FrmRdy Sil%s\n",
2895 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002896}
2897
Andy Hung8d31fd22023-06-26 19:20:57 -07002898void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002899{
Eric Laurent973db022018-11-20 14:54:31 -08002900 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002901 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002902 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002903 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002904 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002905 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002906 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002907 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002908 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002909 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002910 mCblk->mFlags,
2911
Eric Laurent81784c32012-11-19 14:55:58 -08002912 mFormat,
2913 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002914 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002915 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002916
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002917 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002918 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002919 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002920 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002921 );
Andy Hung000adb52018-06-01 15:43:26 -07002922 if (isServerLatencySupported()) {
2923 double latencyMs;
2924 bool fromTrack;
2925 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2926 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2927 // or 'k' if estimated from kernel (usually for debugging).
2928 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2929 } else {
2930 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2931 }
2932 }
2933 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002934}
2935
Andy Hung93bb5732023-05-04 21:16:34 -07002936// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002937void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002938 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002939{
Andy Hung93bb5732023-05-04 21:16:34 -07002940 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002941 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002942 if (threadBase != 0) {
2943 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2944 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07002945 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002946 }
Andy Hung93bb5732023-05-04 21:16:34 -07002947
2948 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002949}
2950
Andy Hung8d31fd22023-06-26 19:20:57 -07002951void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002952{
Andy Hung93bb5732023-05-04 21:16:34 -07002953 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002954}
2955
Andy Hung8d31fd22023-06-26 19:20:57 -07002956void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002957 int64_t trackFramesReleased, int64_t sourceFramesRead,
2958 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2959{
Andy Hung30282562018-08-08 18:27:03 -07002960 // Make the kernel frametime available.
2961 const FrameTime ft{
2962 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2963 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2964 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2965 mKernelFrameTime.store(ft);
2966 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002967 // Stream is direct, return provided timestamp with no conversion
2968 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002969 return;
2970 }
2971
Andy Hung3f0c9022016-01-15 17:49:46 -08002972 ExtendedTimestamp local = timestamp;
2973
2974 // Convert HAL frames to server-side track frames at track sample rate.
2975 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2976 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2977 if (local.mTimeNs[i] != 0) {
2978 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2979 const int64_t relativeTrackFrames = relativeServerFrames
2980 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2981 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2982 }
2983 }
Andy Hung6ae58432016-02-16 18:32:24 -08002984 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002985
2986 // Compute latency info.
2987 const bool useTrackTimestamp = true; // use track unless debugging.
2988 const double latencyMs = - (useTrackTimestamp
2989 ? local.getOutputServerLatencyMs(sampleRate())
2990 : timestamp.getOutputServerLatencyMs(halSampleRate));
2991
2992 mServerLatencyFromTrack.store(useTrackTimestamp);
2993 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08002994}
Eric Laurent83b88082014-06-20 18:31:16 -07002995
Andy Hung8d31fd22023-06-26 19:20:57 -07002996status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07002997 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08002998{
Andy Hung87c693c2023-07-06 20:56:16 -07002999 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003000 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003001 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003002 return recordThread->getActiveMicrophones(activeMicrophones);
3003 } else {
3004 return BAD_VALUE;
3005 }
3006}
3007
Andy Hung8d31fd22023-06-26 19:20:57 -07003008status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003009 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003010 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003011 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003012 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003013 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003014 } else {
3015 return BAD_VALUE;
3016 }
3017}
3018
Andy Hung8d31fd22023-06-26 19:20:57 -07003019status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003020 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003021 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003022 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003023 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003024 } else {
3025 return BAD_VALUE;
3026 }
3027}
3028
Andy Hung8d31fd22023-06-26 19:20:57 -07003029status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003030 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3031
3032 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3033 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3034 if (callingUid != mUid || callingPid != mCreatorPid) {
3035 return PERMISSION_DENIED;
3036 }
3037
Svet Ganov33761132021-05-13 22:51:08 +00003038 AttributionSourceState attributionSource{};
3039 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3040 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3041 attributionSource.token = sp<BBinder>::make();
3042 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003043 return PERMISSION_DENIED;
3044 }
3045
Andy Hung87c693c2023-07-06 20:56:16 -07003046 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003047 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003048 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003049 status_t status = recordThread->shareAudioHistory(
3050 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3051 if (status == NO_ERROR) {
3052 mSharedAudioPackageName = sharedAudioPackageName;
3053 }
3054 return status;
3055 } else {
3056 return BAD_VALUE;
3057 }
3058}
3059
Andy Hung8d31fd22023-06-26 19:20:57 -07003060void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003061{
3062
3063 // Do not forward PatchRecord metadata with unspecified audio source
3064 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3065 return;
3066 }
3067
3068 // No track is invalid as this is called after prepareTrack_l in the same critical section
3069 record_track_metadata_v7_t metadata;
3070 metadata.base = {
3071 .source = mAttr.source,
3072 .gain = 1, // capture tracks do not have volumes
3073 };
3074 metadata.channel_mask = mChannelMask;
3075 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3076
3077 *backInserter++ = metadata;
3078}
Eric Laurentec376dc2021-04-08 20:41:22 +02003079
Andy Hung9d84af52018-09-12 18:03:44 -07003080// ----------------------------------------------------------------------------
3081#undef LOG_TAG
3082#define LOG_TAG "AF::PatchRecord"
3083
Andy Hung8d31fd22023-06-26 19:20:57 -07003084/* static */
3085sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003086 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003087 uint32_t sampleRate,
3088 audio_channel_mask_t channelMask,
3089 audio_format_t format,
3090 size_t frameCount,
3091 void *buffer,
3092 size_t bufferSize,
3093 audio_input_flags_t flags,
3094 const Timeout& timeout,
3095 audio_source_t source)
3096{
3097 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003098 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003099 sampleRate,
3100 channelMask,
3101 format,
3102 frameCount,
3103 buffer,
3104 bufferSize,
3105 flags,
3106 timeout,
3107 source);
3108}
3109
Andy Hung87c693c2023-07-06 20:56:16 -07003110PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003111 uint32_t sampleRate,
3112 audio_channel_mask_t channelMask,
3113 audio_format_t format,
3114 size_t frameCount,
3115 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003116 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003117 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003118 const Timeout& timeout,
3119 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003120 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003121 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003122 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003123 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003124 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003125 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3126 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003127 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003128{
Andy Hung9d84af52018-09-12 18:03:44 -07003129 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3130 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003131 (int)mPeerTimeout.tv_sec,
3132 (int)(mPeerTimeout.tv_nsec / 1000000));
3133}
3134
Andy Hung8d31fd22023-06-26 19:20:57 -07003135PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003136{
Andy Hungabfab202019-03-07 19:45:54 -08003137 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003138}
3139
Mikhail Naganov8296c252019-09-25 14:59:54 -07003140static size_t writeFramesHelper(
3141 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3142{
3143 AudioBufferProvider::Buffer patchBuffer;
3144 patchBuffer.frameCount = frameCount;
3145 auto status = dest->getNextBuffer(&patchBuffer);
3146 if (status != NO_ERROR) {
3147 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3148 __func__, status, strerror(-status));
3149 return 0;
3150 }
3151 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3152 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3153 size_t framesWritten = patchBuffer.frameCount;
3154 dest->releaseBuffer(&patchBuffer);
3155 return framesWritten;
3156}
3157
3158// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003159size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003160 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3161{
3162 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3163 // On buffer wrap, the buffer frame count will be less than requested,
3164 // when this happens a second buffer needs to be used to write the leftover audio
3165 const size_t framesLeft = frameCount - framesWritten;
3166 if (framesWritten != 0 && framesLeft != 0) {
3167 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3168 framesLeft, frameSize);
3169 }
3170 return framesWritten;
3171}
3172
Eric Laurent83b88082014-06-20 18:31:16 -07003173// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003174status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003175 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003176{
Andy Hung9d84af52018-09-12 18:03:44 -07003177 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003178 Proxy::Buffer buf;
3179 buf.mFrameCount = buffer->frameCount;
3180 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3181 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003182 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003183 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003184 if (ATRACE_ENABLED()) {
3185 std::string traceName("PRnObt");
3186 traceName += std::to_string(id());
3187 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3188 }
Eric Laurent83b88082014-06-20 18:31:16 -07003189 if (buf.mFrameCount == 0) {
3190 return WOULD_BLOCK;
3191 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003192 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003193 return status;
3194}
3195
Andy Hung8d31fd22023-06-26 19:20:57 -07003196void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003197{
Andy Hung9d84af52018-09-12 18:03:44 -07003198 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003199 Proxy::Buffer buf;
3200 buf.mFrameCount = buffer->frameCount;
3201 buf.mRaw = buffer->raw;
3202 mPeerProxy->releaseBuffer(&buf);
3203 TrackBase::releaseBuffer(buffer);
3204}
3205
Andy Hung8d31fd22023-06-26 19:20:57 -07003206status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003207 const struct timespec *timeOut)
3208{
3209 return mProxy->obtainBuffer(buffer, timeOut);
3210}
3211
Andy Hung8d31fd22023-06-26 19:20:57 -07003212void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003213{
3214 mProxy->releaseBuffer(buffer);
3215}
3216
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003217#undef LOG_TAG
3218#define LOG_TAG "AF::PthrPatchRecord"
3219
3220static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3221{
3222 void *ptr = nullptr;
3223 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003224 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003225}
3226
Andy Hung8d31fd22023-06-26 19:20:57 -07003227/* static */
3228sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003229 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003230 uint32_t sampleRate,
3231 audio_channel_mask_t channelMask,
3232 audio_format_t format,
3233 size_t frameCount,
3234 audio_input_flags_t flags,
3235 audio_source_t source)
3236{
3237 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003238 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003239 sampleRate,
3240 channelMask,
3241 format,
3242 frameCount,
3243 flags,
3244 source);
3245}
3246
3247PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003248 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003249 uint32_t sampleRate,
3250 audio_channel_mask_t channelMask,
3251 audio_format_t format,
3252 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003253 audio_input_flags_t flags,
3254 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003255 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003256 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003257 mPatchRecordAudioBufferProvider(*this),
3258 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3259 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3260{
3261 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3262}
3263
Andy Hung8d31fd22023-06-26 19:20:57 -07003264sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003265 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003266{
3267 *thread = mThread.promote();
3268 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003269 auto* const recordThread = (*thread)->asIAfRecordThread().get();
3270 Mutex::Autolock _l(recordThread->mutex());
3271 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003272}
3273
3274// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003275status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003276 Proxy::Buffer* buffer, const struct timespec* timeOut)
3277{
3278 if (mUnconsumedFrames) {
3279 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3280 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3281 return PatchRecord::obtainBuffer(buffer, timeOut);
3282 }
3283
3284 // Otherwise, execute a read from HAL and write into the buffer.
3285 nsecs_t startTimeNs = 0;
3286 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3287 // Will need to correct timeOut by elapsed time.
3288 startTimeNs = systemTime();
3289 }
3290 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3291 buffer->mFrameCount = 0;
3292 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003293 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003294 sp<StreamInHalInterface> stream = obtainStream(&thread);
3295 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3296
3297 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003298 size_t bytesRead = 0;
3299 {
3300 ATRACE_NAME("read");
3301 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3302 if (result != NO_ERROR) goto stream_error;
3303 if (bytesRead == 0) return NO_ERROR;
3304 }
3305
3306 {
3307 std::lock_guard<std::mutex> lock(mReadLock);
3308 mReadBytes += bytesRead;
3309 mReadError = NO_ERROR;
3310 }
3311 mReadCV.notify_one();
3312 // writeFrames handles wraparound and should write all the provided frames.
3313 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3314 buffer->mFrameCount = writeFrames(
3315 &mPatchRecordAudioBufferProvider,
3316 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3317 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3318 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3319 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003320 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003321 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003322 // Correct the timeout by elapsed time.
3323 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003324 if (newTimeOutNs < 0) newTimeOutNs = 0;
3325 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3326 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003327 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003328 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003329 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003330
3331stream_error:
3332 stream->standby();
3333 {
3334 std::lock_guard<std::mutex> lock(mReadLock);
3335 mReadError = result;
3336 }
3337 mReadCV.notify_one();
3338 return result;
3339}
3340
Andy Hung8d31fd22023-06-26 19:20:57 -07003341void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003342{
3343 if (buffer->mFrameCount <= mUnconsumedFrames) {
3344 mUnconsumedFrames -= buffer->mFrameCount;
3345 } else {
3346 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3347 buffer->mFrameCount, mUnconsumedFrames);
3348 mUnconsumedFrames = 0;
3349 }
3350 PatchRecord::releaseBuffer(buffer);
3351}
3352
3353// AudioBufferProvider and Source methods are called on RecordThread
3354// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3355// and 'releaseBuffer' are stubbed out and ignore their input.
3356// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3357// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003358status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003359 void* buffer, size_t bytes, size_t* read)
3360{
3361 bytes = std::min(bytes, mFrameCount * mFrameSize);
3362 {
3363 std::unique_lock<std::mutex> lock(mReadLock);
3364 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3365 if (mReadError != NO_ERROR) {
3366 mLastReadFrames = 0;
3367 return mReadError;
3368 }
3369 *read = std::min(bytes, mReadBytes);
3370 mReadBytes -= *read;
3371 }
3372 mLastReadFrames = *read / mFrameSize;
3373 memset(buffer, 0, *read);
3374 return 0;
3375}
3376
Andy Hung8d31fd22023-06-26 19:20:57 -07003377status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003378 int64_t* frames, int64_t* time)
3379{
Andy Hung87c693c2023-07-06 20:56:16 -07003380 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003381 sp<StreamInHalInterface> stream = obtainStream(&thread);
3382 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3383}
3384
Andy Hung8d31fd22023-06-26 19:20:57 -07003385status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003386{
3387 // RecordThread issues 'standby' command in two major cases:
3388 // 1. Error on read--this case is handled in 'obtainBuffer'.
3389 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3390 // output, this can only happen when the software patch
3391 // is being torn down. In this case, the RecordThread
3392 // will terminate and close the HAL stream.
3393 return 0;
3394}
3395
3396// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003397status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003398 AudioBufferProvider::Buffer* buffer)
3399{
3400 buffer->frameCount = mLastReadFrames;
3401 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3402 return NO_ERROR;
3403}
3404
Andy Hung8d31fd22023-06-26 19:20:57 -07003405void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003406 AudioBufferProvider::Buffer* buffer)
3407{
3408 buffer->frameCount = 0;
3409 buffer->raw = nullptr;
3410}
3411
Andy Hung9d84af52018-09-12 18:03:44 -07003412// ----------------------------------------------------------------------------
3413#undef LOG_TAG
3414#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003415
Andy Hung8d31fd22023-06-26 19:20:57 -07003416/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003417sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003418 const audio_attributes_t& attr,
3419 uint32_t sampleRate,
3420 audio_format_t format,
3421 audio_channel_mask_t channelMask,
3422 audio_session_t sessionId,
3423 bool isOut,
3424 const android::content::AttributionSourceState& attributionSource,
3425 pid_t creatorPid,
3426 audio_port_handle_t portId)
3427{
3428 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003429 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003430 attr,
3431 sampleRate,
3432 format,
3433 channelMask,
3434 sessionId,
3435 isOut,
3436 attributionSource,
3437 creatorPid,
3438 portId);
3439}
3440
Andy Hung87c693c2023-07-06 20:56:16 -07003441MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003442 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003443 uint32_t sampleRate,
3444 audio_format_t format,
3445 audio_channel_mask_t channelMask,
3446 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003447 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003448 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003449 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003450 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003451 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003452 channelMask, (size_t)0 /* frameCount */,
3453 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003454 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003455 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003456 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003457 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003458 TYPE_DEFAULT, portId,
3459 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003460 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003461 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003462{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003463 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003464 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003465}
3466
Andy Hung8d31fd22023-06-26 19:20:57 -07003467MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003468{
3469}
3470
Andy Hung8d31fd22023-06-26 19:20:57 -07003471status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003472{
3473 return NO_ERROR;
3474}
3475
Andy Hung8d31fd22023-06-26 19:20:57 -07003476status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003477 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003478{
3479 return NO_ERROR;
3480}
3481
Andy Hung8d31fd22023-06-26 19:20:57 -07003482void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003483{
3484}
3485
3486// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003487status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003488{
3489 buffer->frameCount = 0;
3490 buffer->raw = nullptr;
3491 return INVALID_OPERATION;
3492}
3493
3494// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003495size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003496 return 0;
3497}
3498
Andy Hung8d31fd22023-06-26 19:20:57 -07003499int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003500{
3501 return 0;
3502}
3503
Andy Hung8d31fd22023-06-26 19:20:57 -07003504void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003505{
3506}
3507
Andy Hung8d31fd22023-06-26 19:20:57 -07003508void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003509{
3510 if (mMuteState == muteState) {
3511 // mute state did not change, do nothing
3512 return;
3513 }
3514
3515 status_t result = UNKNOWN_ERROR;
3516 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3517 if (mMuteEventExtras == nullptr) {
3518 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3519 }
3520 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3521 static_cast<int>(muteState));
3522
3523 result = audioManager->portEvent(mPortId,
3524 PLAYER_UPDATE_MUTED,
3525 mMuteEventExtras);
3526 }
3527
3528 if (result == OK) {
3529 mMuteState = muteState;
3530 } else {
3531 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3532 __func__,
3533 id(),
3534 mPortId,
3535 result);
3536 }
3537}
3538
Andy Hung8d31fd22023-06-26 19:20:57 -07003539void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003540{
Eric Laurent973db022018-11-20 14:54:31 -08003541 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003542 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003543}
3544
Andy Hung8d31fd22023-06-26 19:20:57 -07003545void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003546{
Eric Laurent973db022018-11-20 14:54:31 -08003547 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003548 mPid,
3549 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003550 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003551 mFormat,
3552 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003553 mSampleRate,
3554 mAttr.flags);
3555 if (isOut()) {
3556 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3557 } else {
3558 result.appendFormat("%6x", mAttr.source);
3559 }
3560 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003561}
3562
Glenn Kasten63238ef2015-03-02 15:50:29 -08003563} // namespace android