blob: 4fe5b840ac82127128c597431783b4b070d19a7a [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Eric Laurent81784c32012-11-19 14:55:58 -080018#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070020#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080021
Andy Hungce240472023-07-19 11:40:07 -070022#include "MmapTracks.h"
23#include "PlaybackTracks.h"
24#include "RecordTracks.h"
25
26#include "Client.h"
27#include "IAfEffect.h"
28#include "IAfThread.h"
29#include "ResamplerBufferProvider.h"
30
31#include <audio_utils/minifloat.h>
32#include <media/AudioValidator.h>
33#include <media/RecordBufferConverter.h>
34#include <media/nbaio/Pipe.h>
35#include <media/nbaio/PipeReader.h>
36#include <mediautils/ServiceUtilities.h>
37#include <mediautils/SharedMemoryAllocator.h>
38#include <private/media/AudioTrackShared.h>
Eric Laurent81784c32012-11-19 14:55:58 -080039#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070040#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080041
Andy Hungce240472023-07-19 11:40:07 -070042#include <linux/futex.h>
43#include <math.h>
44#include <sys/syscall.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080045
Eric Laurent81784c32012-11-19 14:55:58 -080046// ----------------------------------------------------------------------------
47
48// Note: the following macro is used for extremely verbose logging message. In
49// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
50// 0; but one side effect of this is to turn all LOGV's as well. Some messages
51// are so verbose that we want to suppress them even when we have ALOG_ASSERT
52// turned on. Do not uncomment the #def below unless you really know what you
53// are doing and want to see all of the extremely verbose messages.
54//#define VERY_VERY_VERBOSE_LOGGING
55#ifdef VERY_VERY_VERBOSE_LOGGING
56#define ALOGVV ALOGV
57#else
58#define ALOGVV(a...) do { } while(0)
59#endif
60
Kuowei Lid4adbdb2020-08-13 14:44:25 +080061// TODO: Remove when this is put into AidlConversionUtil.h
62#define VALUE_OR_RETURN_BINDER_STATUS(x) \
63 ({ \
64 auto _tmp = (x); \
65 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
66 std::move(_tmp.value()); \
67 })
68
Eric Laurent81784c32012-11-19 14:55:58 -080069namespace android {
70
Kuowei Lid4adbdb2020-08-13 14:44:25 +080071using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080072using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000073using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070074using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080075// ----------------------------------------------------------------------------
76// TrackBase
77// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070078#undef LOG_TAG
79#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080080
Glenn Kastenda6ef132013-01-10 12:31:01 -080081static volatile int32_t nextTrackId = 55;
82
Eric Laurent81784c32012-11-19 14:55:58 -080083// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -070084TrackBase::TrackBase(
Andy Hung44f27182023-07-06 20:56:16 -070085 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080086 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070087 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080088 uint32_t sampleRate,
89 audio_format_t format,
90 audio_channel_mask_t channelMask,
91 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070092 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070093 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080094 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070095 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080096 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070097 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070098 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080099 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800100 audio_port_handle_t portId,
101 std::string metricsId)
Andy Hung02a6c4e2023-06-23 19:27:19 -0700102 :
Eric Laurent81784c32012-11-19 14:55:58 -0800103 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700104 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800105 mClient(client),
106 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700107 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800108 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700109 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800110 mSampleRate(sampleRate),
111 mFormat(format),
112 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700113 mChannelCount(isOut ?
114 audio_channel_count_from_out_mask(channelMask) :
115 audio_channel_count_from_in_mask(channelMask)),
Dean Wheatleyd883e302023-10-20 06:11:43 +1100116 mFrameSize(audio_bytes_per_frame(mChannelCount, format)),
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung3ff4b552023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung3ff4b552023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung2ac52f12023-08-28 18:36:53 -0700279 audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung3ff4b552023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung3ff4b552023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung3ff4b552023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung837229a2023-07-14 16:57:01 -0700318 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
Andy Hung837229a2023-07-14 16:57:01 -0700325 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
326 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung3ff4b552023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hungaaa18282023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hungaaa18282023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hungaaa18282023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hungaaa18282023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hung02a6c4e2023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hung225aef62022-12-06 16:33:20 -0800391 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800392}
393
Andy Hungaaa18282023-06-23 19:27:19 -0700394TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800395 // just stop the track on deletion, associated resources
396 // will be freed from the main thread once all pending buffers have
397 // been played. Unless it's not in the active track list, in which
398 // case we free everything now...
399 mTrack->destroy();
400}
401
Andy Hungaaa18282023-06-23 19:27:19 -0700402Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800403 std::optional<media::SharedFileRegion>* _aidl_return) {
404 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
405 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800406}
407
Andy Hungaaa18282023-06-23 19:27:19 -0700408Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800409 *_aidl_return = mTrack->start();
410 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800411}
412
Andy Hungaaa18282023-06-23 19:27:19 -0700413Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800414 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800415 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800416}
417
Andy Hungaaa18282023-06-23 19:27:19 -0700418Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800419 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800420 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800421}
422
Andy Hungaaa18282023-06-23 19:27:19 -0700423Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800424 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800425 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800426}
427
Andy Hungaaa18282023-06-23 19:27:19 -0700428Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800429 int32_t* _aidl_return) {
430 *_aidl_return = mTrack->attachAuxEffect(effectId);
431 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800432}
433
Andy Hungaaa18282023-06-23 19:27:19 -0700434Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800435 int32_t* _aidl_return) {
436 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
437 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700438}
439
Andy Hungaaa18282023-06-23 19:27:19 -0700440Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800441 int32_t* _aidl_return) {
442 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
443 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800444}
445
Andy Hungaaa18282023-06-23 19:27:19 -0700446Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800447 int32_t* _aidl_return) {
448 AudioTimestamp legacy;
449 *_aidl_return = mTrack->getTimestamp(legacy);
450 if (*_aidl_return != OK) {
451 return Status::ok();
452 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000453
454 // restrict position modulo INT_MAX to avoid integer sanitization abort
455 legacy.mPosition &= INT_MAX;
456
Andy Hung973638a2020-12-08 20:47:45 -0800457 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800458 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800459}
460
Andy Hungaaa18282023-06-23 19:27:19 -0700461Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800462 mTrack->signal();
463 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800464}
465
Andy Hungaaa18282023-06-23 19:27:19 -0700466Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800467 const media::VolumeShaperConfiguration& configuration,
468 const media::VolumeShaperOperation& operation,
469 int32_t* _aidl_return) {
470 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
471 *_aidl_return = conf->readFromParcelable(configuration);
472 if (*_aidl_return != OK) {
473 return Status::ok();
474 }
475
476 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
477 *_aidl_return = op->readFromParcelable(operation);
478 if (*_aidl_return != OK) {
479 return Status::ok();
480 }
481
482 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
483 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700484}
485
Andy Hungaaa18282023-06-23 19:27:19 -0700486Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800487 int32_t id,
488 std::optional<media::VolumeShaperState>* _aidl_return) {
489 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
490 if (legacy == nullptr) {
491 _aidl_return->reset();
492 return Status::ok();
493 }
494 media::VolumeShaperState aidl;
495 legacy->writeToParcelable(&aidl);
496 *_aidl_return = aidl;
497 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800498}
499
Andy Hungaaa18282023-06-23 19:27:19 -0700500Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000501 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800502{
503 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
504 const status_t status = mTrack->getDualMonoMode(&mode)
505 ?: AudioValidator::validateDualMonoMode(mode);
506 if (status == OK) {
507 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
508 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
509 }
510 return binderStatusFromStatusT(status);
511}
512
Andy Hungaaa18282023-06-23 19:27:19 -0700513Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000514 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800515{
516 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
517 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
518 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
519 ?: mTrack->setDualMonoMode(localMonoMode));
520}
521
Andy Hungaaa18282023-06-23 19:27:19 -0700522Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800523{
524 float leveldB = -std::numeric_limits<float>::infinity();
525 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
526 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
527 if (status == OK) *_aidl_return = leveldB;
528 return binderStatusFromStatusT(status);
529}
530
Andy Hungaaa18282023-06-23 19:27:19 -0700531Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800532{
533 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
534 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
535}
536
Andy Hungaaa18282023-06-23 19:27:19 -0700537Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000538 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800539{
540 audio_playback_rate_t localPlaybackRate{};
541 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
542 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
543 if (status == NO_ERROR) {
544 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
545 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
546 }
547 return binderStatusFromStatusT(status);
548}
549
Andy Hungaaa18282023-06-23 19:27:19 -0700550Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000551 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800552{
553 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
554 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
555 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
556 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
557}
558
Eric Laurent81784c32012-11-19 14:55:58 -0800559// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800560// AppOp for audio playback
561// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700562
563// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700564sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung44f27182023-07-06 20:56:16 -0700565 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000566 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700567 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800568{
Vlad Popa103be862023-07-10 20:27:41 -0700569 Vector<String16> packages;
570 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000571 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700572 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700573 if (packages.isEmpty()) {
574 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
575 id,
576 attr.usage,
577 uid);
578 return nullptr;
579 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800580 }
581 // stream type has been filtered by audio policy to indicate whether it can be muted
582 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700583 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700584 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800585 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700586 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
587 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
588 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
589 id, attr.flags);
590 return nullptr;
591 }
Vlad Popa103be862023-07-10 20:27:41 -0700592 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700593}
594
Andy Hung44f27182023-07-06 20:56:16 -0700595OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
596 const AttributionSourceState& attributionSource,
597 audio_usage_t usage, int id, uid_t uid)
598 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa103be862023-07-10 20:27:41 -0700599 mHasOpPlayAudio(true),
600 mAttributionSource(attributionSource),
601 mUsage((int32_t)usage),
602 mId(id),
603 mUid(uid),
604 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
605 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800606
Andy Hung3ff4b552023-06-26 19:20:57 -0700607OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800608{
609 if (mOpCallback != 0) {
610 mAppOpsManager.stopWatchingMode(mOpCallback);
611 }
612 mOpCallback.clear();
613}
614
Andy Hung3ff4b552023-06-26 19:20:57 -0700615void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700616{
Vlad Popad2152122023-08-02 18:36:04 -0700617 // make sure not to broadcast the initial state since it is not needed and could
618 // cause a deadlock since this method can be called with the mThread->mLock held
619 checkPlayAudioForUsage(/*doBroadcast=*/false);
Svet Ganov33761132021-05-13 22:51:08 +0000620 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700621 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700622 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Vlad Popa103be862023-07-10 20:27:41 -0700623 mPackageName, mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700624 }
625}
626
Andy Hung3ff4b552023-06-26 19:20:57 -0700627bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800628 return mHasOpPlayAudio.load();
629}
630
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700631// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800632// - not called from constructor due to check on UID,
633// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung3ff4b552023-06-26 19:20:57 -0700634void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800635{
Vlad Popa103be862023-07-10 20:27:41 -0700636 const bool hasAppOps = mAttributionSource.packageName.has_value()
637 && mAppOpsManager.checkAudioOpNoThrow(
638 AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
639 AppOpsManager::MODE_ALLOWED;
640
641 bool shouldChange = !hasAppOps; // check if we need to update.
642 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
643 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
Vlad Popad2152122023-08-02 18:36:04 -0700644 if (doBroadcast) {
645 auto thread = mThread.promote();
Andy Hung71742ab2023-07-07 13:47:37 -0700646 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popad2152122023-08-02 18:36:04 -0700647 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87e82412023-08-29 14:26:09 -0700648 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad2152122023-08-02 18:36:04 -0700649 thread->broadcast_l();
650 }
Vlad Popa103be862023-07-10 20:27:41 -0700651 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800652 }
653}
654
Andy Hung3ff4b552023-06-26 19:20:57 -0700655OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800656 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
657{ }
658
Andy Hung3ff4b552023-06-26 19:20:57 -0700659void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800660 const String16& packageName) {
661 // we only have uid, so we need to check all package names anyway
662 UNUSED(packageName);
663 if (op != AppOpsManager::OP_PLAY_AUDIO) {
664 return;
665 }
666 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
667 if (monitor != NULL) {
Vlad Popad2152122023-08-02 18:36:04 -0700668 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800669 }
670}
671
Eric Laurent9066ad32019-05-20 14:40:10 -0700672// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700673void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700674 uid_t uid, Vector<String16>& packages)
675{
676 PermissionController permissionController;
677 permissionController.getPackagesForUid(uid, packages);
678}
679
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800680// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700681#undef LOG_TAG
682#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800683
Andy Hung3ff4b552023-06-26 19:20:57 -0700684/* static */
Andy Hung44f27182023-07-06 20:56:16 -0700685sp<IAfTrack> IAfTrack::create(
686 IAfPlaybackThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700687 const sp<Client>& client,
688 audio_stream_type_t streamType,
689 const audio_attributes_t& attr,
690 uint32_t sampleRate,
691 audio_format_t format,
692 audio_channel_mask_t channelMask,
693 size_t frameCount,
694 void *buffer,
695 size_t bufferSize,
696 const sp<IMemory>& sharedBuffer,
697 audio_session_t sessionId,
698 pid_t creatorPid,
699 const AttributionSourceState& attributionSource,
700 audio_output_flags_t flags,
701 track_type type,
702 audio_port_handle_t portId,
703 /** default behaviour is to start when there are as many frames
704 * ready as possible (aka. Buffer is full). */
705 size_t frameCountToBeReady,
706 float speed,
707 bool isSpatialized,
708 bool isBitPerfect) {
Andy Hung44f27182023-07-06 20:56:16 -0700709 return sp<Track>::make(thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700710 client,
711 streamType,
712 attr,
713 sampleRate,
714 format,
715 channelMask,
716 frameCount,
717 buffer,
718 bufferSize,
719 sharedBuffer,
720 sessionId,
721 creatorPid,
722 attributionSource,
723 flags,
724 type,
725 portId,
726 frameCountToBeReady,
727 speed,
728 isSpatialized,
729 isBitPerfect);
730}
731
Eric Laurent81784c32012-11-19 14:55:58 -0800732// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -0700733Track::Track(
Andy Hung44f27182023-07-06 20:56:16 -0700734 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800735 const sp<Client>& client,
736 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700737 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800738 uint32_t sampleRate,
739 audio_format_t format,
740 audio_channel_mask_t channelMask,
741 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700742 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700743 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800744 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800745 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700746 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000747 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700748 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800749 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100750 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000751 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200752 float speed,
jiabinc658e452022-10-21 20:52:21 +0000753 bool isSpatialized,
754 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700755 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700756 // TODO: Using unsecurePointer() has some associated security pitfalls
757 // (see declaration for details).
758 // Either document why it is safe in this case or address the
759 // issue (e.g. by copying).
760 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700761 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700762 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000763 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700764 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800765 type,
766 portId,
767 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung3ff4b552023-06-26 19:20:57 -0700768 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800769 // mRetryCount initialized later when needed
770 mSharedBuffer(sharedBuffer),
771 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700772 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800773 mAuxBuffer(NULL),
774 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700775 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700776 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa103be862023-07-10 20:27:41 -0700777 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700778 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700779 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800780 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800781 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700782 /* The track might not play immediately after being active, similarly as if its volume was 0.
783 * When the track starts playing, its volume will be computed. */
784 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800785 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700786 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000787 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200788 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000789 mIsSpatialized(isSpatialized),
790 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800791{
Eric Laurent83b88082014-06-20 18:31:16 -0700792 // client == 0 implies sharedBuffer == 0
793 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
794
Andy Hung9d84af52018-09-12 18:03:44 -0700795 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700796 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700797
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700798 if (mCblk == NULL) {
799 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800800 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700801
Svet Ganov33761132021-05-13 22:51:08 +0000802 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700803 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
804 ALOGE("%s(%d): no more tracks available", __func__, mId);
805 releaseCblk(); // this makes the track invalid.
806 return;
807 }
808
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700809 if (sharedBuffer == 0) {
810 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700811 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700812 } else {
813 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100814 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700815 }
816 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700817 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700818
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700819 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700820 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700821 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
822 // race with setSyncEvent(). However, if we call it, we cannot properly start
823 // static fast tracks (SoundPool) immediately after stopping.
824 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung44f27182023-07-06 20:56:16 -0700825 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
826 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700827 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700828 // FIXME This is too eager. We allocate a fast track index before the
829 // fast track becomes active. Since fast tracks are a scarce resource,
830 // this means we are potentially denying other more important fast tracks from
831 // being created. It would be better to allocate the index dynamically.
832 mFastIndex = i;
Andy Hung44f27182023-07-06 20:56:16 -0700833 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700834 }
Andy Hung8946a282018-04-19 20:04:56 -0700835
Dean Wheatley7b036912020-06-18 16:22:11 +1000836 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700837#ifdef TEE_SINK
838 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800839 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700840#endif
jiabin57303cc2018-12-18 15:45:57 -0800841
jiabineb3bda02020-06-30 14:07:03 -0700842 if (thread->supportsHapticPlayback()) {
843 // If the track is attached to haptic playback thread, it is potentially to have
844 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
845 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800846 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000847 std::string packageName = attributionSource.packageName.has_value() ?
848 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800849 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700850 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800851 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800852
853 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700854 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800855 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800856}
857
Andy Hung3ff4b552023-06-26 19:20:57 -0700858Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800859{
Andy Hung9d84af52018-09-12 18:03:44 -0700860 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700861
862 // The destructor would clear mSharedBuffer,
863 // but it will not push the decremented reference count,
864 // leaving the client's IMemory dangling indefinitely.
865 // This prevents that leak.
866 if (mSharedBuffer != 0) {
867 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700868 }
Eric Laurent81784c32012-11-19 14:55:58 -0800869}
870
Andy Hung3ff4b552023-06-26 19:20:57 -0700871status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700872{
873 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700874 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700875 status = NO_MEMORY;
876 }
877 return status;
878}
879
Andy Hung3ff4b552023-06-26 19:20:57 -0700880void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800881{
882 // NOTE: destroyTrack_l() can remove a strong reference to this Track
883 // by removing it from mTracks vector, so there is a risk that this Tracks's
884 // destructor is called. As the destructor needs to lock mLock,
885 // we must acquire a strong reference on this Track before locking mLock
886 // here so that the destructor is called only when exiting this function.
887 // On the other hand, as long as Track::destroy() is only called by
888 // TrackHandle destructor, the TrackHandle still holds a strong ref on
889 // this Track with its member mTrack.
890 sp<Track> keep(this);
891 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700892 bool wasActive = false;
Andy Hung44f27182023-07-06 20:56:16 -0700893 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800894 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -0700895 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -0700896 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700897 wasActive = playbackThread->destroyTrack_l(this);
jiabin6e506fc2023-06-27 18:22:35 +0000898 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Eric Laurentaaa44472014-09-12 17:41:50 -0700899 }
900 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700901 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800902 }
903 }
904}
905
Andy Hung3ff4b552023-06-26 19:20:57 -0700906void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800907{
Eric Laurent973db022018-11-20 14:54:31 -0800908 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700909 " Format Chn mask SRate "
910 "ST Usg CT "
911 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000912 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700913 "%s\n",
914 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800915}
916
Andy Hung3ff4b552023-06-26 19:20:57 -0700917void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800918{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700919 char trackType;
920 switch (mType) {
921 case TYPE_DEFAULT:
922 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700923 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700924 trackType = 'S'; // static
925 } else {
926 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800927 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700928 break;
929 case TYPE_PATCH:
930 trackType = 'P';
931 break;
932 default:
933 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800934 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700935
936 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700937 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700938 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700939 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700940 }
941
Eric Laurent81784c32012-11-19 14:55:58 -0800942 char nowInUnderrun;
943 switch (mObservedUnderruns.mBitFields.mMostRecent) {
944 case UNDERRUN_FULL:
945 nowInUnderrun = ' ';
946 break;
947 case UNDERRUN_PARTIAL:
948 nowInUnderrun = '<';
949 break;
950 case UNDERRUN_EMPTY:
951 nowInUnderrun = '*';
952 break;
953 default:
954 nowInUnderrun = '?';
955 break;
956 }
Andy Hungda540db2017-04-20 14:06:17 -0700957
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700958 char fillingStatus;
Andy Hung3ff4b552023-06-26 19:20:57 -0700959 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700960 case FS_INVALID:
961 fillingStatus = 'I';
962 break;
963 case FS_FILLING:
964 fillingStatus = 'f';
965 break;
966 case FS_FILLED:
967 fillingStatus = 'F';
968 break;
969 case FS_ACTIVE:
970 fillingStatus = 'A';
971 break;
972 default:
973 fillingStatus = '?';
974 break;
975 }
976
977 // clip framesReadySafe to max representation in dump
978 const size_t framesReadySafe =
979 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
980
981 // obtain volumes
982 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
983 const std::pair<float /* volume */, bool /* active */> vsVolume =
984 mVolumeHandler->getLastVolume();
985
986 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
987 // as it may be reduced by the application.
988 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
989 // Check whether the buffer size has been modified by the app.
990 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
991 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
992 ? 'e' /* error */ : ' ' /* identical */;
993
Eric Laurent973db022018-11-20 14:54:31 -0800994 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700995 "%08X %08X %6u "
996 "%2u %3x %2x "
997 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000998 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800999 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001000 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001001 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001002 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001003 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001004 mCblk->mFlags,
1005
Eric Laurent81784c32012-11-19 14:55:58 -08001006 mFormat,
1007 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001008 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001009
1010 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001011 mAttr.usage,
1012 mAttr.content_type,
1013
1014 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001015 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1016 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001017 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1018 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001019
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001020 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001021 bufferSizeInFrames,
1022 modifiedBufferChar,
1023 framesReadySafe,
1024 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001025 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001026 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001027 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1028 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001029 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001030
1031 if (isServerLatencySupported()) {
1032 double latencyMs;
1033 bool fromTrack;
1034 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1035 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1036 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1037 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001038 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001039 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001040 }
1041 }
1042 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001043}
1044
Andy Hung3ff4b552023-06-26 19:20:57 -07001045uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001046 return mAudioTrackServerProxy->getSampleRate();
1047}
1048
Eric Laurent81784c32012-11-19 14:55:58 -08001049// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001050status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001051{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001052 ServerProxy::Buffer buf;
1053 size_t desiredFrames = buffer->frameCount;
1054 buf.mFrameCount = desiredFrames;
1055 status_t status = mServerProxy->obtainBuffer(&buf);
1056 buffer->frameCount = buf.mFrameCount;
1057 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001058 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001059 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001060 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001061 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001062 } else {
1063 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001064 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001065 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001066}
1067
Andy Hung3ff4b552023-06-26 19:20:57 -07001068void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001069{
1070 interceptBuffer(*buffer);
1071 TrackBase::releaseBuffer(buffer);
1072}
1073
1074// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001075void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001076 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001077 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001078 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001079 if (frameCount == 0) {
1080 return; // No audio to intercept.
1081 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1082 // does not allow 0 frame size request contrary to getNextBuffer
1083 }
Jiabin Huang98b8d452024-01-04 18:42:55 +00001084 TeePatches teePatches;
1085 if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
1086 // Cache a copy of tee patches in case it is updated while using.
1087 teePatches = mTeePatches;
1088 mTeePatchesRWLock.unlock();
1089 }
1090 for (auto& teePatch : teePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001091 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001092 const size_t framesWritten = patchRecord->writeFrames(
1093 sourceBuffer.i8, frameCount, mFrameSize);
1094 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001095 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001096 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001097 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001098 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001099 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1100 using namespace std::chrono_literals;
1101 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001102 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Jiabin Huang98b8d452024-01-04 18:42:55 +00001103 spent.count(), teePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001104}
1105
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001106// ExtendedAudioBufferProvider interface
1107
Andy Hung27876c02014-09-09 18:07:55 -07001108// framesReady() may return an approximation of the number of frames if called
1109// from a different thread than the one calling Proxy->obtainBuffer() and
1110// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1111// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001112size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001113 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1114 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1115 // The remainder of the buffer is not drained.
1116 return 0;
1117 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001118 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001119}
1120
Andy Hung3ff4b552023-06-26 19:20:57 -07001121int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001122{
1123 return mAudioTrackServerProxy->framesReleased();
1124}
1125
Andy Hung3ff4b552023-06-26 19:20:57 -07001126void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001127{
1128 // This call comes from a FastTrack and should be kept lockless.
1129 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001130 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001131
Andy Hung818e7a32016-02-16 18:08:07 -08001132 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001133
1134 // Compute latency.
1135 // TODO: Consider whether the server latency may be passed in by FastMixer
1136 // as a constant for all active FastTracks.
1137 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1138 mServerLatencyFromTrack.store(true);
1139 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001140}
1141
Eric Laurent81784c32012-11-19 14:55:58 -08001142// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001143bool Track::isReady() const {
1144 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001145 return true;
1146 }
1147
Eric Laurent16498512014-03-17 17:22:08 -07001148 if (isStopping()) {
1149 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001150 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001151 }
Eric Laurent81784c32012-11-19 14:55:58 -08001152 return true;
1153 }
1154
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001155 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001156 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1157 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1158 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1159 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001160
1161 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1162 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1163 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001164 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001165 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001166 return true;
1167 }
1168 return false;
1169}
1170
Andy Hung3ff4b552023-06-26 19:20:57 -07001171status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001172 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001173{
1174 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001175 ALOGV("%s(%d): calling pid %d session %d",
1176 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001177
Andy Hung44f27182023-07-06 20:56:16 -07001178 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001179 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001180 if (isOffloaded()) {
Andy Hung2ac52f12023-08-28 18:36:53 -07001181 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hung94dfbb42023-09-06 19:41:47 -07001182 const bool nonOffloadableGlobalEffectEnabled =
1183 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hung87e82412023-08-29 14:26:09 -07001184 audio_utils::lock_guard _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001185 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung94dfbb42023-09-06 19:41:47 -07001186 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001187 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001188 invalidate();
1189 return PERMISSION_DENIED;
1190 }
1191 }
Andy Hung87e82412023-08-29 14:26:09 -07001192 audio_utils::lock_guard _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001193 track_state state = mState;
1194 // here the track could be either new, or restarted
1195 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001196
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001197 // initial state-stopping. next state-pausing.
1198 // What if resume is called ?
1199
Zhou Song1ed46a22020-08-17 15:36:56 +08001200 if (state == FLUSHED) {
1201 // avoid underrun glitches when starting after flush
1202 reset();
1203 }
1204
kuowei.li576f1362021-05-11 18:02:32 +08001205 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1206 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001207 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001208 if (mResumeToStopping) {
1209 // happened we need to resume to STOPPING_1
1210 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001211 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1212 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001213 } else {
1214 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001215 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1216 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001217 }
Eric Laurent81784c32012-11-19 14:55:58 -08001218 } else {
1219 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001220 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1221 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001222 }
1223
Andy Hung44f27182023-07-06 20:56:16 -07001224 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001225
1226 // states to reset position info for pcm tracks
1227 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001228 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1229 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001230
1231 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1232 // Start point of track -> sink frame map. If the HAL returns a
1233 // frame position smaller than the first written frame in
1234 // updateTrackFrameInfo, the timestamp can be interpolated
1235 // instead of using a larger value.
1236 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1237 playbackThread->framesWritten());
1238 }
Andy Hunge10393e2015-06-12 13:59:33 -07001239 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001240 if (isFastTrack()) {
1241 // refresh fast track underruns on start because that field is never cleared
1242 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1243 // after stop.
1244 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1245 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001246 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001247 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001248 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001249 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001250 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001251 mState = state;
1252 }
1253 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001254
Andy Hungb68f5eb2019-12-03 16:49:17 -08001255 // Audio timing metrics are computed a few mix cycles after starting.
1256 {
1257 mLogStartCountdown = LOG_START_COUNTDOWN;
1258 mLogStartTimeNs = systemTime();
1259 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001260 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1261 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001262 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001263 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001264
Andy Hung1d3556d2018-03-29 16:30:14 -07001265 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1266 // for streaming tracks, remove the buffer read stop limit.
1267 mAudioTrackServerProxy->start();
1268 }
1269
Eric Laurentbfb1b832013-01-07 09:53:42 -08001270 // track was already in the active list, not a problem
1271 if (status == ALREADY_EXISTS) {
1272 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001273 } else {
1274 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1275 // It is usually unsafe to access the server proxy from a binder thread.
1276 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1277 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1278 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001279 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001280 ServerProxy::Buffer buffer;
1281 buffer.mFrameCount = 1;
1282 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001283 }
jiabin6e506fc2023-06-27 18:22:35 +00001284 if (status == NO_ERROR) {
1285 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1286 }
Eric Laurent81784c32012-11-19 14:55:58 -08001287 } else {
1288 status = BAD_VALUE;
1289 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001290 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001291 // send format to AudioManager for playback activity monitoring
Andy Hung2cbc2722023-07-17 17:05:00 -07001292 const sp<IAudioManager> audioManager =
1293 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001294 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1295 std::unique_ptr<os::PersistableBundle> bundle =
1296 std::make_unique<os::PersistableBundle>();
1297 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1298 isSpatialized());
1299 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1300 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1301 status_t result = audioManager->portEvent(mPortId,
1302 PLAYER_UPDATE_FORMAT, bundle);
1303 if (result != OK) {
1304 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1305 __func__, mPortId, result);
1306 }
1307 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001308 }
Eric Laurent81784c32012-11-19 14:55:58 -08001309 return status;
1310}
1311
Andy Hung3ff4b552023-06-26 19:20:57 -07001312void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001313{
Andy Hungc0691382018-09-12 18:01:57 -07001314 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001315 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001316 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001317 audio_utils::lock_guard _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001318 track_state state = mState;
1319 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1320 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001321 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1322 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001323 reset();
1324 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001325 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001326 mState = STOPPED;
1327 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001328 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1329 // presentation is complete
1330 // For an offloaded track this starts a drain and state will
1331 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001332 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001333 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001334 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001335 }
Eric Laurent81784c32012-11-19 14:55:58 -08001336 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001337 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001338 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1339 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001340 }
jiabin6e506fc2023-06-27 18:22:35 +00001341 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001342 }
1343}
1344
Andy Hung3ff4b552023-06-26 19:20:57 -07001345void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001346{
Andy Hungc0691382018-09-12 18:01:57 -07001347 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001348 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001349 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001350 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001351 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001352 switch (mState) {
1353 case STOPPING_1:
1354 case STOPPING_2:
1355 if (!isOffloaded()) {
1356 /* nothing to do if track is not offloaded */
1357 break;
1358 }
1359
1360 // Offloaded track was draining, we need to carry on draining when resumed
1361 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001362 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001363 case ACTIVE:
1364 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001365 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001366 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1367 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001368 if (isOffloadedOrDirect()) {
1369 mPauseHwPending = true;
1370 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001371 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001372 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001373
Eric Laurentbfb1b832013-01-07 09:53:42 -08001374 default:
1375 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001376 }
jiabin6e506fc2023-06-27 18:22:35 +00001377 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1378 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001379 }
1380}
1381
Andy Hung3ff4b552023-06-26 19:20:57 -07001382void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001383{
Andy Hungc0691382018-09-12 18:01:57 -07001384 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001385 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001386 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001387 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001388 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001389
Phil Burk4bb650b2016-09-09 12:11:17 -07001390 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1391 // Otherwise the flush would not be done until the track is resumed.
1392 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001393 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001394 (void)mServerProxy->flushBufferIfNeeded();
1395 }
1396
Eric Laurentbfb1b832013-01-07 09:53:42 -08001397 if (isOffloaded()) {
1398 // If offloaded we allow flush during any state except terminated
1399 // and keep the track active to avoid problems if user is seeking
1400 // rapidly and underlying hardware has a significant delay handling
1401 // a pause
1402 if (isTerminated()) {
1403 return;
1404 }
1405
Andy Hung9d84af52018-09-12 18:03:44 -07001406 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001407 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001408
1409 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001410 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1411 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001412 mState = ACTIVE;
1413 }
1414
Haynes Mathew George7844f672014-01-15 12:32:55 -08001415 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001416 mResumeToStopping = false;
1417 } else {
1418 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1419 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1420 return;
1421 }
1422 // No point remaining in PAUSED state after a flush => go to
1423 // FLUSHED state
1424 mState = FLUSHED;
1425 // do not reset the track if it is still in the process of being stopped or paused.
1426 // this will be done by prepareTracks_l() when the track is stopped.
1427 // prepareTracks_l() will see mState == FLUSHED, then
1428 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001429 if (isDirect()) {
1430 mFlushHwPending = true;
1431 }
Andy Hung44f27182023-07-06 20:56:16 -07001432 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001433 reset();
1434 }
Eric Laurent81784c32012-11-19 14:55:58 -08001435 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001436 // Prevent flush being lost if the track is flushed and then resumed
1437 // before mixer thread can run. This is important when offloading
1438 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001439 playbackThread->broadcast_l();
jiabin6e506fc2023-06-27 18:22:35 +00001440 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1441 // new data
1442 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001443 }
1444}
1445
Haynes Mathew George7844f672014-01-15 12:32:55 -08001446// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001447void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001448{
Andy Hung71ba4b32022-10-06 12:09:49 -07001449 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001450 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001451 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001452
Phil Burk4bb650b2016-09-09 12:11:17 -07001453 // Clear the client ring buffer so that the app can prime the buffer while paused.
1454 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1455 mServerProxy->flushBufferIfNeeded();
1456
Haynes Mathew George7844f672014-01-15 12:32:55 -08001457 mFlushHwPending = false;
1458}
1459
Andy Hung3ff4b552023-06-26 19:20:57 -07001460void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001461{
1462 mPauseHwPending = false;
1463}
1464
Andy Hung3ff4b552023-06-26 19:20:57 -07001465void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001466{
1467 // Do not reset twice to avoid discarding data written just after a flush and before
1468 // the audioflinger thread detects the track is stopped.
1469 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001470 // Force underrun condition to avoid false underrun callback until first data is
1471 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001472 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001473 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001474 mResetDone = true;
1475 if (mState == FLUSHED) {
1476 mState = IDLE;
1477 }
1478 }
1479}
1480
Andy Hung3ff4b552023-06-26 19:20:57 -07001481status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001482{
Andy Hung44f27182023-07-06 20:56:16 -07001483 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001484 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001485 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001486 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001487 } else if (thread->type() == IAfThreadBase::DIRECT
1488 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001489 return thread->setParameters(keyValuePairs);
1490 } else {
1491 return PERMISSION_DENIED;
1492 }
1493}
1494
Andy Hung3ff4b552023-06-26 19:20:57 -07001495status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001496 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001497 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001498 if (thread == 0) {
1499 ALOGE("thread is dead");
1500 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001501 } else if (thread->type() == IAfThreadBase::DIRECT
1502 || thread->type() == IAfThreadBase::OFFLOAD) {
1503 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001504 return directOutputThread->selectPresentation(presentationId, programId);
1505 }
1506 return INVALID_OPERATION;
1507}
1508
Andy Hung3ff4b552023-06-26 19:20:57 -07001509VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001510 const sp<VolumeShaper::Configuration>& configuration,
1511 const sp<VolumeShaper::Operation>& operation)
1512{
Andy Hungee86cee2022-12-13 19:19:53 -08001513 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001514
1515 if (isOffloadedOrDirect()) {
1516 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001517 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001518 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001519 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001520 thread->broadcast_l();
1521 }
1522 }
1523 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001524}
1525
Andy Hung3ff4b552023-06-26 19:20:57 -07001526sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001527{
1528 // Note: We don't check if Thread exists.
1529
1530 // mVolumeHandler is thread safe.
1531 return mVolumeHandler->getVolumeShaperState(id);
1532}
1533
Andy Hung3ff4b552023-06-26 19:20:57 -07001534void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001535{
jiabin76d94692022-12-15 21:51:21 +00001536 mFinalVolumeLeft = volumeLeft;
1537 mFinalVolumeRight = volumeRight;
1538 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001539 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1540 mFinalVolume = volume;
1541 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001542 mLogForceVolumeUpdate = true;
1543 }
1544 if (mLogForceVolumeUpdate) {
1545 mLogForceVolumeUpdate = false;
1546 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001547 }
1548}
1549
Andy Hung3ff4b552023-06-26 19:20:57 -07001550void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001551{
Eric Laurent49e39282022-06-24 18:42:45 +02001552 // Do not forward metadata for PatchTrack with unspecified stream type
1553 if (mStreamType == AUDIO_STREAM_PATCH) {
1554 return;
1555 }
1556
Eric Laurent94579172020-11-20 18:41:04 +01001557 playback_track_metadata_v7_t metadata;
1558 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001559 .usage = mAttr.usage,
1560 .content_type = mAttr.content_type,
1561 .gain = mFinalVolume,
1562 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001563
1564 // When attributes are undefined, derive default values from stream type.
1565 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1566 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1567 switch (mStreamType) {
1568 case AUDIO_STREAM_VOICE_CALL:
1569 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1570 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1571 break;
1572 case AUDIO_STREAM_SYSTEM:
1573 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1574 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1575 break;
1576 case AUDIO_STREAM_RING:
1577 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1578 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1579 break;
1580 case AUDIO_STREAM_MUSIC:
1581 metadata.base.usage = AUDIO_USAGE_MEDIA;
1582 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1583 break;
1584 case AUDIO_STREAM_ALARM:
1585 metadata.base.usage = AUDIO_USAGE_ALARM;
1586 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1587 break;
1588 case AUDIO_STREAM_NOTIFICATION:
1589 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1590 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1591 break;
1592 case AUDIO_STREAM_DTMF:
1593 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1594 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1595 break;
1596 case AUDIO_STREAM_ACCESSIBILITY:
1597 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1598 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1599 break;
1600 case AUDIO_STREAM_ASSISTANT:
1601 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1602 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1603 break;
1604 case AUDIO_STREAM_REROUTING:
1605 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1606 // unknown content type
1607 break;
1608 case AUDIO_STREAM_CALL_ASSISTANT:
1609 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1610 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1611 break;
1612 default:
1613 break;
1614 }
1615 }
1616
Eric Laurent78b07302022-10-07 16:20:34 +02001617 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001618 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1619 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001620}
1621
jiabin6e506fc2023-06-27 18:22:35 +00001622void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001623 if (mTeePatchesToUpdate.has_value()) {
jiabin6e506fc2023-06-27 18:22:35 +00001624 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huang98b8d452024-01-04 18:42:55 +00001625 {
1626 RWLock::AutoWLock writeLock(mTeePatchesRWLock);
1627 mTeePatches = std::move(mTeePatchesToUpdate.value());
1628 }
Jiabin Huangfb476842022-12-06 03:18:10 +00001629 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1630 mState == TrackBase::STOPPING_1) {
jiabin6e506fc2023-06-27 18:22:35 +00001631 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001632 }
1633 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001634 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001635}
1636
jiabin6e506fc2023-06-27 18:22:35 +00001637void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001638 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1639 "%s, existing tee patches to update will be ignored", __func__);
1640 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1641}
1642
Vlad Popae8d99472022-06-30 16:02:48 +02001643// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001644void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001645 IAudioManager>& audioManager, mute_state_t muteState)
1646{
1647 if (mMuteState == muteState) {
1648 // mute state did not change, do nothing
1649 return;
1650 }
1651
1652 status_t result = UNKNOWN_ERROR;
1653 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1654 if (mMuteEventExtras == nullptr) {
1655 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1656 }
1657 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1658 static_cast<int>(muteState));
1659
1660 result = audioManager->portEvent(mPortId,
1661 PLAYER_UPDATE_MUTED,
1662 mMuteEventExtras);
1663 }
1664
1665 if (result == OK) {
1666 mMuteState = muteState;
1667 } else {
1668 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1669 __func__,
1670 id(),
1671 mPortId,
1672 result);
Andy Hung818e7a32016-02-16 18:08:07 -08001673 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001674}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001675
Andy Hung3ff4b552023-06-26 19:20:57 -07001676status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001677{
1678 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001679 return INVALID_OPERATION; // normal tracks handled through SSQ
1680 }
Andy Hung44f27182023-07-06 20:56:16 -07001681 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001682 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001683 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001684 }
Phil Burk6140c792015-03-19 14:30:21 -07001685
Andy Hung87e82412023-08-29 14:26:09 -07001686 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001687 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001688 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001689}
1690
Andy Hung3ff4b552023-06-26 19:20:57 -07001691status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001692{
Andy Hung44f27182023-07-06 20:56:16 -07001693 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001694 if (thread == nullptr) {
1695 return DEAD_OBJECT;
1696 }
Eric Laurent81784c32012-11-19 14:55:58 -08001697
Andy Hung44f27182023-07-06 20:56:16 -07001698 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001699 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001700 sp<IAfPlaybackThread> srcThread;
Andy Hungfa2f4f32023-07-17 12:40:43 -07001701 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001702 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001703
Eric Laurent6c796322019-04-09 14:13:17 -07001704 if (EffectId != 0 && status == NO_ERROR) {
1705 status = dstThread->attachAuxEffect(this, EffectId);
1706 if (status == NO_ERROR) {
1707 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001708 }
Eric Laurent6c796322019-04-09 14:13:17 -07001709 }
1710
1711 if (status != NO_ERROR && srcThread != nullptr) {
1712 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001713 }
1714 return status;
1715}
1716
Andy Hung3ff4b552023-06-26 19:20:57 -07001717void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001718{
1719 mAuxEffectId = EffectId;
1720 mAuxBuffer = buffer;
1721}
1722
Andy Hung59de4262021-06-14 10:53:54 -07001723// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001724bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001725 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001726{
Andy Hung818e7a32016-02-16 18:08:07 -08001727 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1728 // This assists in proper timestamp computation as well as wakelock management.
1729
Eric Laurent81784c32012-11-19 14:55:58 -08001730 // a track is considered presented when the total number of frames written to audio HAL
1731 // corresponds to the number of frames written when presentationComplete() is called for the
1732 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001733 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1734 // to detect when all frames have been played. In this case framesWritten isn't
1735 // useful because it doesn't always reflect whether there is data in the h/w
1736 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001737 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1738 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001739 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001740 if (mPresentationCompleteFrames == 0) {
1741 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001742 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001743 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1744 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001745 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001746 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001747
Andy Hungc54b1ff2016-02-23 14:07:07 -08001748 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001749 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001750 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001751 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1752 __func__, mId, (complete ? "complete" : "waiting"),
1753 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001754 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001755 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001756 && mAudioTrackServerProxy->isDrained();
1757 }
1758
1759 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001760 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001761 return true;
1762 }
1763 return false;
1764}
1765
Andy Hung59de4262021-06-14 10:53:54 -07001766// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001767bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001768{
1769 // For Offloaded or Direct tracks.
1770
1771 // For a direct track, we incorporated time based testing for presentationComplete.
1772
1773 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1774 // to detect when all frames have been played. In this case latencyMs isn't
1775 // useful because it doesn't always reflect whether there is data in the h/w
1776 // buffers, particularly if a track has been paused and resumed during draining
1777
1778 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1779 if (mPresentationCompleteTimeNs == 0) {
1780 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1781 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1782 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1783 }
1784
1785 bool complete;
1786 if (isOffloaded()) {
1787 complete = true;
1788 } else { // Direct
1789 complete = systemTime() >= mPresentationCompleteTimeNs;
1790 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1791 }
1792 if (complete) {
1793 notifyPresentationComplete();
1794 return true;
1795 }
1796 return false;
1797}
1798
Andy Hung3ff4b552023-06-26 19:20:57 -07001799void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001800{
1801 // This only triggers once. TODO: should we enforce this?
1802 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1803 mAudioTrackServerProxy->setStreamEndDone();
1804}
1805
Andy Hung3ff4b552023-06-26 19:20:57 -07001806void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001807{
Andy Hung068e08e2023-05-15 19:02:55 -07001808 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1809 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001810 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001811 (*it)->trigger();
1812 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001813 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001814 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001815 }
1816 }
1817}
1818
1819// implement VolumeBufferProvider interface
1820
Andy Hung3ff4b552023-06-26 19:20:57 -07001821gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001822{
1823 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1824 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001825 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1826 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1827 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001828 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001829 if (vl > GAIN_FLOAT_UNITY) {
1830 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001831 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001832 if (vr > GAIN_FLOAT_UNITY) {
1833 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001834 }
1835 // now apply the cached master volume and stream type volume;
1836 // this is trusted but lacks any synchronization or barrier so may be stale
1837 float v = mCachedVolume;
1838 vl *= v;
1839 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001840 // re-combine into packed minifloat
1841 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001842 // FIXME look at mute, pause, and stop flags
1843 return vlr;
1844}
1845
Andy Hung3ff4b552023-06-26 19:20:57 -07001846status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001847 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001848{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001849 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001850 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1851 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001852 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1853 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001854 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001855 event->cancel();
1856 return INVALID_OPERATION;
1857 }
1858 (void) TrackBase::setSyncEvent(event);
1859 return NO_ERROR;
1860}
1861
Andy Hung3ff4b552023-06-26 19:20:57 -07001862void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001863{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001864 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001865 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001866}
1867
Andy Hung3ff4b552023-06-26 19:20:57 -07001868void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001869{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001870 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001871 signalClientFlag(CBLK_DISABLED);
1872}
1873
Andy Hung3ff4b552023-06-26 19:20:57 -07001874void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001875{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001876 // FIXME should use proxy, and needs work
1877 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001878 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001879 android_atomic_release_store(0x40000000, &cblk->mFutex);
1880 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001881 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001882}
1883
Andy Hung3ff4b552023-06-26 19:20:57 -07001884void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001885{
Andy Hung44f27182023-07-06 20:56:16 -07001886 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001887 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001888 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001889 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001890 t->broadcast_l();
1891 }
1892}
1893
Andy Hung3ff4b552023-06-26 19:20:57 -07001894status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001895{
1896 status_t status = INVALID_OPERATION;
1897 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001898 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001899 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001900 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001901 audio_utils::lock_guard _l(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001902 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001903 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1904 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1905 }
1906 }
1907 return status;
1908}
1909
Andy Hung3ff4b552023-06-26 19:20:57 -07001910status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001911{
1912 status_t status = INVALID_OPERATION;
1913 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001914 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001915 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001916 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001917 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001918 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001919 if (status == NO_ERROR) {
1920 mDualMonoMode = mode;
1921 }
1922 }
1923 }
1924 return status;
1925}
1926
Andy Hung3ff4b552023-06-26 19:20:57 -07001927status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001928{
1929 status_t status = INVALID_OPERATION;
1930 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001931 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001933 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001934 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001935 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001936 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1937 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1938 }
1939 }
1940 return status;
1941}
1942
Andy Hung3ff4b552023-06-26 19:20:57 -07001943status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001944{
1945 status_t status = INVALID_OPERATION;
1946 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001947 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001948 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001949 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001950 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001951 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001952 if (status == NO_ERROR) {
1953 mAudioDescriptionMixLevel = leveldB;
1954 }
1955 }
1956 }
1957 return status;
1958}
1959
Andy Hung3ff4b552023-06-26 19:20:57 -07001960status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001961 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001962{
1963 status_t status = INVALID_OPERATION;
1964 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001965 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001966 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001967 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001968 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001969 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001970 ALOGD_IF((status == NO_ERROR) &&
1971 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1972 "%s: playbackRate inconsistent", __func__);
1973 }
1974 }
1975 return status;
1976}
1977
Andy Hung3ff4b552023-06-26 19:20:57 -07001978status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001979 const audio_playback_rate_t& playbackRate)
1980{
1981 status_t status = INVALID_OPERATION;
1982 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001983 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001984 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001985 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001986 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001987 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001988 if (status == NO_ERROR) {
1989 mPlaybackRateParameters = playbackRate;
1990 }
1991 }
1992 }
1993 return status;
1994}
1995
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001996//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001997bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07001998 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001999 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07002000 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002001 /* Resume is pending if track was stopping before pause was called */
2002 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07002003 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002004 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07002005 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002006
2007 return false;
2008}
2009
2010//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002011void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07002012 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002013 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07002014 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002015
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002016 // Other possibility of pending resume is stopping_1 state
2017 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002018 // drain being called.
2019 if (mState == STOPPING_1) {
2020 mResumeToStopping = false;
2021 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002022}
Andy Hunge10393e2015-06-12 13:59:33 -07002023
2024//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002025void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002026 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002027 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002028 // Make the kernel frametime available.
2029 const FrameTime ft{
2030 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2031 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2032 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2033 mKernelFrameTime.store(ft);
2034 if (!audio_is_linear_pcm(mFormat)) {
2035 return;
2036 }
2037
Andy Hung818e7a32016-02-16 18:08:07 -08002038 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002039 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002040
2041 // adjust server times and set drained state.
2042 //
2043 // Our timestamps are only updated when the track is on the Thread active list.
2044 // We need to ensure that tracks are not removed before full drain.
2045 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002046 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002047 bool checked = false;
2048 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2049 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2050 // Lookup the track frame corresponding to the sink frame position.
2051 if (local.mTimeNs[i] > 0) {
2052 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2053 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002054 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002055 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002056 checked = true;
2057 }
2058 }
Andy Hunge10393e2015-06-12 13:59:33 -07002059 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002060
Andy Hung93bb5732023-05-04 21:16:34 -07002061 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2062 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002063 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002064 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002065 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002066 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002067
2068 // Compute latency info.
2069 const bool useTrackTimestamp = !drained;
2070 const double latencyMs = useTrackTimestamp
2071 ? local.getOutputServerLatencyMs(sampleRate())
2072 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2073
2074 mServerLatencyFromTrack.store(useTrackTimestamp);
2075 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002076
Andy Hung62921122020-05-18 10:47:31 -07002077 if (mLogStartCountdown > 0
2078 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2079 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2080 {
2081 if (mLogStartCountdown > 1) {
2082 --mLogStartCountdown;
2083 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2084 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002085 // startup is the difference in times for the current timestamp and our start
2086 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002087 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002088 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002089 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2090 * 1e3 / mSampleRate;
2091 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2092 " localTime:%lld startTime:%lld"
2093 " localPosition:%lld startPosition:%lld",
2094 __func__, latencyMs, startUpMs,
2095 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002096 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002097 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002098 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002099 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002100 }
Andy Hung62921122020-05-18 10:47:31 -07002101 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002102 }
Andy Hunge10393e2015-06-12 13:59:33 -07002103}
2104
Andy Hung3ff4b552023-06-26 19:20:57 -07002105bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002106 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002107 if (thread != 0) {
2108 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87e82412023-08-29 14:26:09 -07002109 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002110 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002111 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002112 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002113 ALOGD("%s, haptic playback was %s for track %d",
2114 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002115 mTrack->setHapticPlaybackEnabled(!muted);
2116 return true;
jiabin57303cc2018-12-18 15:45:57 -08002117 }
2118 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002119 return false;
2120}
2121
Andy Hung3ff4b552023-06-26 19:20:57 -07002122binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002123 /*out*/ bool *ret) {
2124 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002125 return binder::Status::ok();
2126}
2127
Andy Hung3ff4b552023-06-26 19:20:57 -07002128binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002129 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002130 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002131 return binder::Status::ok();
2132}
2133
Eric Laurent81784c32012-11-19 14:55:58 -08002134// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002135#undef LOG_TAG
2136#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002137
Andy Hung3ff4b552023-06-26 19:20:57 -07002138/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002139sp<IAfOutputTrack> IAfOutputTrack::create(
2140 IAfPlaybackThread* playbackThread,
2141 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002142 uint32_t sampleRate,
2143 audio_format_t format,
2144 audio_channel_mask_t channelMask,
2145 size_t frameCount,
2146 const AttributionSourceState& attributionSource) {
2147 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002148 playbackThread,
2149 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002150 sampleRate,
2151 format,
2152 channelMask,
2153 frameCount,
2154 attributionSource);
2155}
2156
2157OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002158 IAfPlaybackThread* playbackThread,
2159 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002160 uint32_t sampleRate,
2161 audio_format_t format,
2162 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002163 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002164 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002165 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002166 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002167 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002168 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002169 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002170 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002171 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002172{
2173
2174 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002175 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002176 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002177 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002178 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002179 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002180 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002181 // since client and server are in the same process,
2182 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002183 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2184 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002185 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002186 mClientProxy->setSendLevel(0.0);
2187 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002188 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002189 ALOGW("%s(%d): Error creating output track on thread %d",
2190 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002191 }
2192}
2193
Andy Hung3ff4b552023-06-26 19:20:57 -07002194OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002195{
2196 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002197 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002198}
2199
Andy Hung3ff4b552023-06-26 19:20:57 -07002200status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002201 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002202{
2203 status_t status = Track::start(event, triggerSession);
2204 if (status != NO_ERROR) {
2205 return status;
2206 }
2207
2208 mActive = true;
2209 mRetryCount = 127;
2210 return status;
2211}
2212
Andy Hung3ff4b552023-06-26 19:20:57 -07002213void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002214{
2215 Track::stop();
2216 clearBufferQueue();
2217 mOutBuffer.frameCount = 0;
2218 mActive = false;
2219}
2220
Andy Hung3ff4b552023-06-26 19:20:57 -07002221ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002222{
Eric Laurent19952e12023-04-20 10:08:29 +02002223 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002224 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002225 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002226 // preload one silent buffer to trigger mixer on start()
2227 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2228 status_t status = mClientProxy->obtainBuffer(&buf);
2229 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2230 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2231 return 0;
2232 }
2233 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2234 mClientProxy->releaseBuffer(&buf);
2235
2236 (void) start();
2237
2238 // wait for HAL stream to start before sending actual audio. Doing this on each
2239 // OutputTrack makes that playback start on all output streams is synchronized.
2240 // If another OutputTrack has already started it can underrun but this is OK
2241 // as only silence has been played so far and the retry count is very high on
2242 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002243 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002244 if (!pt->waitForHalStart()) {
2245 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2246 stop();
2247 return 0;
2248 }
2249
2250 // enqueue the first buffer and exit so that other OutputTracks will also start before
2251 // write() is called again and this buffer actually consumed.
2252 Buffer firstBuffer;
2253 firstBuffer.frameCount = frames;
2254 firstBuffer.raw = data;
2255 queueBuffer(firstBuffer);
2256 return frames;
2257 } else {
2258 (void) start();
2259 }
2260 }
2261
Eric Laurent81784c32012-11-19 14:55:58 -08002262 Buffer *pInBuffer;
2263 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002264 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002265 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002266 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002267 while (waitTimeLeftMs) {
2268 // First write pending buffers, then new data
2269 if (mBufferQueue.size()) {
2270 pInBuffer = mBufferQueue.itemAt(0);
2271 } else {
2272 pInBuffer = &inBuffer;
2273 }
2274
2275 if (pInBuffer->frameCount == 0) {
2276 break;
2277 }
2278
2279 if (mOutBuffer.frameCount == 0) {
2280 mOutBuffer.frameCount = pInBuffer->frameCount;
2281 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002282 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002283 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002284 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2285 __func__, mId,
2286 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002287 break;
2288 }
2289 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2290 if (waitTimeLeftMs >= waitTimeMs) {
2291 waitTimeLeftMs -= waitTimeMs;
2292 } else {
2293 waitTimeLeftMs = 0;
2294 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002295 if (status == NOT_ENOUGH_DATA) {
2296 restartIfDisabled();
2297 continue;
2298 }
Eric Laurent81784c32012-11-19 14:55:58 -08002299 }
2300
2301 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2302 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002303 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002304 Proxy::Buffer buf;
2305 buf.mFrameCount = outFrames;
2306 buf.mRaw = NULL;
2307 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002308 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002309 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002310 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002311 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002312 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002313
2314 if (pInBuffer->frameCount == 0) {
2315 if (mBufferQueue.size()) {
2316 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002317 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002318 if (pInBuffer != &inBuffer) {
2319 delete pInBuffer;
2320 }
Andy Hung9d84af52018-09-12 18:03:44 -07002321 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2322 __func__, mId,
2323 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002324 } else {
2325 break;
2326 }
2327 }
2328 }
2329
2330 // If we could not write all frames, allocate a buffer and queue it for next time.
2331 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002332 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002333 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002334 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002335 }
2336 }
2337
Andy Hungc25b84a2015-01-14 19:04:10 -08002338 // Calling write() with a 0 length buffer means that no more data will be written:
2339 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2340 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2341 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002342 }
2343
Andy Hung1c86ebe2018-05-29 20:29:08 -07002344 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002345}
2346
Andy Hung3ff4b552023-06-26 19:20:57 -07002347void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002348
2349 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2350 Buffer *pInBuffer = new Buffer;
2351 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2352 pInBuffer->mBuffer = malloc(bufferSize);
2353 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2354 "%s: Unable to malloc size %zu", __func__, bufferSize);
2355 pInBuffer->frameCount = inBuffer.frameCount;
2356 pInBuffer->raw = pInBuffer->mBuffer;
2357 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2358 mBufferQueue.add(pInBuffer);
2359 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2360 (int)mThreadIoHandle, mBufferQueue.size());
2361 // audio data is consumed (stored locally); set frameCount to 0.
2362 inBuffer.frameCount = 0;
2363 } else {
2364 ALOGW("%s(%d): thread %d no more overflow buffers",
2365 __func__, mId, (int)mThreadIoHandle);
2366 // TODO: return error for this.
2367 }
2368}
2369
Andy Hung3ff4b552023-06-26 19:20:57 -07002370void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002371{
Andy Hung87e82412023-08-29 14:26:09 -07002372 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002373 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2374}
2375
Andy Hung3ff4b552023-06-26 19:20:57 -07002376void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002377 {
Andy Hung87e82412023-08-29 14:26:09 -07002378 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002379 mTrackMetadatas = metadatas;
2380 }
2381 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2382 setMetadataHasChanged();
2383}
2384
Andy Hung3ff4b552023-06-26 19:20:57 -07002385status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002386 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2387{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002388 ClientProxy::Buffer buf;
2389 buf.mFrameCount = buffer->frameCount;
2390 struct timespec timeout;
2391 timeout.tv_sec = waitTimeMs / 1000;
2392 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2393 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2394 buffer->frameCount = buf.mFrameCount;
2395 buffer->raw = buf.mRaw;
2396 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002397}
2398
Andy Hung3ff4b552023-06-26 19:20:57 -07002399void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002400{
2401 size_t size = mBufferQueue.size();
2402
2403 for (size_t i = 0; i < size; i++) {
2404 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002405 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002406 delete pBuffer;
2407 }
2408 mBufferQueue.clear();
2409}
2410
Andy Hung3ff4b552023-06-26 19:20:57 -07002411void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002412{
2413 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2414 if (mActive && (flags & CBLK_DISABLED)) {
2415 start();
2416 }
2417}
Eric Laurent81784c32012-11-19 14:55:58 -08002418
Andy Hung9d84af52018-09-12 18:03:44 -07002419// ----------------------------------------------------------------------------
2420#undef LOG_TAG
2421#define LOG_TAG "AF::PatchTrack"
2422
Andy Hung3ff4b552023-06-26 19:20:57 -07002423/* static */
2424sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002425 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002426 audio_stream_type_t streamType,
2427 uint32_t sampleRate,
2428 audio_channel_mask_t channelMask,
2429 audio_format_t format,
2430 size_t frameCount,
2431 void* buffer,
2432 size_t bufferSize,
2433 audio_output_flags_t flags,
2434 const Timeout& timeout,
2435 size_t frameCountToBeReady /** Default behaviour is to start
2436 * as soon as possible to have
2437 * the lowest possible latency
2438 * even if it might glitch. */)
2439{
2440 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002441 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002442 streamType,
2443 sampleRate,
2444 channelMask,
2445 format,
2446 frameCount,
2447 buffer,
2448 bufferSize,
2449 flags,
2450 timeout,
2451 frameCountToBeReady);
2452}
2453
Andy Hung44f27182023-07-06 20:56:16 -07002454PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002455 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002456 uint32_t sampleRate,
2457 audio_channel_mask_t channelMask,
2458 audio_format_t format,
2459 size_t frameCount,
2460 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002461 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002462 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002463 const Timeout& timeout,
2464 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002465 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002466 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002467 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002468 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002469 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002470 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002471 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2472 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07002473 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002474{
Andy Hung9d84af52018-09-12 18:03:44 -07002475 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2476 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002477 (int)mPeerTimeout.tv_sec,
2478 (int)(mPeerTimeout.tv_nsec / 1000000));
2479}
2480
Andy Hung3ff4b552023-06-26 19:20:57 -07002481PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002482{
Andy Hungabfab202019-03-07 19:45:54 -08002483 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002484}
2485
Andy Hung3ff4b552023-06-26 19:20:57 -07002486size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002487{
2488 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2489 return std::numeric_limits<size_t>::max();
2490 } else {
2491 return Track::framesReady();
2492 }
2493}
2494
Andy Hung3ff4b552023-06-26 19:20:57 -07002495status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002496 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002497{
2498 status_t status = Track::start(event, triggerSession);
2499 if (status != NO_ERROR) {
2500 return status;
2501 }
2502 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2503 return status;
2504}
2505
Eric Laurent83b88082014-06-20 18:31:16 -07002506// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002507status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002508 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002509{
Andy Hung9d84af52018-09-12 18:03:44 -07002510 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002511 Proxy::Buffer buf;
2512 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002513 if (ATRACE_ENABLED()) {
2514 std::string traceName("PTnReq");
2515 traceName += std::to_string(id());
2516 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2517 }
Eric Laurent83b88082014-06-20 18:31:16 -07002518 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002519 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002520 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002521 if (ATRACE_ENABLED()) {
2522 std::string traceName("PTnObt");
2523 traceName += std::to_string(id());
2524 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2525 }
Eric Laurent83b88082014-06-20 18:31:16 -07002526 if (buf.mFrameCount == 0) {
2527 return WOULD_BLOCK;
2528 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002529 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002530 return status;
2531}
2532
Andy Hung3ff4b552023-06-26 19:20:57 -07002533void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002534{
Andy Hung9d84af52018-09-12 18:03:44 -07002535 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002536 Proxy::Buffer buf;
2537 buf.mFrameCount = buffer->frameCount;
2538 buf.mRaw = buffer->raw;
2539 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002540 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002541}
2542
Andy Hung3ff4b552023-06-26 19:20:57 -07002543status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002544 const struct timespec *timeOut)
2545{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002546 status_t status = NO_ERROR;
2547 static const int32_t kMaxTries = 5;
2548 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002549 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002550 do {
2551 if (status == NOT_ENOUGH_DATA) {
2552 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002553 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002554 }
2555 status = mProxy->obtainBuffer(buffer, timeOut);
2556 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2557 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002558}
2559
Andy Hung3ff4b552023-06-26 19:20:57 -07002560void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002561{
2562 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002563 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002564
2565 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2566 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2567 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2568 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002569 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002570 && audio_is_linear_pcm(mFormat)
2571 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002572 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002573 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002574 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002575 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2576 / playbackThread->sampleRate();
2577 if (framesReady() < frameCount) {
2578 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002579 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002580 }
2581 }
2582 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002583}
2584
Andy Hung3ff4b552023-06-26 19:20:57 -07002585void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002586{
Eric Laurent83b88082014-06-20 18:31:16 -07002587 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002588 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002589 start();
2590 }
Eric Laurent83b88082014-06-20 18:31:16 -07002591}
2592
Eric Laurent81784c32012-11-19 14:55:58 -08002593// ----------------------------------------------------------------------------
2594// Record
2595// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002596
2597
Andy Hung9d84af52018-09-12 18:03:44 -07002598#undef LOG_TAG
2599#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002600
Andy Hungaaa18282023-06-23 19:27:19 -07002601class RecordHandle : public android::media::BnAudioRecord {
2602public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002603 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002604 ~RecordHandle() override;
2605 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2606 int /*audio_session_t*/ triggerSession) final;
2607 binder::Status stop() final;
2608 binder::Status getActiveMicrophones(
2609 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2610 binder::Status setPreferredMicrophoneDirection(
2611 int /*audio_microphone_direction_t*/ direction) final;
2612 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2613 binder::Status shareAudioHistory(
2614 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2615
2616private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002617 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002618
2619 // for use from destructor
2620 void stop_nonvirtual();
2621};
2622
2623/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002624sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2625 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002626 return sp<RecordHandle>::make(recordTrack);
2627}
2628
2629RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002630 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002631 : BnAudioRecord(),
2632 mRecordTrack(recordTrack)
2633{
Andy Hung225aef62022-12-06 16:33:20 -08002634 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002635}
2636
Andy Hungaaa18282023-06-23 19:27:19 -07002637RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002638 stop_nonvirtual();
2639 mRecordTrack->destroy();
2640}
2641
Andy Hungaaa18282023-06-23 19:27:19 -07002642binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002643 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002644 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002645 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002646 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002647}
2648
Andy Hungaaa18282023-06-23 19:27:19 -07002649binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002650 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002651 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002652}
2653
Andy Hungaaa18282023-06-23 19:27:19 -07002654void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002655 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002656 mRecordTrack->stop();
2657}
2658
Andy Hungaaa18282023-06-23 19:27:19 -07002659binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002660 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002661 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002662 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002663}
2664
Andy Hungaaa18282023-06-23 19:27:19 -07002665binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002666 int /*audio_microphone_direction_t*/ direction) {
2667 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002668 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002669 static_cast<audio_microphone_direction_t>(direction)));
2670}
2671
Andy Hungaaa18282023-06-23 19:27:19 -07002672binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002673 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002674 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002675}
2676
Andy Hungaaa18282023-06-23 19:27:19 -07002677binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002678 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2679 return binderStatusFromStatusT(
2680 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2681}
2682
Eric Laurent81784c32012-11-19 14:55:58 -08002683// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002684#undef LOG_TAG
2685#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002686
Andy Hung3ff4b552023-06-26 19:20:57 -07002687
Andy Hung56126702023-07-14 11:00:08 -07002688/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002689sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002690 const sp<Client>& client,
2691 const audio_attributes_t& attr,
2692 uint32_t sampleRate,
2693 audio_format_t format,
2694 audio_channel_mask_t channelMask,
2695 size_t frameCount,
2696 void* buffer,
2697 size_t bufferSize,
2698 audio_session_t sessionId,
2699 pid_t creatorPid,
2700 const AttributionSourceState& attributionSource,
2701 audio_input_flags_t flags,
2702 track_type type,
2703 audio_port_handle_t portId,
2704 int32_t startFrames)
2705{
2706 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002707 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002708 client,
2709 attr,
2710 sampleRate,
2711 format,
2712 channelMask,
2713 frameCount,
2714 buffer,
2715 bufferSize,
2716 sessionId,
2717 creatorPid,
2718 attributionSource,
2719 flags,
2720 type,
2721 portId,
2722 startFrames);
2723}
2724
Glenn Kasten05997e22014-03-13 15:08:33 -07002725// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002726RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002727 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002728 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002729 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002730 uint32_t sampleRate,
2731 audio_format_t format,
2732 audio_channel_mask_t channelMask,
2733 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002734 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002735 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002736 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002737 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002738 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002739 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002740 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002741 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002742 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002743 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002744 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002745 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002746 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002747 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002748 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002749 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002750 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002751 type, portId,
2752 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002753 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002754 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002755 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002756 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002757 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002758 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002759{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002760 if (mCblk == NULL) {
2761 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002762 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002763
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002764 if (!isDirect()) {
2765 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002766 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002767 channelMask, format, sampleRate);
2768 // Check if the RecordBufferConverter construction was successful.
2769 // If not, don't continue with construction.
2770 //
2771 // NOTE: It would be extremely rare that the record track cannot be created
2772 // for the current device, but a pending or future device change would make
2773 // the record track configuration valid.
2774 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002775 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002776 return;
2777 }
Andy Hung97a893e2015-03-29 01:03:07 -07002778 }
2779
Andy Hung6ae58432016-02-16 18:32:24 -08002780 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002781 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002782
Andy Hung97a893e2015-03-29 01:03:07 -07002783 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002784
Eric Laurent05067782016-06-01 18:27:28 -07002785 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002786 ALOG_ASSERT(thread->fastTrackAvailable());
2787 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002788 } else {
2789 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002790 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002791 }
Andy Hung8946a282018-04-19 20:04:56 -07002792#ifdef TEE_SINK
2793 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2794 + "_" + std::to_string(mId)
2795 + "_R");
2796#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002797
2798 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002799 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002800}
2801
Andy Hung3ff4b552023-06-26 19:20:57 -07002802RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002803{
Andy Hung9d84af52018-09-12 18:03:44 -07002804 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002805 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002806 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002807}
2808
Andy Hung3ff4b552023-06-26 19:20:57 -07002809status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002810{
2811 status_t status = TrackBase::initCheck();
2812 if (status == NO_ERROR && mServerProxy == 0) {
2813 status = BAD_VALUE;
2814 }
2815 return status;
2816}
2817
Eric Laurent81784c32012-11-19 14:55:58 -08002818// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002819status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002820{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002821 ServerProxy::Buffer buf;
2822 buf.mFrameCount = buffer->frameCount;
2823 status_t status = mServerProxy->obtainBuffer(&buf);
2824 buffer->frameCount = buf.mFrameCount;
2825 buffer->raw = buf.mRaw;
2826 if (buf.mFrameCount == 0) {
2827 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002828 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002829 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002830 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002831}
2832
Andy Hung3ff4b552023-06-26 19:20:57 -07002833status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002834 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002835{
Andy Hung44f27182023-07-06 20:56:16 -07002836 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002837 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002838 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002839 return recordThread->start(this, event, triggerSession);
2840 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002841 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2842 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002843 }
2844}
2845
Andy Hung3ff4b552023-06-26 19:20:57 -07002846void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002847{
Andy Hung44f27182023-07-06 20:56:16 -07002848 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002849 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002850 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002851 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002852 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002853 }
2854 }
2855}
2856
Andy Hung3ff4b552023-06-26 19:20:57 -07002857void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002858{
Andy Hung3ff4b552023-06-26 19:20:57 -07002859 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002860 sp<RecordTrack> keep(this);
2861 {
Andy Hungce685402018-10-05 17:23:27 -07002862 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002863 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002864 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07002865 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002866 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002867 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002868 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002869 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002870 }
Andy Hungce685402018-10-05 17:23:27 -07002871 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2872 }
2873 // APM portid/client management done outside of lock.
2874 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2875 if (isExternalTrack()) {
2876 switch (priorState) {
2877 case ACTIVE: // invalidated while still active
2878 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2879 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2880 AudioSystem::stopInput(mPortId);
2881 break;
2882
2883 case STARTING_1: // invalidated/start-aborted and startInput not successful
2884 case PAUSED: // OK, not active
2885 case IDLE: // OK, not active
2886 break;
2887
2888 case STOPPED: // unexpected (destroyed)
2889 default:
2890 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2891 }
2892 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002893 }
2894 }
2895}
2896
Andy Hung3ff4b552023-06-26 19:20:57 -07002897void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002898{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002899 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002900 // FIXME should use proxy, and needs work
2901 audio_track_cblk_t* cblk = mCblk;
2902 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2903 android_atomic_release_store(0x40000000, &cblk->mFutex);
2904 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002905 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002906}
2907
Eric Laurent81784c32012-11-19 14:55:58 -08002908
Andy Hung3ff4b552023-06-26 19:20:57 -07002909void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002910{
Eric Laurent973db022018-11-20 14:54:31 -08002911 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002912 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002913 " Server FrmCnt FrmRdy Sil%s\n",
2914 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002915}
2916
Andy Hung3ff4b552023-06-26 19:20:57 -07002917void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002918{
Eric Laurent973db022018-11-20 14:54:31 -08002919 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002920 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002921 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002922 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002923 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002924 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002925 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002926 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002927 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002928 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002929 mCblk->mFlags,
2930
Eric Laurent81784c32012-11-19 14:55:58 -08002931 mFormat,
2932 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002933 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002934 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002935
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002936 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002937 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002938 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002939 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002940 );
Andy Hung000adb52018-06-01 15:43:26 -07002941 if (isServerLatencySupported()) {
2942 double latencyMs;
2943 bool fromTrack;
2944 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2945 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2946 // or 'k' if estimated from kernel (usually for debugging).
2947 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2948 } else {
2949 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2950 }
2951 }
2952 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002953}
2954
Andy Hung93bb5732023-05-04 21:16:34 -07002955// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002956void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002957 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002958{
Andy Hung93bb5732023-05-04 21:16:34 -07002959 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002960 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002961 if (threadBase != 0) {
2962 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2963 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002964 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002965 }
Andy Hung93bb5732023-05-04 21:16:34 -07002966
2967 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002968}
2969
Andy Hung3ff4b552023-06-26 19:20:57 -07002970void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002971{
Andy Hung93bb5732023-05-04 21:16:34 -07002972 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002973}
2974
Andy Hung3ff4b552023-06-26 19:20:57 -07002975void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002976 int64_t trackFramesReleased, int64_t sourceFramesRead,
2977 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2978{
Andy Hung30282562018-08-08 18:27:03 -07002979 // Make the kernel frametime available.
2980 const FrameTime ft{
2981 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2982 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2983 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2984 mKernelFrameTime.store(ft);
2985 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002986 // Stream is direct, return provided timestamp with no conversion
2987 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002988 return;
2989 }
2990
Andy Hung3f0c9022016-01-15 17:49:46 -08002991 ExtendedTimestamp local = timestamp;
2992
2993 // Convert HAL frames to server-side track frames at track sample rate.
2994 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2995 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2996 if (local.mTimeNs[i] != 0) {
2997 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2998 const int64_t relativeTrackFrames = relativeServerFrames
2999 * mSampleRate / halSampleRate; // TODO: potential computation overflow
3000 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
3001 }
3002 }
Andy Hung6ae58432016-02-16 18:32:24 -08003003 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07003004
3005 // Compute latency info.
3006 const bool useTrackTimestamp = true; // use track unless debugging.
3007 const double latencyMs = - (useTrackTimestamp
3008 ? local.getOutputServerLatencyMs(sampleRate())
3009 : timestamp.getOutputServerLatencyMs(halSampleRate));
3010
3011 mServerLatencyFromTrack.store(useTrackTimestamp);
3012 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003013}
Eric Laurent83b88082014-06-20 18:31:16 -07003014
Andy Hung3ff4b552023-06-26 19:20:57 -07003015status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003016 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003017{
Andy Hung44f27182023-07-06 20:56:16 -07003018 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003019 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003020 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003021 return recordThread->getActiveMicrophones(activeMicrophones);
3022 } else {
3023 return BAD_VALUE;
3024 }
3025}
3026
Andy Hung3ff4b552023-06-26 19:20:57 -07003027status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003028 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003029 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003030 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003031 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003032 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003033 } else {
3034 return BAD_VALUE;
3035 }
3036}
3037
Andy Hung3ff4b552023-06-26 19:20:57 -07003038status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003039 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003040 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003041 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003042 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003043 } else {
3044 return BAD_VALUE;
3045 }
3046}
3047
Andy Hung3ff4b552023-06-26 19:20:57 -07003048status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003049 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3050
3051 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3052 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3053 if (callingUid != mUid || callingPid != mCreatorPid) {
3054 return PERMISSION_DENIED;
3055 }
3056
Svet Ganov33761132021-05-13 22:51:08 +00003057 AttributionSourceState attributionSource{};
3058 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3059 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3060 attributionSource.token = sp<BBinder>::make();
3061 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003062 return PERMISSION_DENIED;
3063 }
3064
Andy Hung44f27182023-07-06 20:56:16 -07003065 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003066 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003067 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003068 status_t status = recordThread->shareAudioHistory(
3069 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3070 if (status == NO_ERROR) {
3071 mSharedAudioPackageName = sharedAudioPackageName;
3072 }
3073 return status;
3074 } else {
3075 return BAD_VALUE;
3076 }
3077}
3078
Andy Hung3ff4b552023-06-26 19:20:57 -07003079void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003080{
3081
3082 // Do not forward PatchRecord metadata with unspecified audio source
3083 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3084 return;
3085 }
3086
3087 // No track is invalid as this is called after prepareTrack_l in the same critical section
3088 record_track_metadata_v7_t metadata;
3089 metadata.base = {
3090 .source = mAttr.source,
3091 .gain = 1, // capture tracks do not have volumes
3092 };
3093 metadata.channel_mask = mChannelMask;
3094 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3095
3096 *backInserter++ = metadata;
3097}
Eric Laurentec376dc2021-04-08 20:41:22 +02003098
Andy Hung9d84af52018-09-12 18:03:44 -07003099// ----------------------------------------------------------------------------
3100#undef LOG_TAG
3101#define LOG_TAG "AF::PatchRecord"
3102
Andy Hung3ff4b552023-06-26 19:20:57 -07003103/* static */
3104sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003105 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003106 uint32_t sampleRate,
3107 audio_channel_mask_t channelMask,
3108 audio_format_t format,
3109 size_t frameCount,
3110 void *buffer,
3111 size_t bufferSize,
3112 audio_input_flags_t flags,
3113 const Timeout& timeout,
3114 audio_source_t source)
3115{
3116 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003117 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003118 sampleRate,
3119 channelMask,
3120 format,
3121 frameCount,
3122 buffer,
3123 bufferSize,
3124 flags,
3125 timeout,
3126 source);
3127}
3128
Andy Hung44f27182023-07-06 20:56:16 -07003129PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003130 uint32_t sampleRate,
3131 audio_channel_mask_t channelMask,
3132 audio_format_t format,
3133 size_t frameCount,
3134 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003135 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003136 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003137 const Timeout& timeout,
3138 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003139 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003140 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003141 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003142 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003143 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003144 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3145 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07003146 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003147{
Andy Hung9d84af52018-09-12 18:03:44 -07003148 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3149 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003150 (int)mPeerTimeout.tv_sec,
3151 (int)(mPeerTimeout.tv_nsec / 1000000));
3152}
3153
Andy Hung3ff4b552023-06-26 19:20:57 -07003154PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003155{
Andy Hungabfab202019-03-07 19:45:54 -08003156 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003157}
3158
Mikhail Naganov8296c252019-09-25 14:59:54 -07003159static size_t writeFramesHelper(
3160 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3161{
3162 AudioBufferProvider::Buffer patchBuffer;
3163 patchBuffer.frameCount = frameCount;
3164 auto status = dest->getNextBuffer(&patchBuffer);
3165 if (status != NO_ERROR) {
3166 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3167 __func__, status, strerror(-status));
3168 return 0;
3169 }
3170 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3171 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3172 size_t framesWritten = patchBuffer.frameCount;
3173 dest->releaseBuffer(&patchBuffer);
3174 return framesWritten;
3175}
3176
3177// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003178size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003179 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3180{
3181 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3182 // On buffer wrap, the buffer frame count will be less than requested,
3183 // when this happens a second buffer needs to be used to write the leftover audio
3184 const size_t framesLeft = frameCount - framesWritten;
3185 if (framesWritten != 0 && framesLeft != 0) {
3186 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3187 framesLeft, frameSize);
3188 }
3189 return framesWritten;
3190}
3191
Eric Laurent83b88082014-06-20 18:31:16 -07003192// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003193status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003194 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003195{
Andy Hung9d84af52018-09-12 18:03:44 -07003196 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003197 Proxy::Buffer buf;
3198 buf.mFrameCount = buffer->frameCount;
3199 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3200 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003201 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003202 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003203 if (ATRACE_ENABLED()) {
3204 std::string traceName("PRnObt");
3205 traceName += std::to_string(id());
3206 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3207 }
Eric Laurent83b88082014-06-20 18:31:16 -07003208 if (buf.mFrameCount == 0) {
3209 return WOULD_BLOCK;
3210 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003211 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003212 return status;
3213}
3214
Andy Hung3ff4b552023-06-26 19:20:57 -07003215void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003216{
Andy Hung9d84af52018-09-12 18:03:44 -07003217 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003218 Proxy::Buffer buf;
3219 buf.mFrameCount = buffer->frameCount;
3220 buf.mRaw = buffer->raw;
3221 mPeerProxy->releaseBuffer(&buf);
3222 TrackBase::releaseBuffer(buffer);
3223}
3224
Andy Hung3ff4b552023-06-26 19:20:57 -07003225status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003226 const struct timespec *timeOut)
3227{
3228 return mProxy->obtainBuffer(buffer, timeOut);
3229}
3230
Andy Hung3ff4b552023-06-26 19:20:57 -07003231void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003232{
3233 mProxy->releaseBuffer(buffer);
3234}
3235
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003236#undef LOG_TAG
3237#define LOG_TAG "AF::PthrPatchRecord"
3238
3239static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3240{
3241 void *ptr = nullptr;
3242 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003243 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003244}
3245
Andy Hung3ff4b552023-06-26 19:20:57 -07003246/* static */
3247sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003248 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003249 uint32_t sampleRate,
3250 audio_channel_mask_t channelMask,
3251 audio_format_t format,
3252 size_t frameCount,
3253 audio_input_flags_t flags,
3254 audio_source_t source)
3255{
3256 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003257 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003258 sampleRate,
3259 channelMask,
3260 format,
3261 frameCount,
3262 flags,
3263 source);
3264}
3265
3266PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003267 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003268 uint32_t sampleRate,
3269 audio_channel_mask_t channelMask,
3270 audio_format_t format,
3271 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003272 audio_input_flags_t flags,
3273 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003274 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003275 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003276 mPatchRecordAudioBufferProvider(*this),
3277 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3278 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3279{
3280 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3281}
3282
Andy Hung3ff4b552023-06-26 19:20:57 -07003283sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003284 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003285{
3286 *thread = mThread.promote();
3287 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003288 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07003289 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07003290 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003291}
3292
3293// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003294status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003295 Proxy::Buffer* buffer, const struct timespec* timeOut)
3296{
3297 if (mUnconsumedFrames) {
3298 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3299 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3300 return PatchRecord::obtainBuffer(buffer, timeOut);
3301 }
3302
3303 // Otherwise, execute a read from HAL and write into the buffer.
3304 nsecs_t startTimeNs = 0;
3305 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3306 // Will need to correct timeOut by elapsed time.
3307 startTimeNs = systemTime();
3308 }
3309 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3310 buffer->mFrameCount = 0;
3311 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003312 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003313 sp<StreamInHalInterface> stream = obtainStream(&thread);
3314 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3315
3316 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003317 size_t bytesRead = 0;
3318 {
3319 ATRACE_NAME("read");
3320 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3321 if (result != NO_ERROR) goto stream_error;
3322 if (bytesRead == 0) return NO_ERROR;
3323 }
3324
3325 {
Andy Hung094dc762023-08-28 19:12:14 -07003326 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003327 mReadBytes += bytesRead;
3328 mReadError = NO_ERROR;
3329 }
3330 mReadCV.notify_one();
3331 // writeFrames handles wraparound and should write all the provided frames.
3332 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3333 buffer->mFrameCount = writeFrames(
3334 &mPatchRecordAudioBufferProvider,
3335 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3336 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3337 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3338 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003339 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003340 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003341 // Correct the timeout by elapsed time.
3342 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003343 if (newTimeOutNs < 0) newTimeOutNs = 0;
3344 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3345 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003346 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003347 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003348 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003349
3350stream_error:
3351 stream->standby();
3352 {
Andy Hung094dc762023-08-28 19:12:14 -07003353 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003354 mReadError = result;
3355 }
3356 mReadCV.notify_one();
3357 return result;
3358}
3359
Andy Hung3ff4b552023-06-26 19:20:57 -07003360void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003361{
3362 if (buffer->mFrameCount <= mUnconsumedFrames) {
3363 mUnconsumedFrames -= buffer->mFrameCount;
3364 } else {
3365 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3366 buffer->mFrameCount, mUnconsumedFrames);
3367 mUnconsumedFrames = 0;
3368 }
3369 PatchRecord::releaseBuffer(buffer);
3370}
3371
3372// AudioBufferProvider and Source methods are called on RecordThread
3373// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3374// and 'releaseBuffer' are stubbed out and ignore their input.
3375// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3376// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003377status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003378 void* buffer, size_t bytes, size_t* read)
3379{
3380 bytes = std::min(bytes, mFrameCount * mFrameSize);
3381 {
Andy Hung094dc762023-08-28 19:12:14 -07003382 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003383 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3384 if (mReadError != NO_ERROR) {
3385 mLastReadFrames = 0;
3386 return mReadError;
3387 }
3388 *read = std::min(bytes, mReadBytes);
3389 mReadBytes -= *read;
3390 }
3391 mLastReadFrames = *read / mFrameSize;
3392 memset(buffer, 0, *read);
3393 return 0;
3394}
3395
Andy Hung3ff4b552023-06-26 19:20:57 -07003396status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003397 int64_t* frames, int64_t* time)
3398{
Andy Hung44f27182023-07-06 20:56:16 -07003399 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003400 sp<StreamInHalInterface> stream = obtainStream(&thread);
3401 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3402}
3403
Andy Hung3ff4b552023-06-26 19:20:57 -07003404status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003405{
3406 // RecordThread issues 'standby' command in two major cases:
3407 // 1. Error on read--this case is handled in 'obtainBuffer'.
3408 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3409 // output, this can only happen when the software patch
3410 // is being torn down. In this case, the RecordThread
3411 // will terminate and close the HAL stream.
3412 return 0;
3413}
3414
3415// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003416status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003417 AudioBufferProvider::Buffer* buffer)
3418{
3419 buffer->frameCount = mLastReadFrames;
3420 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3421 return NO_ERROR;
3422}
3423
Andy Hung3ff4b552023-06-26 19:20:57 -07003424void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003425 AudioBufferProvider::Buffer* buffer)
3426{
3427 buffer->frameCount = 0;
3428 buffer->raw = nullptr;
3429}
3430
Andy Hung9d84af52018-09-12 18:03:44 -07003431// ----------------------------------------------------------------------------
3432#undef LOG_TAG
3433#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003434
Andy Hung3ff4b552023-06-26 19:20:57 -07003435/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003436sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003437 const audio_attributes_t& attr,
3438 uint32_t sampleRate,
3439 audio_format_t format,
3440 audio_channel_mask_t channelMask,
3441 audio_session_t sessionId,
3442 bool isOut,
3443 const android::content::AttributionSourceState& attributionSource,
3444 pid_t creatorPid,
3445 audio_port_handle_t portId)
3446{
3447 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003448 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003449 attr,
3450 sampleRate,
3451 format,
3452 channelMask,
3453 sessionId,
3454 isOut,
3455 attributionSource,
3456 creatorPid,
3457 portId);
3458}
3459
Andy Hung44f27182023-07-06 20:56:16 -07003460MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003461 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003462 uint32_t sampleRate,
3463 audio_format_t format,
3464 audio_channel_mask_t channelMask,
3465 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003466 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003467 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003468 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003469 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003470 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003471 channelMask, (size_t)0 /* frameCount */,
3472 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003473 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003474 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003475 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003476 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003477 TYPE_DEFAULT, portId,
3478 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003479 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003480 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003481{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003482 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003483 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003484}
3485
Andy Hung3ff4b552023-06-26 19:20:57 -07003486MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003487{
3488}
3489
Andy Hung3ff4b552023-06-26 19:20:57 -07003490status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003491{
3492 return NO_ERROR;
3493}
3494
Andy Hung3ff4b552023-06-26 19:20:57 -07003495status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003496 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003497{
3498 return NO_ERROR;
3499}
3500
Andy Hung3ff4b552023-06-26 19:20:57 -07003501void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003502{
3503}
3504
3505// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003506status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003507{
3508 buffer->frameCount = 0;
3509 buffer->raw = nullptr;
3510 return INVALID_OPERATION;
3511}
3512
3513// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003514size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003515 return 0;
3516}
3517
Andy Hung3ff4b552023-06-26 19:20:57 -07003518int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003519{
3520 return 0;
3521}
3522
Andy Hung3ff4b552023-06-26 19:20:57 -07003523void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003524{
3525}
3526
Andy Hung3ff4b552023-06-26 19:20:57 -07003527void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003528{
3529 if (mMuteState == muteState) {
3530 // mute state did not change, do nothing
3531 return;
3532 }
3533
3534 status_t result = UNKNOWN_ERROR;
3535 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3536 if (mMuteEventExtras == nullptr) {
3537 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3538 }
3539 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3540 static_cast<int>(muteState));
3541
3542 result = audioManager->portEvent(mPortId,
3543 PLAYER_UPDATE_MUTED,
3544 mMuteEventExtras);
3545 }
3546
3547 if (result == OK) {
3548 mMuteState = muteState;
3549 } else {
3550 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3551 __func__,
3552 id(),
3553 mPortId,
3554 result);
3555 }
3556}
3557
Andy Hung3ff4b552023-06-26 19:20:57 -07003558void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003559{
Eric Laurent973db022018-11-20 14:54:31 -08003560 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003561 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003562}
3563
Andy Hung3ff4b552023-06-26 19:20:57 -07003564void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003565{
Eric Laurent973db022018-11-20 14:54:31 -08003566 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003567 mPid,
3568 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003569 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003570 mFormat,
3571 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003572 mSampleRate,
3573 mAttr.flags);
3574 if (isOut()) {
3575 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3576 } else {
3577 result.appendFormat("%6x", mAttr.source);
3578 }
3579 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003580}
3581
Glenn Kasten63238ef2015-03-02 15:50:29 -08003582} // namespace android