blob: fe582eb45fb5ef7615dc53f9a57fa74059d28cc4 [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Eric Laurent81784c32012-11-19 14:55:58 -080018#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070020#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080021
Andy Hung0f725b42023-07-19 11:40:07 -070022#include "MmapTracks.h"
23#include "PlaybackTracks.h"
24#include "RecordTracks.h"
25
26#include "Client.h"
27#include "IAfEffect.h"
28#include "IAfThread.h"
29#include "ResamplerBufferProvider.h"
30
31#include <audio_utils/minifloat.h>
32#include <media/AudioValidator.h>
33#include <media/RecordBufferConverter.h>
34#include <media/nbaio/Pipe.h>
35#include <media/nbaio/PipeReader.h>
36#include <mediautils/ServiceUtilities.h>
37#include <mediautils/SharedMemoryAllocator.h>
38#include <private/media/AudioTrackShared.h>
Eric Laurent81784c32012-11-19 14:55:58 -080039#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070040#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080041
Andy Hung0f725b42023-07-19 11:40:07 -070042#include <linux/futex.h>
43#include <math.h>
44#include <sys/syscall.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080045
Eric Laurent81784c32012-11-19 14:55:58 -080046// ----------------------------------------------------------------------------
47
48// Note: the following macro is used for extremely verbose logging message. In
49// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
50// 0; but one side effect of this is to turn all LOGV's as well. Some messages
51// are so verbose that we want to suppress them even when we have ALOG_ASSERT
52// turned on. Do not uncomment the #def below unless you really know what you
53// are doing and want to see all of the extremely verbose messages.
54//#define VERY_VERY_VERBOSE_LOGGING
55#ifdef VERY_VERY_VERBOSE_LOGGING
56#define ALOGVV ALOGV
57#else
58#define ALOGVV(a...) do { } while(0)
59#endif
60
Kuowei Lid4adbdb2020-08-13 14:44:25 +080061// TODO: Remove when this is put into AidlConversionUtil.h
62#define VALUE_OR_RETURN_BINDER_STATUS(x) \
63 ({ \
64 auto _tmp = (x); \
65 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
66 std::move(_tmp.value()); \
67 })
68
Eric Laurent81784c32012-11-19 14:55:58 -080069namespace android {
70
Kuowei Lid4adbdb2020-08-13 14:44:25 +080071using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080072using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000073using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070074using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080075// ----------------------------------------------------------------------------
76// TrackBase
77// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070078#undef LOG_TAG
79#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080080
Glenn Kastenda6ef132013-01-10 12:31:01 -080081static volatile int32_t nextTrackId = 55;
82
Eric Laurent81784c32012-11-19 14:55:58 -080083// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung87c693c2023-07-06 20:56:16 -070085 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080086 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070087 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080088 uint32_t sampleRate,
89 audio_format_t format,
90 audio_channel_mask_t channelMask,
91 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070092 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070093 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080094 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070095 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080096 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070097 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070098 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080099 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800100 audio_port_handle_t portId,
101 std::string metricsId)
Andy Hungd29af632023-06-23 19:27:19 -0700102 :
Eric Laurent81784c32012-11-19 14:55:58 -0800103 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700104 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800105 mClient(client),
106 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700107 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800108 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700109 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800110 mSampleRate(sampleRate),
111 mFormat(format),
112 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700113 mChannelCount(isOut ?
114 audio_channel_count_from_out_mask(channelMask) :
115 audio_channel_count_from_in_mask(channelMask)),
Dean Wheatleyd883e302023-10-20 06:11:43 +1100116 mFrameSize(audio_bytes_per_frame(mChannelCount, format)),
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung8d31fd22023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung8d31fd22023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung954b9712023-08-28 18:36:53 -0700279 audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung8d31fd22023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung8d31fd22023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung8d31fd22023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung4fd69012023-07-14 16:57:01 -0700318 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
Andy Hung4fd69012023-07-14 16:57:01 -0700325 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
326 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung8d31fd22023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hunga5a7fc92023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hungd29af632023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hunga5a7fc92023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hungd29af632023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hungd29af632023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hunga5a7fc92023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hungd29af632023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hung225aef62022-12-06 16:33:20 -0800391 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800392}
393
Andy Hunga5a7fc92023-06-23 19:27:19 -0700394TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800395 // just stop the track on deletion, associated resources
396 // will be freed from the main thread once all pending buffers have
397 // been played. Unless it's not in the active track list, in which
398 // case we free everything now...
399 mTrack->destroy();
400}
401
Andy Hunga5a7fc92023-06-23 19:27:19 -0700402Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800403 std::optional<media::SharedFileRegion>* _aidl_return) {
404 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
405 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800406}
407
Andy Hunga5a7fc92023-06-23 19:27:19 -0700408Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800409 *_aidl_return = mTrack->start();
410 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800411}
412
Andy Hunga5a7fc92023-06-23 19:27:19 -0700413Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800414 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800415 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800416}
417
Andy Hunga5a7fc92023-06-23 19:27:19 -0700418Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800419 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800420 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800421}
422
Andy Hunga5a7fc92023-06-23 19:27:19 -0700423Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800424 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800425 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800426}
427
Andy Hunga5a7fc92023-06-23 19:27:19 -0700428Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800429 int32_t* _aidl_return) {
430 *_aidl_return = mTrack->attachAuxEffect(effectId);
431 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800432}
433
Andy Hunga5a7fc92023-06-23 19:27:19 -0700434Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800435 int32_t* _aidl_return) {
436 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
437 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700438}
439
Andy Hunga5a7fc92023-06-23 19:27:19 -0700440Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800441 int32_t* _aidl_return) {
442 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
443 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800444}
445
Andy Hunga5a7fc92023-06-23 19:27:19 -0700446Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800447 int32_t* _aidl_return) {
448 AudioTimestamp legacy;
449 *_aidl_return = mTrack->getTimestamp(legacy);
450 if (*_aidl_return != OK) {
451 return Status::ok();
452 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000453
454 // restrict position modulo INT_MAX to avoid integer sanitization abort
455 legacy.mPosition &= INT_MAX;
456
Andy Hung973638a2020-12-08 20:47:45 -0800457 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800458 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800459}
460
Andy Hunga5a7fc92023-06-23 19:27:19 -0700461Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800462 mTrack->signal();
463 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800464}
465
Andy Hunga5a7fc92023-06-23 19:27:19 -0700466Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800467 const media::VolumeShaperConfiguration& configuration,
468 const media::VolumeShaperOperation& operation,
469 int32_t* _aidl_return) {
470 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
471 *_aidl_return = conf->readFromParcelable(configuration);
472 if (*_aidl_return != OK) {
473 return Status::ok();
474 }
475
476 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
477 *_aidl_return = op->readFromParcelable(operation);
478 if (*_aidl_return != OK) {
479 return Status::ok();
480 }
481
482 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
483 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700484}
485
Andy Hunga5a7fc92023-06-23 19:27:19 -0700486Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800487 int32_t id,
488 std::optional<media::VolumeShaperState>* _aidl_return) {
489 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
490 if (legacy == nullptr) {
491 _aidl_return->reset();
492 return Status::ok();
493 }
494 media::VolumeShaperState aidl;
495 legacy->writeToParcelable(&aidl);
496 *_aidl_return = aidl;
497 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800498}
499
Andy Hunga5a7fc92023-06-23 19:27:19 -0700500Status TrackHandle::getDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000501 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800502{
503 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
504 const status_t status = mTrack->getDualMonoMode(&mode)
505 ?: AudioValidator::validateDualMonoMode(mode);
506 if (status == OK) {
507 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
508 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
509 }
510 return binderStatusFromStatusT(status);
511}
512
Andy Hunga5a7fc92023-06-23 19:27:19 -0700513Status TrackHandle::setDualMonoMode(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000514 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800515{
516 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
517 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
518 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
519 ?: mTrack->setDualMonoMode(localMonoMode));
520}
521
Andy Hunga5a7fc92023-06-23 19:27:19 -0700522Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800523{
524 float leveldB = -std::numeric_limits<float>::infinity();
525 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
526 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
527 if (status == OK) *_aidl_return = leveldB;
528 return binderStatusFromStatusT(status);
529}
530
Andy Hunga5a7fc92023-06-23 19:27:19 -0700531Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800532{
533 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
534 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
535}
536
Andy Hunga5a7fc92023-06-23 19:27:19 -0700537Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000538 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800539{
540 audio_playback_rate_t localPlaybackRate{};
541 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
542 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
543 if (status == NO_ERROR) {
544 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
545 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
546 }
547 return binderStatusFromStatusT(status);
548}
549
Andy Hunga5a7fc92023-06-23 19:27:19 -0700550Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganovf53e1822022-12-18 02:48:14 +0000551 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800552{
553 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
554 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
555 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
556 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
557}
558
Eric Laurent81784c32012-11-19 14:55:58 -0800559// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800560// AppOp for audio playback
561// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700562
563// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700564sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung87c693c2023-07-06 20:56:16 -0700565 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000566 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700567 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800568{
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700569 Vector<String16> packages;
570 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000571 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700572 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700573 if (packages.isEmpty()) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000574 ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
Eric Laurent9066ad32019-05-20 14:40:10 -0700575 uid);
576 return nullptr;
577 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800578 }
579 // stream type has been filtered by audio policy to indicate whether it can be muted
580 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700581 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700582 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800583 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700584 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
585 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
586 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
587 id, attr.flags);
588 return nullptr;
589 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700590 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700591}
592
Andy Hung87c693c2023-07-06 20:56:16 -0700593OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700594 const AttributionSourceState& attributionSource,
595 audio_usage_t usage, int id, uid_t uid)
Andy Hung87c693c2023-07-06 20:56:16 -0700596 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700597 mHasOpPlayAudio(true),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700598 mUsage((int32_t)usage),
599 mId(id),
600 mUid(uid),
601 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
602 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800603
Andy Hung8d31fd22023-06-26 19:20:57 -0700604OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800605{
606 if (mOpCallback != 0) {
607 mAppOpsManager.stopWatchingMode(mOpCallback);
608 }
609 mOpCallback.clear();
610}
611
Andy Hung8d31fd22023-06-26 19:20:57 -0700612void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700613{
Vlad Popad5859592023-08-02 18:36:04 -0700614 // make sure not to broadcast the initial state since it is not needed and could
615 // cause a deadlock since this method can be called with the mThread->mLock held
616 checkPlayAudioForUsage(/*doBroadcast=*/false);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000617 if (mPackageName.size()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700618 mOpCallback = new PlayAudioOpCallback(this);
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000619 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
620 } else {
621 ALOGW("Skipping OpPlayAudioMonitor due to null package name");
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700622 }
623}
624
Andy Hung8d31fd22023-06-26 19:20:57 -0700625bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800626 return mHasOpPlayAudio.load();
627}
628
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700629// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800630// - not called from constructor due to check on UID,
631// - not called from PlayAudioOpCallback because the callback is not installed in this case
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000632void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
633 const bool hasAppOps =
634 mPackageName.size() &&
635 mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
636 mPackageName) == AppOpsManager::MODE_ALLOWED;
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700637
638 bool shouldChange = !hasAppOps; // check if we need to update.
639 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000640 ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000641 String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
Vlad Popad5859592023-08-02 18:36:04 -0700642 if (doBroadcast) {
643 auto thread = mThread.promote();
644 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
645 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hungc5007f82023-08-29 14:26:09 -0700646 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad5859592023-08-02 18:36:04 -0700647 thread->broadcast_l();
648 }
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700649 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800650 }
651}
652
Andy Hung8d31fd22023-06-26 19:20:57 -0700653OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800654 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
655{ }
656
Andy Hung8d31fd22023-06-26 19:20:57 -0700657void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800658 const String16& packageName) {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800659 if (op != AppOpsManager::OP_PLAY_AUDIO) {
660 return;
661 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +0000662
Tomasz Wasilczykb61c7212023-09-08 17:32:11 +0000663 ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800664 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
665 if (monitor != NULL) {
Vlad Popad5859592023-08-02 18:36:04 -0700666 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800667 }
668}
669
Eric Laurent9066ad32019-05-20 14:40:10 -0700670// static
Andy Hung8d31fd22023-06-26 19:20:57 -0700671void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700672 uid_t uid, Vector<String16>& packages)
673{
674 PermissionController permissionController;
675 permissionController.getPackagesForUid(uid, packages);
676}
677
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800678// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700679#undef LOG_TAG
680#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800681
Andy Hung8d31fd22023-06-26 19:20:57 -0700682/* static */
Andy Hung87c693c2023-07-06 20:56:16 -0700683sp<IAfTrack> IAfTrack::create(
684 IAfPlaybackThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700685 const sp<Client>& client,
686 audio_stream_type_t streamType,
687 const audio_attributes_t& attr,
688 uint32_t sampleRate,
689 audio_format_t format,
690 audio_channel_mask_t channelMask,
691 size_t frameCount,
692 void *buffer,
693 size_t bufferSize,
694 const sp<IMemory>& sharedBuffer,
695 audio_session_t sessionId,
696 pid_t creatorPid,
697 const AttributionSourceState& attributionSource,
698 audio_output_flags_t flags,
699 track_type type,
700 audio_port_handle_t portId,
701 /** default behaviour is to start when there are as many frames
702 * ready as possible (aka. Buffer is full). */
703 size_t frameCountToBeReady,
704 float speed,
705 bool isSpatialized,
706 bool isBitPerfect) {
Andy Hung87c693c2023-07-06 20:56:16 -0700707 return sp<Track>::make(thread,
Andy Hung8d31fd22023-06-26 19:20:57 -0700708 client,
709 streamType,
710 attr,
711 sampleRate,
712 format,
713 channelMask,
714 frameCount,
715 buffer,
716 bufferSize,
717 sharedBuffer,
718 sessionId,
719 creatorPid,
720 attributionSource,
721 flags,
722 type,
723 portId,
724 frameCountToBeReady,
725 speed,
726 isSpatialized,
727 isBitPerfect);
728}
729
Eric Laurent81784c32012-11-19 14:55:58 -0800730// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -0700731Track::Track(
Andy Hung87c693c2023-07-06 20:56:16 -0700732 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800733 const sp<Client>& client,
734 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700735 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800736 uint32_t sampleRate,
737 audio_format_t format,
738 audio_channel_mask_t channelMask,
739 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700740 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700741 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800742 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800743 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700744 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000745 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700746 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800747 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100748 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000749 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200750 float speed,
jiabinc658e452022-10-21 20:52:21 +0000751 bool isSpatialized,
752 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700753 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700754 // TODO: Using unsecurePointer() has some associated security pitfalls
755 // (see declaration for details).
756 // Either document why it is safe in this case or address the
757 // issue (e.g. by copying).
758 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700759 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700760 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000761 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700762 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800763 type,
764 portId,
765 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung8d31fd22023-06-26 19:20:57 -0700766 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800767 // mRetryCount initialized later when needed
768 mSharedBuffer(sharedBuffer),
769 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700770 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800771 mAuxBuffer(NULL),
772 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700773 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700774 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa9d7c6f82023-07-10 20:27:41 -0700775 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700776 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700777 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800778 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800779 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700780 /* The track might not play immediately after being active, similarly as if its volume was 0.
781 * When the track starts playing, its volume will be computed. */
782 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800783 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700784 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000785 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200786 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000787 mIsSpatialized(isSpatialized),
788 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800789{
Eric Laurent83b88082014-06-20 18:31:16 -0700790 // client == 0 implies sharedBuffer == 0
791 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
792
Andy Hung9d84af52018-09-12 18:03:44 -0700793 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700794 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700795
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700796 if (mCblk == NULL) {
797 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800798 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700799
Svet Ganov33761132021-05-13 22:51:08 +0000800 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700801 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
802 ALOGE("%s(%d): no more tracks available", __func__, mId);
803 releaseCblk(); // this makes the track invalid.
804 return;
805 }
806
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700807 if (sharedBuffer == 0) {
808 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700809 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700810 } else {
811 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100812 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700813 }
814 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700815 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700816
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700817 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700818 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700819 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
820 // race with setSyncEvent(). However, if we call it, we cannot properly start
821 // static fast tracks (SoundPool) immediately after stopping.
822 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung87c693c2023-07-06 20:56:16 -0700823 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
824 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700825 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700826 // FIXME This is too eager. We allocate a fast track index before the
827 // fast track becomes active. Since fast tracks are a scarce resource,
828 // this means we are potentially denying other more important fast tracks from
829 // being created. It would be better to allocate the index dynamically.
830 mFastIndex = i;
Andy Hung87c693c2023-07-06 20:56:16 -0700831 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700832 }
Andy Hung8946a282018-04-19 20:04:56 -0700833
Dean Wheatley7b036912020-06-18 16:22:11 +1000834 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700835#ifdef TEE_SINK
836 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800837 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700838#endif
jiabin57303cc2018-12-18 15:45:57 -0800839
jiabineb3bda02020-06-30 14:07:03 -0700840 if (thread->supportsHapticPlayback()) {
841 // If the track is attached to haptic playback thread, it is potentially to have
842 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
843 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800844 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000845 std::string packageName = attributionSource.packageName.has_value() ?
846 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800847 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700848 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800849 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800850
851 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700852 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800853 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800854}
855
Andy Hung8d31fd22023-06-26 19:20:57 -0700856Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800857{
Andy Hung9d84af52018-09-12 18:03:44 -0700858 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700859
860 // The destructor would clear mSharedBuffer,
861 // but it will not push the decremented reference count,
862 // leaving the client's IMemory dangling indefinitely.
863 // This prevents that leak.
864 if (mSharedBuffer != 0) {
865 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700866 }
Eric Laurent81784c32012-11-19 14:55:58 -0800867}
868
Andy Hung8d31fd22023-06-26 19:20:57 -0700869status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700870{
871 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700872 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700873 status = NO_MEMORY;
874 }
875 return status;
876}
877
Andy Hung8d31fd22023-06-26 19:20:57 -0700878void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800879{
880 // NOTE: destroyTrack_l() can remove a strong reference to this Track
881 // by removing it from mTracks vector, so there is a risk that this Tracks's
882 // destructor is called. As the destructor needs to lock mLock,
883 // we must acquire a strong reference on this Track before locking mLock
884 // here so that the destructor is called only when exiting this function.
885 // On the other hand, as long as Track::destroy() is only called by
886 // TrackHandle destructor, the TrackHandle still holds a strong ref on
887 // this Track with its member mTrack.
888 sp<Track> keep(this);
889 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700890 bool wasActive = false;
Andy Hung87c693c2023-07-06 20:56:16 -0700891 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800892 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -0700893 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -0700894 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700895 wasActive = playbackThread->destroyTrack_l(this);
jiabin7434e812023-06-27 18:22:35 +0000896 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700897 }
898 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700899 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800900 }
901 }
902}
903
Andy Hung8d31fd22023-06-26 19:20:57 -0700904void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800905{
Eric Laurent973db022018-11-20 14:54:31 -0800906 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700907 " Format Chn mask SRate "
908 "ST Usg CT "
909 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000910 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700911 "%s\n",
912 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800913}
914
Andy Hung8d31fd22023-06-26 19:20:57 -0700915void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800916{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700917 char trackType;
918 switch (mType) {
919 case TYPE_DEFAULT:
920 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700921 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700922 trackType = 'S'; // static
923 } else {
924 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800925 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700926 break;
927 case TYPE_PATCH:
928 trackType = 'P';
929 break;
930 default:
931 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800932 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700933
934 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700935 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700936 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700937 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700938 }
939
Eric Laurent81784c32012-11-19 14:55:58 -0800940 char nowInUnderrun;
941 switch (mObservedUnderruns.mBitFields.mMostRecent) {
942 case UNDERRUN_FULL:
943 nowInUnderrun = ' ';
944 break;
945 case UNDERRUN_PARTIAL:
946 nowInUnderrun = '<';
947 break;
948 case UNDERRUN_EMPTY:
949 nowInUnderrun = '*';
950 break;
951 default:
952 nowInUnderrun = '?';
953 break;
954 }
Andy Hungda540db2017-04-20 14:06:17 -0700955
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700956 char fillingStatus;
Andy Hung8d31fd22023-06-26 19:20:57 -0700957 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700958 case FS_INVALID:
959 fillingStatus = 'I';
960 break;
961 case FS_FILLING:
962 fillingStatus = 'f';
963 break;
964 case FS_FILLED:
965 fillingStatus = 'F';
966 break;
967 case FS_ACTIVE:
968 fillingStatus = 'A';
969 break;
970 default:
971 fillingStatus = '?';
972 break;
973 }
974
975 // clip framesReadySafe to max representation in dump
976 const size_t framesReadySafe =
977 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
978
979 // obtain volumes
980 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
981 const std::pair<float /* volume */, bool /* active */> vsVolume =
982 mVolumeHandler->getLastVolume();
983
984 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
985 // as it may be reduced by the application.
986 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
987 // Check whether the buffer size has been modified by the app.
988 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
989 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
990 ? 'e' /* error */ : ' ' /* identical */;
991
Eric Laurent973db022018-11-20 14:54:31 -0800992 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700993 "%08X %08X %6u "
994 "%2u %3x %2x "
995 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000996 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800997 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700998 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700999 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001000 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001001 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001002 mCblk->mFlags,
1003
Eric Laurent81784c32012-11-19 14:55:58 -08001004 mFormat,
1005 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001006 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001007
1008 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001009 mAttr.usage,
1010 mAttr.content_type,
1011
1012 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001013 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1014 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001015 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1016 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001017
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001018 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001019 bufferSizeInFrames,
1020 modifiedBufferChar,
1021 framesReadySafe,
1022 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001023 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001024 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001025 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1026 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001027 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001028
1029 if (isServerLatencySupported()) {
1030 double latencyMs;
1031 bool fromTrack;
1032 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1033 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1034 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1035 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001036 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001037 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001038 }
1039 }
1040 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001041}
1042
Andy Hung8d31fd22023-06-26 19:20:57 -07001043uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001044 return mAudioTrackServerProxy->getSampleRate();
1045}
1046
Eric Laurent81784c32012-11-19 14:55:58 -08001047// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07001048status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001049{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001050 ServerProxy::Buffer buf;
1051 size_t desiredFrames = buffer->frameCount;
1052 buf.mFrameCount = desiredFrames;
1053 status_t status = mServerProxy->obtainBuffer(&buf);
1054 buffer->frameCount = buf.mFrameCount;
1055 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001056 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001057 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001058 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001059 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001060 } else {
1061 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001062 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001063 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001064}
1065
Andy Hung8d31fd22023-06-26 19:20:57 -07001066void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001067{
1068 interceptBuffer(*buffer);
1069 TrackBase::releaseBuffer(buffer);
1070}
1071
1072// TODO: compensate for time shift between HW modules.
Andy Hung8d31fd22023-06-26 19:20:57 -07001073void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001074 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001075 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001076 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001077 if (frameCount == 0) {
1078 return; // No audio to intercept.
1079 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1080 // does not allow 0 frame size request contrary to getNextBuffer
1081 }
1082 for (auto& teePatch : mTeePatches) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001083 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001084 const size_t framesWritten = patchRecord->writeFrames(
1085 sourceBuffer.i8, frameCount, mFrameSize);
1086 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001087 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung8d31fd22023-06-26 19:20:57 -07001088 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001089 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001090 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001091 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1092 using namespace std::chrono_literals;
1093 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001094 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001095 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001096}
1097
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001098// ExtendedAudioBufferProvider interface
1099
Andy Hung27876c02014-09-09 18:07:55 -07001100// framesReady() may return an approximation of the number of frames if called
1101// from a different thread than the one calling Proxy->obtainBuffer() and
1102// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1103// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001104size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001105 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1106 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1107 // The remainder of the buffer is not drained.
1108 return 0;
1109 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001110 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001111}
1112
Andy Hung8d31fd22023-06-26 19:20:57 -07001113int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001114{
1115 return mAudioTrackServerProxy->framesReleased();
1116}
1117
Andy Hung8d31fd22023-06-26 19:20:57 -07001118void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001119{
1120 // This call comes from a FastTrack and should be kept lockless.
1121 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001122 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001123
Andy Hung818e7a32016-02-16 18:08:07 -08001124 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001125
1126 // Compute latency.
1127 // TODO: Consider whether the server latency may be passed in by FastMixer
1128 // as a constant for all active FastTracks.
1129 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1130 mServerLatencyFromTrack.store(true);
1131 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001132}
1133
Eric Laurent81784c32012-11-19 14:55:58 -08001134// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung8d31fd22023-06-26 19:20:57 -07001135bool Track::isReady() const {
1136 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001137 return true;
1138 }
1139
Eric Laurent16498512014-03-17 17:22:08 -07001140 if (isStopping()) {
1141 if (framesReady() > 0) {
Andy Hung8d31fd22023-06-26 19:20:57 -07001142 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001143 }
Eric Laurent81784c32012-11-19 14:55:58 -08001144 return true;
1145 }
1146
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001147 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001148 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1149 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1150 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1151 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001152
1153 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1154 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1155 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung8d31fd22023-06-26 19:20:57 -07001156 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001157 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001158 return true;
1159 }
1160 return false;
1161}
1162
Andy Hung8d31fd22023-06-26 19:20:57 -07001163status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001164 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001165{
1166 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001167 ALOGV("%s(%d): calling pid %d session %d",
1168 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001169
Andy Hung87c693c2023-07-06 20:56:16 -07001170 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001171 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001172 if (isOffloaded()) {
Andy Hung954b9712023-08-28 18:36:53 -07001173 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hungab65b182023-09-06 19:41:47 -07001174 const bool nonOffloadableGlobalEffectEnabled =
1175 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hungc5007f82023-08-29 14:26:09 -07001176 audio_utils::lock_guard _lth(thread->mutex());
Andy Hung116bc262023-06-20 18:56:17 -07001177 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hungab65b182023-09-06 19:41:47 -07001178 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001179 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001180 invalidate();
1181 return PERMISSION_DENIED;
1182 }
1183 }
Andy Hungc5007f82023-08-29 14:26:09 -07001184 audio_utils::lock_guard _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001185 track_state state = mState;
1186 // here the track could be either new, or restarted
1187 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001188
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001189 // initial state-stopping. next state-pausing.
1190 // What if resume is called ?
1191
Zhou Song1ed46a22020-08-17 15:36:56 +08001192 if (state == FLUSHED) {
1193 // avoid underrun glitches when starting after flush
1194 reset();
1195 }
1196
kuowei.li576f1362021-05-11 18:02:32 +08001197 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1198 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001199 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001200 if (mResumeToStopping) {
1201 // happened we need to resume to STOPPING_1
1202 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001203 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1204 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001205 } else {
1206 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001207 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1208 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001209 }
Eric Laurent81784c32012-11-19 14:55:58 -08001210 } else {
1211 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001212 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1213 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001214 }
1215
Andy Hung87c693c2023-07-06 20:56:16 -07001216 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu6cfb5932022-07-20 17:40:39 -07001217
1218 // states to reset position info for pcm tracks
1219 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001220 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1221 mFrameMap.reset();
yucliu6cfb5932022-07-20 17:40:39 -07001222
1223 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1224 // Start point of track -> sink frame map. If the HAL returns a
1225 // frame position smaller than the first written frame in
1226 // updateTrackFrameInfo, the timestamp can be interpolated
1227 // instead of using a larger value.
1228 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1229 playbackThread->framesWritten());
1230 }
Andy Hunge10393e2015-06-12 13:59:33 -07001231 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001232 if (isFastTrack()) {
1233 // refresh fast track underruns on start because that field is never cleared
1234 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1235 // after stop.
1236 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1237 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001238 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001239 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001240 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001241 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001242 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001243 mState = state;
1244 }
1245 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001246
Andy Hungb68f5eb2019-12-03 16:49:17 -08001247 // Audio timing metrics are computed a few mix cycles after starting.
1248 {
1249 mLogStartCountdown = LOG_START_COUNTDOWN;
1250 mLogStartTimeNs = systemTime();
1251 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001252 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1253 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001254 }
Andy Hunga81a4b42022-05-19 19:24:51 -07001255 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001256
Andy Hung1d3556d2018-03-29 16:30:14 -07001257 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1258 // for streaming tracks, remove the buffer read stop limit.
1259 mAudioTrackServerProxy->start();
1260 }
1261
Eric Laurentbfb1b832013-01-07 09:53:42 -08001262 // track was already in the active list, not a problem
1263 if (status == ALREADY_EXISTS) {
1264 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001265 } else {
1266 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1267 // It is usually unsafe to access the server proxy from a binder thread.
1268 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1269 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1270 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001271 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001272 ServerProxy::Buffer buffer;
1273 buffer.mFrameCount = 1;
1274 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001275 }
jiabin7434e812023-06-27 18:22:35 +00001276 if (status == NO_ERROR) {
1277 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1278 }
Eric Laurent81784c32012-11-19 14:55:58 -08001279 } else {
1280 status = BAD_VALUE;
1281 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001282 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001283 // send format to AudioManager for playback activity monitoring
Andy Hung583043b2023-07-17 17:05:00 -07001284 const sp<IAudioManager> audioManager =
1285 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001286 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1287 std::unique_ptr<os::PersistableBundle> bundle =
1288 std::make_unique<os::PersistableBundle>();
1289 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1290 isSpatialized());
1291 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1292 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1293 status_t result = audioManager->portEvent(mPortId,
1294 PLAYER_UPDATE_FORMAT, bundle);
1295 if (result != OK) {
1296 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1297 __func__, mPortId, result);
1298 }
1299 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001300 }
Eric Laurent81784c32012-11-19 14:55:58 -08001301 return status;
1302}
1303
Andy Hung8d31fd22023-06-26 19:20:57 -07001304void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001305{
Andy Hungc0691382018-09-12 18:01:57 -07001306 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001307 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001308 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001309 audio_utils::lock_guard _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001310 track_state state = mState;
1311 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1312 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung87c693c2023-07-06 20:56:16 -07001313 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1314 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001315 reset();
1316 mState = STOPPED;
François Gaffie1353b292023-11-03 13:09:53 +01001317 } else if (isPatchTrack() || (!isFastTrack() && !isOffloaded() && !isDirect())) {
1318 // for a PatchTrack (whatever fast ot not), do not drain but move directly
1319 // to STOPPED to avoid closing while active.
Eric Laurent81784c32012-11-19 14:55:58 -08001320 mState = STOPPED;
1321 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001322 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1323 // presentation is complete
1324 // For an offloaded track this starts a drain and state will
1325 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001326 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001327 if (isOffloaded()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001328 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001329 }
Eric Laurent81784c32012-11-19 14:55:58 -08001330 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001331 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001332 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1333 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001334 }
jiabin7434e812023-06-27 18:22:35 +00001335 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001336 }
1337}
1338
Andy Hung8d31fd22023-06-26 19:20:57 -07001339void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001340{
Andy Hungc0691382018-09-12 18:01:57 -07001341 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung87c693c2023-07-06 20:56:16 -07001342 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001343 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001344 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001345 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001346 switch (mState) {
1347 case STOPPING_1:
1348 case STOPPING_2:
1349 if (!isOffloaded()) {
1350 /* nothing to do if track is not offloaded */
1351 break;
1352 }
1353
1354 // Offloaded track was draining, we need to carry on draining when resumed
1355 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001356 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001357 case ACTIVE:
1358 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001359 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001360 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1361 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001362 if (isOffloadedOrDirect()) {
1363 mPauseHwPending = true;
1364 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001365 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001366 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001367
Eric Laurentbfb1b832013-01-07 09:53:42 -08001368 default:
1369 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001370 }
jiabin7434e812023-06-27 18:22:35 +00001371 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1372 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001373 }
1374}
1375
Andy Hung8d31fd22023-06-26 19:20:57 -07001376void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001377{
Andy Hungc0691382018-09-12 18:01:57 -07001378 ALOGV("%s(%d)", __func__, mId);
Andy Hung87c693c2023-07-06 20:56:16 -07001379 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001380 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001381 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001382 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001383
Phil Burk4bb650b2016-09-09 12:11:17 -07001384 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1385 // Otherwise the flush would not be done until the track is resumed.
1386 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung87c693c2023-07-06 20:56:16 -07001387 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001388 (void)mServerProxy->flushBufferIfNeeded();
1389 }
1390
Eric Laurentbfb1b832013-01-07 09:53:42 -08001391 if (isOffloaded()) {
1392 // If offloaded we allow flush during any state except terminated
1393 // and keep the track active to avoid problems if user is seeking
1394 // rapidly and underlying hardware has a significant delay handling
1395 // a pause
1396 if (isTerminated()) {
1397 return;
1398 }
1399
Andy Hung9d84af52018-09-12 18:03:44 -07001400 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001401 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001402
1403 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001404 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1405 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001406 mState = ACTIVE;
1407 }
1408
Haynes Mathew George7844f672014-01-15 12:32:55 -08001409 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001410 mResumeToStopping = false;
1411 } else {
1412 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1413 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1414 return;
1415 }
1416 // No point remaining in PAUSED state after a flush => go to
1417 // FLUSHED state
1418 mState = FLUSHED;
1419 // do not reset the track if it is still in the process of being stopped or paused.
1420 // this will be done by prepareTracks_l() when the track is stopped.
1421 // prepareTracks_l() will see mState == FLUSHED, then
1422 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001423 if (isDirect()) {
1424 mFlushHwPending = true;
1425 }
Andy Hung87c693c2023-07-06 20:56:16 -07001426 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001427 reset();
1428 }
Eric Laurent81784c32012-11-19 14:55:58 -08001429 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001430 // Prevent flush being lost if the track is flushed and then resumed
1431 // before mixer thread can run. This is important when offloading
1432 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001433 playbackThread->broadcast_l();
jiabin7434e812023-06-27 18:22:35 +00001434 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1435 // new data
1436 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001437 }
1438}
1439
Haynes Mathew George7844f672014-01-15 12:32:55 -08001440// must be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001441void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001442{
Andy Hung920f6572022-10-06 12:09:49 -07001443 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001444 return;
Andy Hung920f6572022-10-06 12:09:49 -07001445 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001446
Phil Burk4bb650b2016-09-09 12:11:17 -07001447 // Clear the client ring buffer so that the app can prime the buffer while paused.
1448 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1449 mServerProxy->flushBufferIfNeeded();
1450
Haynes Mathew George7844f672014-01-15 12:32:55 -08001451 mFlushHwPending = false;
1452}
1453
Andy Hung8d31fd22023-06-26 19:20:57 -07001454void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001455{
1456 mPauseHwPending = false;
1457}
1458
Andy Hung8d31fd22023-06-26 19:20:57 -07001459void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001460{
1461 // Do not reset twice to avoid discarding data written just after a flush and before
1462 // the audioflinger thread detects the track is stopped.
1463 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001464 // Force underrun condition to avoid false underrun callback until first data is
1465 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001466 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung8d31fd22023-06-26 19:20:57 -07001467 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001468 mResetDone = true;
1469 if (mState == FLUSHED) {
1470 mState = IDLE;
1471 }
1472 }
1473}
1474
Andy Hung8d31fd22023-06-26 19:20:57 -07001475status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001476{
Andy Hung87c693c2023-07-06 20:56:16 -07001477 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001478 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001479 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001480 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001481 } else if (thread->type() == IAfThreadBase::DIRECT
1482 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001483 return thread->setParameters(keyValuePairs);
1484 } else {
1485 return PERMISSION_DENIED;
1486 }
1487}
1488
Andy Hung8d31fd22023-06-26 19:20:57 -07001489status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001490 int programId) {
Andy Hung87c693c2023-07-06 20:56:16 -07001491 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001492 if (thread == 0) {
1493 ALOGE("thread is dead");
1494 return FAILED_TRANSACTION;
Andy Hung87c693c2023-07-06 20:56:16 -07001495 } else if (thread->type() == IAfThreadBase::DIRECT
1496 || thread->type() == IAfThreadBase::OFFLOAD) {
1497 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001498 return directOutputThread->selectPresentation(presentationId, programId);
1499 }
1500 return INVALID_OPERATION;
1501}
1502
Andy Hung8d31fd22023-06-26 19:20:57 -07001503VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001504 const sp<VolumeShaper::Configuration>& configuration,
1505 const sp<VolumeShaper::Operation>& operation)
1506{
Andy Hung398ffa22022-12-13 19:19:53 -08001507 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001508
1509 if (isOffloadedOrDirect()) {
1510 // Signal thread to fetch new volume.
Andy Hung87c693c2023-07-06 20:56:16 -07001511 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001512 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07001513 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001514 thread->broadcast_l();
1515 }
1516 }
1517 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001518}
1519
Andy Hung8d31fd22023-06-26 19:20:57 -07001520sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001521{
1522 // Note: We don't check if Thread exists.
1523
1524 // mVolumeHandler is thread safe.
1525 return mVolumeHandler->getVolumeShaperState(id);
1526}
1527
Andy Hung8d31fd22023-06-26 19:20:57 -07001528void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001529{
jiabin76d94692022-12-15 21:51:21 +00001530 mFinalVolumeLeft = volumeLeft;
1531 mFinalVolumeRight = volumeRight;
1532 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001533 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1534 mFinalVolume = volume;
1535 setMetadataHasChanged();
Andy Hunga81a4b42022-05-19 19:24:51 -07001536 mLogForceVolumeUpdate = true;
1537 }
1538 if (mLogForceVolumeUpdate) {
1539 mLogForceVolumeUpdate = false;
1540 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001541 }
1542}
1543
Andy Hung8d31fd22023-06-26 19:20:57 -07001544void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001545{
Eric Laurent49e39282022-06-24 18:42:45 +02001546 // Do not forward metadata for PatchTrack with unspecified stream type
1547 if (mStreamType == AUDIO_STREAM_PATCH) {
1548 return;
1549 }
1550
Eric Laurent94579172020-11-20 18:41:04 +01001551 playback_track_metadata_v7_t metadata;
1552 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001553 .usage = mAttr.usage,
1554 .content_type = mAttr.content_type,
1555 .gain = mFinalVolume,
1556 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001557
1558 // When attributes are undefined, derive default values from stream type.
1559 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1560 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1561 switch (mStreamType) {
1562 case AUDIO_STREAM_VOICE_CALL:
1563 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1564 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1565 break;
1566 case AUDIO_STREAM_SYSTEM:
1567 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1568 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1569 break;
1570 case AUDIO_STREAM_RING:
1571 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1572 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1573 break;
1574 case AUDIO_STREAM_MUSIC:
1575 metadata.base.usage = AUDIO_USAGE_MEDIA;
1576 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1577 break;
1578 case AUDIO_STREAM_ALARM:
1579 metadata.base.usage = AUDIO_USAGE_ALARM;
1580 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1581 break;
1582 case AUDIO_STREAM_NOTIFICATION:
1583 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1584 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1585 break;
1586 case AUDIO_STREAM_DTMF:
1587 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1588 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1589 break;
1590 case AUDIO_STREAM_ACCESSIBILITY:
1591 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1592 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1593 break;
1594 case AUDIO_STREAM_ASSISTANT:
1595 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1596 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1597 break;
1598 case AUDIO_STREAM_REROUTING:
1599 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1600 // unknown content type
1601 break;
1602 case AUDIO_STREAM_CALL_ASSISTANT:
1603 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1604 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1605 break;
1606 default:
1607 break;
1608 }
1609 }
1610
Eric Laurent78b07302022-10-07 16:20:34 +02001611 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001612 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1613 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001614}
1615
Andy Hung8d31fd22023-06-26 19:20:57 -07001616void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001617 if (mTeePatchesToUpdate.has_value()) {
jiabin7434e812023-06-27 18:22:35 +00001618 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001619 mTeePatches = mTeePatchesToUpdate.value();
1620 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1621 mState == TrackBase::STOPPING_1) {
jiabin7434e812023-06-27 18:22:35 +00001622 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001623 }
1624 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001625 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001626}
1627
Andy Hung16ed0da2023-07-14 11:45:38 -07001628void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001629 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1630 "%s, existing tee patches to update will be ignored", __func__);
1631 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1632}
1633
Vlad Popae8d99472022-06-30 16:02:48 +02001634// must be called with player thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001635void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001636 IAudioManager>& audioManager, mute_state_t muteState)
1637{
1638 if (mMuteState == muteState) {
1639 // mute state did not change, do nothing
1640 return;
1641 }
1642
1643 status_t result = UNKNOWN_ERROR;
1644 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1645 if (mMuteEventExtras == nullptr) {
1646 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1647 }
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001648 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001649
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001650 result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
Vlad Popae8d99472022-06-30 16:02:48 +02001651 }
1652
1653 if (result == OK) {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001654 ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
1655 int(muteState), int(mMuteState));
Vlad Popae8d99472022-06-30 16:02:48 +02001656 mMuteState = muteState;
1657 } else {
Shunkai Yaoaf7990a2023-08-18 02:24:01 +00001658 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
1659 mPortId, result);
Vlad Popae8d99472022-06-30 16:02:48 +02001660 }
1661}
1662
Andy Hung8d31fd22023-06-26 19:20:57 -07001663status_t Track::getTimestamp(AudioTimestamp& timestamp)
Glenn Kasten573d80a2013-08-26 09:36:23 -07001664{
Andy Hung818e7a32016-02-16 18:08:07 -08001665 if (!isOffloaded() && !isDirect()) {
1666 return INVALID_OPERATION; // normal tracks handled through SSQ
Glenn Kastenfe346c72013-08-30 13:28:22 -07001667 }
Andy Hung87c693c2023-07-06 20:56:16 -07001668 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001669 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001670 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001671 }
Phil Burk6140c792015-03-19 14:30:21 -07001672
Andy Hungc5007f82023-08-29 14:26:09 -07001673 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001674 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001675 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001676}
1677
Andy Hung8d31fd22023-06-26 19:20:57 -07001678status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001679{
Andy Hung87c693c2023-07-06 20:56:16 -07001680 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001681 if (thread == nullptr) {
1682 return DEAD_OBJECT;
1683 }
Eric Laurent81784c32012-11-19 14:55:58 -08001684
Andy Hung87c693c2023-07-06 20:56:16 -07001685 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung8d31fd22023-06-26 19:20:57 -07001686 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung87c693c2023-07-06 20:56:16 -07001687 sp<IAfPlaybackThread> srcThread;
Andy Hung47c01172023-07-17 12:40:43 -07001688 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001689 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001690
Eric Laurent6c796322019-04-09 14:13:17 -07001691 if (EffectId != 0 && status == NO_ERROR) {
1692 status = dstThread->attachAuxEffect(this, EffectId);
1693 if (status == NO_ERROR) {
1694 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001695 }
Eric Laurent6c796322019-04-09 14:13:17 -07001696 }
1697
1698 if (status != NO_ERROR && srcThread != nullptr) {
1699 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001700 }
1701 return status;
1702}
1703
Andy Hung8d31fd22023-06-26 19:20:57 -07001704void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001705{
1706 mAuxEffectId = EffectId;
1707 mAuxBuffer = buffer;
1708}
1709
Andy Hung59de4262021-06-14 10:53:54 -07001710// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001711bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001712 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001713{
Andy Hung818e7a32016-02-16 18:08:07 -08001714 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1715 // This assists in proper timestamp computation as well as wakelock management.
1716
Eric Laurent81784c32012-11-19 14:55:58 -08001717 // a track is considered presented when the total number of frames written to audio HAL
1718 // corresponds to the number of frames written when presentationComplete() is called for the
1719 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001720 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1721 // to detect when all frames have been played. In this case framesWritten isn't
1722 // useful because it doesn't always reflect whether there is data in the h/w
1723 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001724 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1725 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001726 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001727 if (mPresentationCompleteFrames == 0) {
1728 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001729 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001730 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1731 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001732 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001733 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001734
Andy Hungc54b1ff2016-02-23 14:07:07 -08001735 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001736 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001737 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001738 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1739 __func__, mId, (complete ? "complete" : "waiting"),
1740 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001741 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001742 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001743 && mAudioTrackServerProxy->isDrained();
1744 }
1745
1746 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001747 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001748 return true;
1749 }
1750 return false;
1751}
1752
Andy Hung59de4262021-06-14 10:53:54 -07001753// presentationComplete checked by time, used by DirectTracks.
Andy Hung8d31fd22023-06-26 19:20:57 -07001754bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001755{
1756 // For Offloaded or Direct tracks.
1757
1758 // For a direct track, we incorporated time based testing for presentationComplete.
1759
1760 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1761 // to detect when all frames have been played. In this case latencyMs isn't
1762 // useful because it doesn't always reflect whether there is data in the h/w
1763 // buffers, particularly if a track has been paused and resumed during draining
1764
1765 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1766 if (mPresentationCompleteTimeNs == 0) {
1767 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1768 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1769 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1770 }
1771
1772 bool complete;
1773 if (isOffloaded()) {
1774 complete = true;
1775 } else { // Direct
1776 complete = systemTime() >= mPresentationCompleteTimeNs;
1777 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1778 }
1779 if (complete) {
1780 notifyPresentationComplete();
1781 return true;
1782 }
1783 return false;
1784}
1785
Andy Hung8d31fd22023-06-26 19:20:57 -07001786void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001787{
1788 // This only triggers once. TODO: should we enforce this?
1789 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1790 mAudioTrackServerProxy->setStreamEndDone();
1791}
1792
Andy Hung8d31fd22023-06-26 19:20:57 -07001793void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001794{
Andy Hung068e08e2023-05-15 19:02:55 -07001795 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1796 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001797 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001798 (*it)->trigger();
1799 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001800 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001801 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001802 }
1803 }
1804}
1805
1806// implement VolumeBufferProvider interface
1807
Andy Hung8d31fd22023-06-26 19:20:57 -07001808gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001809{
1810 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1811 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001812 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1813 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1814 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001815 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001816 if (vl > GAIN_FLOAT_UNITY) {
1817 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001818 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001819 if (vr > GAIN_FLOAT_UNITY) {
1820 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001821 }
1822 // now apply the cached master volume and stream type volume;
1823 // this is trusted but lacks any synchronization or barrier so may be stale
1824 float v = mCachedVolume;
1825 vl *= v;
1826 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001827 // re-combine into packed minifloat
1828 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001829 // FIXME look at mute, pause, and stop flags
1830 return vlr;
1831}
1832
Andy Hung8d31fd22023-06-26 19:20:57 -07001833status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001834 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001835{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001836 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001837 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1838 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001839 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1840 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001841 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001842 event->cancel();
1843 return INVALID_OPERATION;
1844 }
1845 (void) TrackBase::setSyncEvent(event);
1846 return NO_ERROR;
1847}
1848
Andy Hung8d31fd22023-06-26 19:20:57 -07001849void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001850{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001851 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001852 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001853}
1854
Andy Hung8d31fd22023-06-26 19:20:57 -07001855void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001856{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001857 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001858 signalClientFlag(CBLK_DISABLED);
1859}
1860
Andy Hung8d31fd22023-06-26 19:20:57 -07001861void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001862{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001863 // FIXME should use proxy, and needs work
1864 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001865 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001866 android_atomic_release_store(0x40000000, &cblk->mFutex);
1867 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001868 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001869}
1870
Andy Hung8d31fd22023-06-26 19:20:57 -07001871void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001872{
Andy Hung87c693c2023-07-06 20:56:16 -07001873 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001874 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07001875 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001876 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001877 t->broadcast_l();
1878 }
1879}
1880
Andy Hung8d31fd22023-06-26 19:20:57 -07001881status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001882{
1883 status_t status = INVALID_OPERATION;
1884 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001885 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001886 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001887 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001888 audio_utils::lock_guard _l(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001889 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001890 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1891 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1892 }
1893 }
1894 return status;
1895}
1896
Andy Hung8d31fd22023-06-26 19:20:57 -07001897status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001898{
1899 status_t status = INVALID_OPERATION;
1900 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001901 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001902 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001903 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001904 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001905 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001906 if (status == NO_ERROR) {
1907 mDualMonoMode = mode;
1908 }
1909 }
1910 }
1911 return status;
1912}
1913
Andy Hung8d31fd22023-06-26 19:20:57 -07001914status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001915{
1916 status_t status = INVALID_OPERATION;
1917 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001918 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001919 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001920 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001921 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001922 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001923 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1924 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1925 }
1926 }
1927 return status;
1928}
1929
Andy Hung8d31fd22023-06-26 19:20:57 -07001930status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001931{
1932 status_t status = INVALID_OPERATION;
1933 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001934 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001935 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001936 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001937 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001938 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001939 if (status == NO_ERROR) {
1940 mAudioDescriptionMixLevel = leveldB;
1941 }
1942 }
1943 }
1944 return status;
1945}
1946
Andy Hung8d31fd22023-06-26 19:20:57 -07001947status_t Track::getPlaybackRateParameters(
Andy Hungd29af632023-06-23 19:27:19 -07001948 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001949{
1950 status_t status = INVALID_OPERATION;
1951 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001952 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001953 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001954 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001955 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001956 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001957 ALOGD_IF((status == NO_ERROR) &&
1958 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1959 "%s: playbackRate inconsistent", __func__);
1960 }
1961 }
1962 return status;
1963}
1964
Andy Hung8d31fd22023-06-26 19:20:57 -07001965status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001966 const audio_playback_rate_t& playbackRate)
1967{
1968 status_t status = INVALID_OPERATION;
1969 if (isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07001970 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001971 if (thread != nullptr) {
Andy Hung87c693c2023-07-06 20:56:16 -07001972 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07001973 audio_utils::lock_guard lock(t->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07001974 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001975 if (status == NO_ERROR) {
1976 mPlaybackRateParameters = playbackRate;
1977 }
1978 }
1979 }
1980 return status;
1981}
1982
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001983//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001984bool Track::isResumePending() const {
Andy Hung920f6572022-10-06 12:09:49 -07001985 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001986 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001987 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001988 /* Resume is pending if track was stopping before pause was called */
1989 if (mState == STOPPING_1 &&
Andy Hung920f6572022-10-06 12:09:49 -07001990 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001991 return true;
Andy Hung920f6572022-10-06 12:09:49 -07001992 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001993
1994 return false;
1995}
1996
1997//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07001998void Track::resumeAck() {
Andy Hung920f6572022-10-06 12:09:49 -07001999 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002000 mState = ACTIVE;
Andy Hung920f6572022-10-06 12:09:49 -07002001 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002002
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002003 // Other possibility of pending resume is stopping_1 state
2004 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002005 // drain being called.
2006 if (mState == STOPPING_1) {
2007 mResumeToStopping = false;
2008 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002009}
Andy Hunge10393e2015-06-12 13:59:33 -07002010
2011//To be called with thread lock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002012void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002013 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002014 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002015 // Make the kernel frametime available.
2016 const FrameTime ft{
2017 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2018 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2019 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2020 mKernelFrameTime.store(ft);
2021 if (!audio_is_linear_pcm(mFormat)) {
2022 return;
2023 }
2024
Andy Hung818e7a32016-02-16 18:08:07 -08002025 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002026 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002027
2028 // adjust server times and set drained state.
2029 //
2030 // Our timestamps are only updated when the track is on the Thread active list.
2031 // We need to ensure that tracks are not removed before full drain.
2032 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002033 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002034 bool checked = false;
2035 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2036 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2037 // Lookup the track frame corresponding to the sink frame position.
2038 if (local.mTimeNs[i] > 0) {
2039 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2040 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002041 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002042 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002043 checked = true;
2044 }
2045 }
Andy Hunge10393e2015-06-12 13:59:33 -07002046 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002047
Andy Hung93bb5732023-05-04 21:16:34 -07002048 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2049 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002050 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002051 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002052 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002053 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002054
2055 // Compute latency info.
2056 const bool useTrackTimestamp = !drained;
2057 const double latencyMs = useTrackTimestamp
2058 ? local.getOutputServerLatencyMs(sampleRate())
2059 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2060
2061 mServerLatencyFromTrack.store(useTrackTimestamp);
2062 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002063
Andy Hung62921122020-05-18 10:47:31 -07002064 if (mLogStartCountdown > 0
2065 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2066 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2067 {
2068 if (mLogStartCountdown > 1) {
2069 --mLogStartCountdown;
2070 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2071 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002072 // startup is the difference in times for the current timestamp and our start
2073 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002074 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002075 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002076 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2077 * 1e3 / mSampleRate;
2078 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2079 " localTime:%lld startTime:%lld"
2080 " localPosition:%lld startPosition:%lld",
2081 __func__, latencyMs, startUpMs,
2082 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002083 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002084 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002085 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002086 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002087 }
Andy Hung62921122020-05-18 10:47:31 -07002088 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002089 }
Andy Hunge10393e2015-06-12 13:59:33 -07002090}
2091
Andy Hung8d31fd22023-06-26 19:20:57 -07002092bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung87c693c2023-07-06 20:56:16 -07002093 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002094 if (thread != 0) {
2095 // Lock for updating mHapticPlaybackEnabled.
Andy Hungc5007f82023-08-29 14:26:09 -07002096 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002097 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002098 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung87c693c2023-07-06 20:56:16 -07002099 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002100 ALOGD("%s, haptic playback was %s for track %d",
2101 __func__, muted ? "muted" : "unmuted", mTrack->id());
2102 mTrack->setHapticPlaybackEnabled(!muted);
2103 return true;
jiabin57303cc2018-12-18 15:45:57 -08002104 }
2105 }
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002106 return false;
2107}
2108
Andy Hung8d31fd22023-06-26 19:20:57 -07002109binder::Status Track::AudioVibrationController::mute(
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002110 /*out*/ bool *ret) {
2111 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002112 return binder::Status::ok();
2113}
2114
Andy Hung8d31fd22023-06-26 19:20:57 -07002115binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002116 /*out*/ bool *ret) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002117 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002118 return binder::Status::ok();
2119}
2120
Eric Laurent81784c32012-11-19 14:55:58 -08002121// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002122#undef LOG_TAG
2123#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002124
Andy Hung8d31fd22023-06-26 19:20:57 -07002125/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002126sp<IAfOutputTrack> IAfOutputTrack::create(
2127 IAfPlaybackThread* playbackThread,
2128 IAfDuplicatingThread* sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002129 uint32_t sampleRate,
2130 audio_format_t format,
2131 audio_channel_mask_t channelMask,
2132 size_t frameCount,
2133 const AttributionSourceState& attributionSource) {
2134 return sp<OutputTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002135 playbackThread,
2136 sourceThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002137 sampleRate,
2138 format,
2139 channelMask,
2140 frameCount,
2141 attributionSource);
2142}
2143
2144OutputTrack::OutputTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002145 IAfPlaybackThread* playbackThread,
2146 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002147 uint32_t sampleRate,
2148 audio_format_t format,
2149 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002150 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002151 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002152 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002153 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002154 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002155 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002156 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002157 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002158 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002159{
2160
2161 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002162 mOutBuffer.frameCount = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002163 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002164 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002165 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002166 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002167 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002168 // since client and server are in the same process,
2169 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002170 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2171 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002172 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002173 mClientProxy->setSendLevel(0.0);
2174 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002175 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002176 ALOGW("%s(%d): Error creating output track on thread %d",
2177 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002178 }
2179}
2180
Andy Hung8d31fd22023-06-26 19:20:57 -07002181OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002182{
2183 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002184 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002185}
2186
Andy Hung8d31fd22023-06-26 19:20:57 -07002187status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002188 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002189{
2190 status_t status = Track::start(event, triggerSession);
2191 if (status != NO_ERROR) {
2192 return status;
2193 }
2194
2195 mActive = true;
2196 mRetryCount = 127;
2197 return status;
2198}
2199
Andy Hung8d31fd22023-06-26 19:20:57 -07002200void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002201{
2202 Track::stop();
2203 clearBufferQueue();
2204 mOutBuffer.frameCount = 0;
2205 mActive = false;
2206}
2207
Andy Hung8d31fd22023-06-26 19:20:57 -07002208ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002209{
Eric Laurent19952e12023-04-20 10:08:29 +02002210 if (!mActive && frames != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002211 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002212 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002213 // preload one silent buffer to trigger mixer on start()
2214 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2215 status_t status = mClientProxy->obtainBuffer(&buf);
2216 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2217 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2218 return 0;
2219 }
2220 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2221 mClientProxy->releaseBuffer(&buf);
2222
2223 (void) start();
2224
2225 // wait for HAL stream to start before sending actual audio. Doing this on each
2226 // OutputTrack makes that playback start on all output streams is synchronized.
2227 // If another OutputTrack has already started it can underrun but this is OK
2228 // as only silence has been played so far and the retry count is very high on
2229 // OutputTrack.
Andy Hung87c693c2023-07-06 20:56:16 -07002230 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002231 if (!pt->waitForHalStart()) {
2232 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2233 stop();
2234 return 0;
2235 }
2236
2237 // enqueue the first buffer and exit so that other OutputTracks will also start before
2238 // write() is called again and this buffer actually consumed.
2239 Buffer firstBuffer;
2240 firstBuffer.frameCount = frames;
2241 firstBuffer.raw = data;
2242 queueBuffer(firstBuffer);
2243 return frames;
2244 } else {
2245 (void) start();
2246 }
2247 }
2248
Eric Laurent81784c32012-11-19 14:55:58 -08002249 Buffer *pInBuffer;
2250 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002251 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002252 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002253 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002254 while (waitTimeLeftMs) {
2255 // First write pending buffers, then new data
2256 if (mBufferQueue.size()) {
2257 pInBuffer = mBufferQueue.itemAt(0);
2258 } else {
2259 pInBuffer = &inBuffer;
2260 }
2261
2262 if (pInBuffer->frameCount == 0) {
2263 break;
2264 }
2265
2266 if (mOutBuffer.frameCount == 0) {
2267 mOutBuffer.frameCount = pInBuffer->frameCount;
2268 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002269 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002270 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002271 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2272 __func__, mId,
2273 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002274 break;
2275 }
2276 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2277 if (waitTimeLeftMs >= waitTimeMs) {
2278 waitTimeLeftMs -= waitTimeMs;
2279 } else {
2280 waitTimeLeftMs = 0;
2281 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002282 if (status == NOT_ENOUGH_DATA) {
2283 restartIfDisabled();
2284 continue;
2285 }
Eric Laurent81784c32012-11-19 14:55:58 -08002286 }
2287
2288 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2289 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002290 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002291 Proxy::Buffer buf;
2292 buf.mFrameCount = outFrames;
2293 buf.mRaw = NULL;
2294 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002295 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002296 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002297 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002298 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002299 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002300
2301 if (pInBuffer->frameCount == 0) {
2302 if (mBufferQueue.size()) {
2303 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002304 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002305 if (pInBuffer != &inBuffer) {
2306 delete pInBuffer;
2307 }
Andy Hung9d84af52018-09-12 18:03:44 -07002308 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2309 __func__, mId,
2310 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002311 } else {
2312 break;
2313 }
2314 }
2315 }
2316
2317 // If we could not write all frames, allocate a buffer and queue it for next time.
2318 if (inBuffer.frameCount) {
Andy Hung87c693c2023-07-06 20:56:16 -07002319 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung440901d2023-06-29 21:19:25 -07002320 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002321 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002322 }
2323 }
2324
Andy Hungc25b84a2015-01-14 19:04:10 -08002325 // Calling write() with a 0 length buffer means that no more data will be written:
2326 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2327 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2328 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002329 }
2330
Andy Hung1c86ebe2018-05-29 20:29:08 -07002331 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002332}
2333
Andy Hung8d31fd22023-06-26 19:20:57 -07002334void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002335
2336 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2337 Buffer *pInBuffer = new Buffer;
2338 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2339 pInBuffer->mBuffer = malloc(bufferSize);
2340 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2341 "%s: Unable to malloc size %zu", __func__, bufferSize);
2342 pInBuffer->frameCount = inBuffer.frameCount;
2343 pInBuffer->raw = pInBuffer->mBuffer;
2344 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2345 mBufferQueue.add(pInBuffer);
2346 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2347 (int)mThreadIoHandle, mBufferQueue.size());
2348 // audio data is consumed (stored locally); set frameCount to 0.
2349 inBuffer.frameCount = 0;
2350 } else {
2351 ALOGW("%s(%d): thread %d no more overflow buffers",
2352 __func__, mId, (int)mThreadIoHandle);
2353 // TODO: return error for this.
2354 }
2355}
2356
Andy Hung8d31fd22023-06-26 19:20:57 -07002357void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002358{
Andy Hungc5007f82023-08-29 14:26:09 -07002359 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002360 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2361}
2362
Andy Hung8d31fd22023-06-26 19:20:57 -07002363void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002364 {
Andy Hungc5007f82023-08-29 14:26:09 -07002365 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002366 mTrackMetadatas = metadatas;
2367 }
2368 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2369 setMetadataHasChanged();
2370}
2371
Andy Hung8d31fd22023-06-26 19:20:57 -07002372status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002373 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2374{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002375 ClientProxy::Buffer buf;
2376 buf.mFrameCount = buffer->frameCount;
2377 struct timespec timeout;
2378 timeout.tv_sec = waitTimeMs / 1000;
2379 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2380 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2381 buffer->frameCount = buf.mFrameCount;
2382 buffer->raw = buf.mRaw;
2383 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002384}
2385
Andy Hung8d31fd22023-06-26 19:20:57 -07002386void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002387{
2388 size_t size = mBufferQueue.size();
2389
2390 for (size_t i = 0; i < size; i++) {
2391 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002392 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002393 delete pBuffer;
2394 }
2395 mBufferQueue.clear();
2396}
2397
Andy Hung8d31fd22023-06-26 19:20:57 -07002398void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002399{
2400 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2401 if (mActive && (flags & CBLK_DISABLED)) {
2402 start();
2403 }
2404}
Eric Laurent81784c32012-11-19 14:55:58 -08002405
Andy Hung9d84af52018-09-12 18:03:44 -07002406// ----------------------------------------------------------------------------
2407#undef LOG_TAG
2408#define LOG_TAG "AF::PatchTrack"
2409
Andy Hung8d31fd22023-06-26 19:20:57 -07002410/* static */
2411sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung87c693c2023-07-06 20:56:16 -07002412 IAfPlaybackThread* playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002413 audio_stream_type_t streamType,
2414 uint32_t sampleRate,
2415 audio_channel_mask_t channelMask,
2416 audio_format_t format,
2417 size_t frameCount,
2418 void* buffer,
2419 size_t bufferSize,
2420 audio_output_flags_t flags,
2421 const Timeout& timeout,
2422 size_t frameCountToBeReady /** Default behaviour is to start
2423 * as soon as possible to have
2424 * the lowest possible latency
2425 * even if it might glitch. */)
2426{
2427 return sp<PatchTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002428 playbackThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002429 streamType,
2430 sampleRate,
2431 channelMask,
2432 format,
2433 frameCount,
2434 buffer,
2435 bufferSize,
2436 flags,
2437 timeout,
2438 frameCountToBeReady);
2439}
2440
Andy Hung87c693c2023-07-06 20:56:16 -07002441PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002442 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002443 uint32_t sampleRate,
2444 audio_channel_mask_t channelMask,
2445 audio_format_t format,
2446 size_t frameCount,
2447 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002448 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002449 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002450 const Timeout& timeout,
2451 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002452 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002453 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002454 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002455 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002456 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002457 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002458 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2459 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07002460 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002461{
Andy Hung9d84af52018-09-12 18:03:44 -07002462 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2463 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002464 (int)mPeerTimeout.tv_sec,
2465 (int)(mPeerTimeout.tv_nsec / 1000000));
2466}
2467
Andy Hung8d31fd22023-06-26 19:20:57 -07002468PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002469{
Andy Hungabfab202019-03-07 19:45:54 -08002470 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002471}
2472
Andy Hung8d31fd22023-06-26 19:20:57 -07002473size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002474{
2475 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2476 return std::numeric_limits<size_t>::max();
2477 } else {
2478 return Track::framesReady();
2479 }
2480}
2481
Andy Hung8d31fd22023-06-26 19:20:57 -07002482status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002483 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002484{
2485 status_t status = Track::start(event, triggerSession);
2486 if (status != NO_ERROR) {
2487 return status;
2488 }
2489 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2490 return status;
2491}
2492
Eric Laurent83b88082014-06-20 18:31:16 -07002493// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002494status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002495 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002496{
Andy Hung9d84af52018-09-12 18:03:44 -07002497 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002498 Proxy::Buffer buf;
2499 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002500 if (ATRACE_ENABLED()) {
2501 std::string traceName("PTnReq");
2502 traceName += std::to_string(id());
2503 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2504 }
Eric Laurent83b88082014-06-20 18:31:16 -07002505 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002506 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002507 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002508 if (ATRACE_ENABLED()) {
2509 std::string traceName("PTnObt");
2510 traceName += std::to_string(id());
2511 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2512 }
Eric Laurent83b88082014-06-20 18:31:16 -07002513 if (buf.mFrameCount == 0) {
2514 return WOULD_BLOCK;
2515 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002516 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002517 return status;
2518}
2519
Andy Hung8d31fd22023-06-26 19:20:57 -07002520void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002521{
Andy Hung9d84af52018-09-12 18:03:44 -07002522 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002523 Proxy::Buffer buf;
2524 buf.mFrameCount = buffer->frameCount;
2525 buf.mRaw = buffer->raw;
2526 mPeerProxy->releaseBuffer(&buf);
Andy Hung920f6572022-10-06 12:09:49 -07002527 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002528}
2529
Andy Hung8d31fd22023-06-26 19:20:57 -07002530status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002531 const struct timespec *timeOut)
2532{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002533 status_t status = NO_ERROR;
2534 static const int32_t kMaxTries = 5;
2535 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002536 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002537 do {
2538 if (status == NOT_ENOUGH_DATA) {
2539 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002540 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002541 }
2542 status = mProxy->obtainBuffer(buffer, timeOut);
2543 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2544 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002545}
2546
Andy Hung8d31fd22023-06-26 19:20:57 -07002547void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002548{
2549 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002550 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002551
2552 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2553 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2554 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2555 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung8d31fd22023-06-26 19:20:57 -07002556 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002557 && audio_is_linear_pcm(mFormat)
2558 && !isOffloadedOrDirect()) {
Andy Hung87c693c2023-07-06 20:56:16 -07002559 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002560 thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002561 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002562 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2563 / playbackThread->sampleRate();
2564 if (framesReady() < frameCount) {
2565 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung8d31fd22023-06-26 19:20:57 -07002566 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002567 }
2568 }
2569 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002570}
2571
Andy Hung8d31fd22023-06-26 19:20:57 -07002572void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002573{
Eric Laurent83b88082014-06-20 18:31:16 -07002574 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002575 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002576 start();
2577 }
Eric Laurent83b88082014-06-20 18:31:16 -07002578}
2579
Eric Laurent81784c32012-11-19 14:55:58 -08002580// ----------------------------------------------------------------------------
2581// Record
2582// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002583
2584
Andy Hung9d84af52018-09-12 18:03:44 -07002585#undef LOG_TAG
2586#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002587
Andy Hunga5a7fc92023-06-23 19:27:19 -07002588class RecordHandle : public android::media::BnAudioRecord {
2589public:
Andy Hungd29af632023-06-23 19:27:19 -07002590 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hunga5a7fc92023-06-23 19:27:19 -07002591 ~RecordHandle() override;
2592 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2593 int /*audio_session_t*/ triggerSession) final;
2594 binder::Status stop() final;
2595 binder::Status getActiveMicrophones(
2596 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2597 binder::Status setPreferredMicrophoneDirection(
2598 int /*audio_microphone_direction_t*/ direction) final;
2599 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2600 binder::Status shareAudioHistory(
2601 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2602
2603private:
Andy Hungd29af632023-06-23 19:27:19 -07002604 const sp<IAfRecordTrack> mRecordTrack;
Andy Hunga5a7fc92023-06-23 19:27:19 -07002605
2606 // for use from destructor
2607 void stop_nonvirtual();
2608};
2609
2610/* static */
Andy Hungd29af632023-06-23 19:27:19 -07002611sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2612 const sp<IAfRecordTrack>& recordTrack) {
Andy Hunga5a7fc92023-06-23 19:27:19 -07002613 return sp<RecordHandle>::make(recordTrack);
2614}
2615
2616RecordHandle::RecordHandle(
Andy Hungd29af632023-06-23 19:27:19 -07002617 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002618 : BnAudioRecord(),
2619 mRecordTrack(recordTrack)
2620{
Andy Hung225aef62022-12-06 16:33:20 -08002621 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002622}
2623
Andy Hunga5a7fc92023-06-23 19:27:19 -07002624RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002625 stop_nonvirtual();
2626 mRecordTrack->destroy();
2627}
2628
Andy Hunga5a7fc92023-06-23 19:27:19 -07002629binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002630 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002631 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002632 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002633 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002634}
2635
Andy Hunga5a7fc92023-06-23 19:27:19 -07002636binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002637 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002638 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002639}
2640
Andy Hunga5a7fc92023-06-23 19:27:19 -07002641void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002642 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002643 mRecordTrack->stop();
2644}
2645
Andy Hunga5a7fc92023-06-23 19:27:19 -07002646binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002647 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002648 ALOGV("%s()", __func__);
Mikhail Naganovd5d9de72023-02-13 11:45:03 -08002649 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002650}
2651
Andy Hunga5a7fc92023-06-23 19:27:19 -07002652binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002653 int /*audio_microphone_direction_t*/ direction) {
2654 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002655 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002656 static_cast<audio_microphone_direction_t>(direction)));
2657}
2658
Andy Hunga5a7fc92023-06-23 19:27:19 -07002659binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002660 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002661 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002662}
2663
Andy Hunga5a7fc92023-06-23 19:27:19 -07002664binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002665 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2666 return binderStatusFromStatusT(
2667 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2668}
2669
Eric Laurent81784c32012-11-19 14:55:58 -08002670// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002671#undef LOG_TAG
2672#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002673
Andy Hung8d31fd22023-06-26 19:20:57 -07002674
Andy Hung99b1ba62023-07-14 11:00:08 -07002675/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07002676sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002677 const sp<Client>& client,
2678 const audio_attributes_t& attr,
2679 uint32_t sampleRate,
2680 audio_format_t format,
2681 audio_channel_mask_t channelMask,
2682 size_t frameCount,
2683 void* buffer,
2684 size_t bufferSize,
2685 audio_session_t sessionId,
2686 pid_t creatorPid,
2687 const AttributionSourceState& attributionSource,
2688 audio_input_flags_t flags,
2689 track_type type,
2690 audio_port_handle_t portId,
2691 int32_t startFrames)
2692{
2693 return sp<RecordTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07002694 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07002695 client,
2696 attr,
2697 sampleRate,
2698 format,
2699 channelMask,
2700 frameCount,
2701 buffer,
2702 bufferSize,
2703 sessionId,
2704 creatorPid,
2705 attributionSource,
2706 flags,
2707 type,
2708 portId,
2709 startFrames);
2710}
2711
Glenn Kasten05997e22014-03-13 15:08:33 -07002712// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung8d31fd22023-06-26 19:20:57 -07002713RecordTrack::RecordTrack(
Andy Hung87c693c2023-07-06 20:56:16 -07002714 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002715 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002716 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002717 uint32_t sampleRate,
2718 audio_format_t format,
2719 audio_channel_mask_t channelMask,
2720 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002721 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002722 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002723 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002724 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002725 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002726 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002727 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002728 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002729 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002730 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002731 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002732 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002733 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002734 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002735 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002736 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002737 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002738 type, portId,
2739 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002740 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002741 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002742 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002743 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002744 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002745 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002746{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002747 if (mCblk == NULL) {
2748 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002749 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002750
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002751 if (!isDirect()) {
2752 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung87c693c2023-07-06 20:56:16 -07002753 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002754 channelMask, format, sampleRate);
2755 // Check if the RecordBufferConverter construction was successful.
2756 // If not, don't continue with construction.
2757 //
2758 // NOTE: It would be extremely rare that the record track cannot be created
2759 // for the current device, but a pending or future device change would make
2760 // the record track configuration valid.
2761 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002762 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002763 return;
2764 }
Andy Hung97a893e2015-03-29 01:03:07 -07002765 }
2766
Andy Hung6ae58432016-02-16 18:32:24 -08002767 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002768 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002769
Andy Hung97a893e2015-03-29 01:03:07 -07002770 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002771
Eric Laurent05067782016-06-01 18:27:28 -07002772 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung87c693c2023-07-06 20:56:16 -07002773 ALOG_ASSERT(thread->fastTrackAvailable());
2774 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002775 } else {
2776 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002777 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002778 }
Andy Hung8946a282018-04-19 20:04:56 -07002779#ifdef TEE_SINK
2780 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2781 + "_" + std::to_string(mId)
2782 + "_R");
2783#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002784
2785 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002786 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002787}
2788
Andy Hung8d31fd22023-06-26 19:20:57 -07002789RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002790{
Andy Hung9d84af52018-09-12 18:03:44 -07002791 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002792 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002793 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002794}
2795
Andy Hung8d31fd22023-06-26 19:20:57 -07002796status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002797{
2798 status_t status = TrackBase::initCheck();
2799 if (status == NO_ERROR && mServerProxy == 0) {
2800 status = BAD_VALUE;
2801 }
2802 return status;
2803}
2804
Eric Laurent81784c32012-11-19 14:55:58 -08002805// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07002806status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002807{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002808 ServerProxy::Buffer buf;
2809 buf.mFrameCount = buffer->frameCount;
2810 status_t status = mServerProxy->obtainBuffer(&buf);
2811 buffer->frameCount = buf.mFrameCount;
2812 buffer->raw = buf.mRaw;
2813 if (buf.mFrameCount == 0) {
2814 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002815 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002816 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002817 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002818}
2819
Andy Hung8d31fd22023-06-26 19:20:57 -07002820status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002821 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002822{
Andy Hung87c693c2023-07-06 20:56:16 -07002823 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002824 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002825 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002826 return recordThread->start(this, event, triggerSession);
2827 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002828 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2829 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002830 }
2831}
2832
Andy Hung8d31fd22023-06-26 19:20:57 -07002833void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002834{
Andy Hung87c693c2023-07-06 20:56:16 -07002835 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002836 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07002837 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002838 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002839 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002840 }
2841 }
2842}
2843
Andy Hung8d31fd22023-06-26 19:20:57 -07002844void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002845{
Andy Hung8d31fd22023-06-26 19:20:57 -07002846 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002847 sp<RecordTrack> keep(this);
2848 {
Andy Hungce685402018-10-05 17:23:27 -07002849 track_state priorState = mState;
Andy Hung87c693c2023-07-06 20:56:16 -07002850 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002851 if (thread != 0) {
Andy Hungc5007f82023-08-29 14:26:09 -07002852 audio_utils::lock_guard _l(thread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07002853 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002854 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002855 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002856 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002857 }
Andy Hungce685402018-10-05 17:23:27 -07002858 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2859 }
2860 // APM portid/client management done outside of lock.
2861 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2862 if (isExternalTrack()) {
2863 switch (priorState) {
2864 case ACTIVE: // invalidated while still active
2865 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2866 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2867 AudioSystem::stopInput(mPortId);
2868 break;
2869
2870 case STARTING_1: // invalidated/start-aborted and startInput not successful
2871 case PAUSED: // OK, not active
2872 case IDLE: // OK, not active
2873 break;
2874
2875 case STOPPED: // unexpected (destroyed)
2876 default:
2877 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2878 }
2879 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002880 }
2881 }
2882}
2883
Andy Hung8d31fd22023-06-26 19:20:57 -07002884void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002885{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002886 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002887 // FIXME should use proxy, and needs work
2888 audio_track_cblk_t* cblk = mCblk;
2889 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2890 android_atomic_release_store(0x40000000, &cblk->mFutex);
2891 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002892 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002893}
2894
Eric Laurent81784c32012-11-19 14:55:58 -08002895
Andy Hung8d31fd22023-06-26 19:20:57 -07002896void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002897{
Eric Laurent973db022018-11-20 14:54:31 -08002898 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002899 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002900 " Server FrmCnt FrmRdy Sil%s\n",
2901 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002902}
2903
Andy Hung8d31fd22023-06-26 19:20:57 -07002904void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002905{
Eric Laurent973db022018-11-20 14:54:31 -08002906 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002907 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002908 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002909 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002910 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002911 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002912 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002913 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002914 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002915 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002916 mCblk->mFlags,
2917
Eric Laurent81784c32012-11-19 14:55:58 -08002918 mFormat,
2919 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002920 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002921 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002922
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002923 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002924 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002925 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002926 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002927 );
Andy Hung000adb52018-06-01 15:43:26 -07002928 if (isServerLatencySupported()) {
2929 double latencyMs;
2930 bool fromTrack;
2931 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2932 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2933 // or 'k' if estimated from kernel (usually for debugging).
2934 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2935 } else {
2936 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2937 }
2938 }
2939 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002940}
2941
Andy Hung93bb5732023-05-04 21:16:34 -07002942// This is invoked by SyncEvent callback.
Andy Hung8d31fd22023-06-26 19:20:57 -07002943void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002944 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002945{
Andy Hung93bb5732023-05-04 21:16:34 -07002946 size_t framesToDrop = 0;
Andy Hung87c693c2023-07-06 20:56:16 -07002947 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002948 if (threadBase != 0) {
2949 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2950 // from audio HAL
Andy Hung87c693c2023-07-06 20:56:16 -07002951 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002952 }
Andy Hung93bb5732023-05-04 21:16:34 -07002953
2954 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002955}
2956
Andy Hung8d31fd22023-06-26 19:20:57 -07002957void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002958{
Andy Hung93bb5732023-05-04 21:16:34 -07002959 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002960}
2961
Andy Hung8d31fd22023-06-26 19:20:57 -07002962void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002963 int64_t trackFramesReleased, int64_t sourceFramesRead,
2964 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2965{
Andy Hung30282562018-08-08 18:27:03 -07002966 // Make the kernel frametime available.
2967 const FrameTime ft{
2968 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2969 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2970 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2971 mKernelFrameTime.store(ft);
2972 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002973 // Stream is direct, return provided timestamp with no conversion
2974 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002975 return;
2976 }
2977
Andy Hung3f0c9022016-01-15 17:49:46 -08002978 ExtendedTimestamp local = timestamp;
2979
2980 // Convert HAL frames to server-side track frames at track sample rate.
2981 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2982 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2983 if (local.mTimeNs[i] != 0) {
2984 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2985 const int64_t relativeTrackFrames = relativeServerFrames
2986 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2987 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2988 }
2989 }
Andy Hung6ae58432016-02-16 18:32:24 -08002990 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002991
2992 // Compute latency info.
2993 const bool useTrackTimestamp = true; // use track unless debugging.
2994 const double latencyMs = - (useTrackTimestamp
2995 ? local.getOutputServerLatencyMs(sampleRate())
2996 : timestamp.getOutputServerLatencyMs(halSampleRate));
2997
2998 mServerLatencyFromTrack.store(useTrackTimestamp);
2999 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003000}
Eric Laurent83b88082014-06-20 18:31:16 -07003001
Andy Hung8d31fd22023-06-26 19:20:57 -07003002status_t RecordTrack::getActiveMicrophones(
Andy Hungd29af632023-06-23 19:27:19 -07003003 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003004{
Andy Hung87c693c2023-07-06 20:56:16 -07003005 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003006 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003007 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003008 return recordThread->getActiveMicrophones(activeMicrophones);
3009 } else {
3010 return BAD_VALUE;
3011 }
3012}
3013
Andy Hung8d31fd22023-06-26 19:20:57 -07003014status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003015 audio_microphone_direction_t direction) {
Andy Hung87c693c2023-07-06 20:56:16 -07003016 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003017 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003018 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003019 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003020 } else {
3021 return BAD_VALUE;
3022 }
3023}
3024
Andy Hung8d31fd22023-06-26 19:20:57 -07003025status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung87c693c2023-07-06 20:56:16 -07003026 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003027 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003028 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003029 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003030 } else {
3031 return BAD_VALUE;
3032 }
3033}
3034
Andy Hung8d31fd22023-06-26 19:20:57 -07003035status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003036 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3037
3038 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3039 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3040 if (callingUid != mUid || callingPid != mCreatorPid) {
3041 return PERMISSION_DENIED;
3042 }
3043
Svet Ganov33761132021-05-13 22:51:08 +00003044 AttributionSourceState attributionSource{};
3045 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3046 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3047 attributionSource.token = sp<BBinder>::make();
3048 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003049 return PERMISSION_DENIED;
3050 }
3051
Andy Hung87c693c2023-07-06 20:56:16 -07003052 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003053 if (thread != 0) {
Andy Hung87c693c2023-07-06 20:56:16 -07003054 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003055 status_t status = recordThread->shareAudioHistory(
3056 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3057 if (status == NO_ERROR) {
3058 mSharedAudioPackageName = sharedAudioPackageName;
3059 }
3060 return status;
3061 } else {
3062 return BAD_VALUE;
3063 }
3064}
3065
Andy Hung8d31fd22023-06-26 19:20:57 -07003066void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003067{
3068
3069 // Do not forward PatchRecord metadata with unspecified audio source
3070 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3071 return;
3072 }
3073
3074 // No track is invalid as this is called after prepareTrack_l in the same critical section
3075 record_track_metadata_v7_t metadata;
3076 metadata.base = {
3077 .source = mAttr.source,
3078 .gain = 1, // capture tracks do not have volumes
3079 };
3080 metadata.channel_mask = mChannelMask;
3081 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3082
3083 *backInserter++ = metadata;
3084}
Eric Laurentec376dc2021-04-08 20:41:22 +02003085
Andy Hung9d84af52018-09-12 18:03:44 -07003086// ----------------------------------------------------------------------------
3087#undef LOG_TAG
3088#define LOG_TAG "AF::PatchRecord"
3089
Andy Hung8d31fd22023-06-26 19:20:57 -07003090/* static */
3091sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung87c693c2023-07-06 20:56:16 -07003092 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003093 uint32_t sampleRate,
3094 audio_channel_mask_t channelMask,
3095 audio_format_t format,
3096 size_t frameCount,
3097 void *buffer,
3098 size_t bufferSize,
3099 audio_input_flags_t flags,
3100 const Timeout& timeout,
3101 audio_source_t source)
3102{
3103 return sp<PatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003104 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003105 sampleRate,
3106 channelMask,
3107 format,
3108 frameCount,
3109 buffer,
3110 bufferSize,
3111 flags,
3112 timeout,
3113 source);
3114}
3115
Andy Hung87c693c2023-07-06 20:56:16 -07003116PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003117 uint32_t sampleRate,
3118 audio_channel_mask_t channelMask,
3119 audio_format_t format,
3120 size_t frameCount,
3121 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003122 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003123 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003124 const Timeout& timeout,
3125 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003126 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003127 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003128 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003129 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003130 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003131 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3132 : nullptr,
Andy Hung4fd69012023-07-14 16:57:01 -07003133 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003134{
Andy Hung9d84af52018-09-12 18:03:44 -07003135 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3136 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003137 (int)mPeerTimeout.tv_sec,
3138 (int)(mPeerTimeout.tv_nsec / 1000000));
3139}
3140
Andy Hung8d31fd22023-06-26 19:20:57 -07003141PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003142{
Andy Hungabfab202019-03-07 19:45:54 -08003143 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003144}
3145
Mikhail Naganov8296c252019-09-25 14:59:54 -07003146static size_t writeFramesHelper(
3147 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3148{
3149 AudioBufferProvider::Buffer patchBuffer;
3150 patchBuffer.frameCount = frameCount;
3151 auto status = dest->getNextBuffer(&patchBuffer);
3152 if (status != NO_ERROR) {
3153 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3154 __func__, status, strerror(-status));
3155 return 0;
3156 }
3157 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3158 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3159 size_t framesWritten = patchBuffer.frameCount;
3160 dest->releaseBuffer(&patchBuffer);
3161 return framesWritten;
3162}
3163
3164// static
Andy Hung8d31fd22023-06-26 19:20:57 -07003165size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003166 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3167{
3168 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3169 // On buffer wrap, the buffer frame count will be less than requested,
3170 // when this happens a second buffer needs to be used to write the leftover audio
3171 const size_t framesLeft = frameCount - framesWritten;
3172 if (framesWritten != 0 && framesLeft != 0) {
3173 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3174 framesLeft, frameSize);
3175 }
3176 return framesWritten;
3177}
3178
Eric Laurent83b88082014-06-20 18:31:16 -07003179// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003180status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003181 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003182{
Andy Hung9d84af52018-09-12 18:03:44 -07003183 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003184 Proxy::Buffer buf;
3185 buf.mFrameCount = buffer->frameCount;
3186 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3187 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003188 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003189 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003190 if (ATRACE_ENABLED()) {
3191 std::string traceName("PRnObt");
3192 traceName += std::to_string(id());
3193 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3194 }
Eric Laurent83b88082014-06-20 18:31:16 -07003195 if (buf.mFrameCount == 0) {
3196 return WOULD_BLOCK;
3197 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003198 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003199 return status;
3200}
3201
Andy Hung8d31fd22023-06-26 19:20:57 -07003202void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003203{
Andy Hung9d84af52018-09-12 18:03:44 -07003204 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003205 Proxy::Buffer buf;
3206 buf.mFrameCount = buffer->frameCount;
3207 buf.mRaw = buffer->raw;
3208 mPeerProxy->releaseBuffer(&buf);
3209 TrackBase::releaseBuffer(buffer);
3210}
3211
Andy Hung8d31fd22023-06-26 19:20:57 -07003212status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003213 const struct timespec *timeOut)
3214{
3215 return mProxy->obtainBuffer(buffer, timeOut);
3216}
3217
Andy Hung8d31fd22023-06-26 19:20:57 -07003218void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003219{
3220 mProxy->releaseBuffer(buffer);
3221}
3222
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003223#undef LOG_TAG
3224#define LOG_TAG "AF::PthrPatchRecord"
3225
3226static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3227{
3228 void *ptr = nullptr;
3229 (void)posix_memalign(&ptr, alignment, size);
Andy Hung920f6572022-10-06 12:09:49 -07003230 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003231}
3232
Andy Hung8d31fd22023-06-26 19:20:57 -07003233/* static */
3234sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung87c693c2023-07-06 20:56:16 -07003235 IAfRecordThread* recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003236 uint32_t sampleRate,
3237 audio_channel_mask_t channelMask,
3238 audio_format_t format,
3239 size_t frameCount,
3240 audio_input_flags_t flags,
3241 audio_source_t source)
3242{
3243 return sp<PassthruPatchRecord>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003244 recordThread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003245 sampleRate,
3246 channelMask,
3247 format,
3248 frameCount,
3249 flags,
3250 source);
3251}
3252
3253PassthruPatchRecord::PassthruPatchRecord(
Andy Hung87c693c2023-07-06 20:56:16 -07003254 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003255 uint32_t sampleRate,
3256 audio_channel_mask_t channelMask,
3257 audio_format_t format,
3258 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003259 audio_input_flags_t flags,
3260 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003261 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003262 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003263 mPatchRecordAudioBufferProvider(*this),
3264 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3265 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3266{
3267 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3268}
3269
Andy Hung8d31fd22023-06-26 19:20:57 -07003270sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung87c693c2023-07-06 20:56:16 -07003271 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003272{
3273 *thread = mThread.promote();
3274 if (!*thread) return nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003275 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hungc5007f82023-08-29 14:26:09 -07003276 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung87c693c2023-07-06 20:56:16 -07003277 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003278}
3279
3280// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung8d31fd22023-06-26 19:20:57 -07003281status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003282 Proxy::Buffer* buffer, const struct timespec* timeOut)
3283{
3284 if (mUnconsumedFrames) {
3285 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3286 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3287 return PatchRecord::obtainBuffer(buffer, timeOut);
3288 }
3289
3290 // Otherwise, execute a read from HAL and write into the buffer.
3291 nsecs_t startTimeNs = 0;
3292 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3293 // Will need to correct timeOut by elapsed time.
3294 startTimeNs = systemTime();
3295 }
3296 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3297 buffer->mFrameCount = 0;
3298 buffer->mRaw = nullptr;
Andy Hung87c693c2023-07-06 20:56:16 -07003299 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003300 sp<StreamInHalInterface> stream = obtainStream(&thread);
3301 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3302
3303 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003304 size_t bytesRead = 0;
3305 {
3306 ATRACE_NAME("read");
3307 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3308 if (result != NO_ERROR) goto stream_error;
3309 if (bytesRead == 0) return NO_ERROR;
3310 }
3311
3312 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003313 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003314 mReadBytes += bytesRead;
3315 mReadError = NO_ERROR;
3316 }
3317 mReadCV.notify_one();
3318 // writeFrames handles wraparound and should write all the provided frames.
3319 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3320 buffer->mFrameCount = writeFrames(
3321 &mPatchRecordAudioBufferProvider,
3322 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3323 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3324 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3325 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003326 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003327 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003328 // Correct the timeout by elapsed time.
3329 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003330 if (newTimeOutNs < 0) newTimeOutNs = 0;
3331 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3332 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003333 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003334 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003335 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003336
3337stream_error:
3338 stream->standby();
3339 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003340 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003341 mReadError = result;
3342 }
3343 mReadCV.notify_one();
3344 return result;
3345}
3346
Andy Hung8d31fd22023-06-26 19:20:57 -07003347void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003348{
3349 if (buffer->mFrameCount <= mUnconsumedFrames) {
3350 mUnconsumedFrames -= buffer->mFrameCount;
3351 } else {
3352 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3353 buffer->mFrameCount, mUnconsumedFrames);
3354 mUnconsumedFrames = 0;
3355 }
3356 PatchRecord::releaseBuffer(buffer);
3357}
3358
3359// AudioBufferProvider and Source methods are called on RecordThread
3360// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3361// and 'releaseBuffer' are stubbed out and ignore their input.
3362// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3363// until we copy it.
Andy Hung8d31fd22023-06-26 19:20:57 -07003364status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003365 void* buffer, size_t bytes, size_t* read)
3366{
3367 bytes = std::min(bytes, mFrameCount * mFrameSize);
3368 {
Andy Hung0169fbc2023-08-28 19:12:14 -07003369 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003370 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3371 if (mReadError != NO_ERROR) {
3372 mLastReadFrames = 0;
3373 return mReadError;
3374 }
3375 *read = std::min(bytes, mReadBytes);
3376 mReadBytes -= *read;
3377 }
3378 mLastReadFrames = *read / mFrameSize;
3379 memset(buffer, 0, *read);
3380 return 0;
3381}
3382
Andy Hung8d31fd22023-06-26 19:20:57 -07003383status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003384 int64_t* frames, int64_t* time)
3385{
Andy Hung87c693c2023-07-06 20:56:16 -07003386 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003387 sp<StreamInHalInterface> stream = obtainStream(&thread);
3388 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3389}
3390
Andy Hung8d31fd22023-06-26 19:20:57 -07003391status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003392{
3393 // RecordThread issues 'standby' command in two major cases:
3394 // 1. Error on read--this case is handled in 'obtainBuffer'.
3395 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3396 // output, this can only happen when the software patch
3397 // is being torn down. In this case, the RecordThread
3398 // will terminate and close the HAL stream.
3399 return 0;
3400}
3401
3402// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung8d31fd22023-06-26 19:20:57 -07003403status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003404 AudioBufferProvider::Buffer* buffer)
3405{
3406 buffer->frameCount = mLastReadFrames;
3407 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3408 return NO_ERROR;
3409}
3410
Andy Hung8d31fd22023-06-26 19:20:57 -07003411void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003412 AudioBufferProvider::Buffer* buffer)
3413{
3414 buffer->frameCount = 0;
3415 buffer->raw = nullptr;
3416}
3417
Andy Hung9d84af52018-09-12 18:03:44 -07003418// ----------------------------------------------------------------------------
3419#undef LOG_TAG
3420#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003421
Andy Hung8d31fd22023-06-26 19:20:57 -07003422/* static */
Andy Hung87c693c2023-07-06 20:56:16 -07003423sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003424 const audio_attributes_t& attr,
3425 uint32_t sampleRate,
3426 audio_format_t format,
3427 audio_channel_mask_t channelMask,
3428 audio_session_t sessionId,
3429 bool isOut,
3430 const android::content::AttributionSourceState& attributionSource,
3431 pid_t creatorPid,
3432 audio_port_handle_t portId)
3433{
3434 return sp<MmapTrack>::make(
Andy Hung87c693c2023-07-06 20:56:16 -07003435 thread,
Andy Hung8d31fd22023-06-26 19:20:57 -07003436 attr,
3437 sampleRate,
3438 format,
3439 channelMask,
3440 sessionId,
3441 isOut,
3442 attributionSource,
3443 creatorPid,
3444 portId);
3445}
3446
Andy Hung87c693c2023-07-06 20:56:16 -07003447MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003448 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003449 uint32_t sampleRate,
3450 audio_format_t format,
3451 audio_channel_mask_t channelMask,
3452 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003453 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003454 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003455 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003456 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003457 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003458 channelMask, (size_t)0 /* frameCount */,
3459 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003460 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003461 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003462 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003463 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003464 TYPE_DEFAULT, portId,
3465 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003466 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003467 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003468{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003469 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003470 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003471}
3472
Andy Hung8d31fd22023-06-26 19:20:57 -07003473MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003474{
3475}
3476
Andy Hung8d31fd22023-06-26 19:20:57 -07003477status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003478{
3479 return NO_ERROR;
3480}
3481
Andy Hung8d31fd22023-06-26 19:20:57 -07003482status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003483 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003484{
3485 return NO_ERROR;
3486}
3487
Andy Hung8d31fd22023-06-26 19:20:57 -07003488void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003489{
3490}
3491
3492// AudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003493status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003494{
3495 buffer->frameCount = 0;
3496 buffer->raw = nullptr;
3497 return INVALID_OPERATION;
3498}
3499
3500// ExtendedAudioBufferProvider interface
Andy Hung8d31fd22023-06-26 19:20:57 -07003501size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003502 return 0;
3503}
3504
Andy Hung8d31fd22023-06-26 19:20:57 -07003505int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003506{
3507 return 0;
3508}
3509
Andy Hung8d31fd22023-06-26 19:20:57 -07003510void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003511{
3512}
3513
Andy Hung8d31fd22023-06-26 19:20:57 -07003514void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003515{
3516 if (mMuteState == muteState) {
3517 // mute state did not change, do nothing
3518 return;
3519 }
3520
3521 status_t result = UNKNOWN_ERROR;
3522 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3523 if (mMuteEventExtras == nullptr) {
3524 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3525 }
3526 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3527 static_cast<int>(muteState));
3528
3529 result = audioManager->portEvent(mPortId,
3530 PLAYER_UPDATE_MUTED,
3531 mMuteEventExtras);
3532 }
3533
3534 if (result == OK) {
3535 mMuteState = muteState;
3536 } else {
3537 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3538 __func__,
3539 id(),
3540 mPortId,
3541 result);
3542 }
3543}
3544
Andy Hung8d31fd22023-06-26 19:20:57 -07003545void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003546{
Eric Laurent973db022018-11-20 14:54:31 -08003547 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003548 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003549}
3550
Andy Hung8d31fd22023-06-26 19:20:57 -07003551void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003552{
Eric Laurent973db022018-11-20 14:54:31 -08003553 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003554 mPid,
3555 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003556 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003557 mFormat,
3558 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003559 mSampleRate,
3560 mAttr.flags);
3561 if (isOut()) {
3562 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3563 } else {
3564 result.appendFormat("%6x", mAttr.source);
3565 }
3566 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003567}
3568
Glenn Kasten63238ef2015-03-02 15:50:29 -08003569} // namespace android