blob: 224c65bb3a20a0c011d69c316d40825489ab73dc [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 }
1084 for (auto& teePatch : mTeePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001085 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001086 const size_t framesWritten = patchRecord->writeFrames(
1087 sourceBuffer.i8, frameCount, mFrameSize);
1088 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001089 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001090 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001091 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001092 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001093 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1094 using namespace std::chrono_literals;
1095 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001096 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001097 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001098}
1099
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001100// ExtendedAudioBufferProvider interface
1101
Andy Hung27876c02014-09-09 18:07:55 -07001102// framesReady() may return an approximation of the number of frames if called
1103// from a different thread than the one calling Proxy->obtainBuffer() and
1104// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1105// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001106size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001107 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1108 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1109 // The remainder of the buffer is not drained.
1110 return 0;
1111 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001112 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001113}
1114
Andy Hung3ff4b552023-06-26 19:20:57 -07001115int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001116{
1117 return mAudioTrackServerProxy->framesReleased();
1118}
1119
Andy Hung3ff4b552023-06-26 19:20:57 -07001120void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001121{
1122 // This call comes from a FastTrack and should be kept lockless.
1123 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001124 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001125
Andy Hung818e7a32016-02-16 18:08:07 -08001126 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001127
1128 // Compute latency.
1129 // TODO: Consider whether the server latency may be passed in by FastMixer
1130 // as a constant for all active FastTracks.
1131 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1132 mServerLatencyFromTrack.store(true);
1133 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001134}
1135
Eric Laurent81784c32012-11-19 14:55:58 -08001136// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001137bool Track::isReady() const {
1138 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001139 return true;
1140 }
1141
Eric Laurent16498512014-03-17 17:22:08 -07001142 if (isStopping()) {
1143 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001144 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001145 }
Eric Laurent81784c32012-11-19 14:55:58 -08001146 return true;
1147 }
1148
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001149 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001150 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1151 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1152 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1153 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001154
1155 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1156 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1157 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001158 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001159 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001160 return true;
1161 }
1162 return false;
1163}
1164
Andy Hung3ff4b552023-06-26 19:20:57 -07001165status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001166 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001167{
1168 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001169 ALOGV("%s(%d): calling pid %d session %d",
1170 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001171
Andy Hung44f27182023-07-06 20:56:16 -07001172 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001173 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001174 if (isOffloaded()) {
Andy Hung2ac52f12023-08-28 18:36:53 -07001175 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hung94dfbb42023-09-06 19:41:47 -07001176 const bool nonOffloadableGlobalEffectEnabled =
1177 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hung87e82412023-08-29 14:26:09 -07001178 audio_utils::lock_guard _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001179 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung94dfbb42023-09-06 19:41:47 -07001180 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001181 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001182 invalidate();
1183 return PERMISSION_DENIED;
1184 }
1185 }
Andy Hung87e82412023-08-29 14:26:09 -07001186 audio_utils::lock_guard _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001187 track_state state = mState;
1188 // here the track could be either new, or restarted
1189 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001190
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001191 // initial state-stopping. next state-pausing.
1192 // What if resume is called ?
1193
Zhou Song1ed46a22020-08-17 15:36:56 +08001194 if (state == FLUSHED) {
1195 // avoid underrun glitches when starting after flush
1196 reset();
1197 }
1198
kuowei.li576f1362021-05-11 18:02:32 +08001199 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1200 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001201 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001202 if (mResumeToStopping) {
1203 // happened we need to resume to STOPPING_1
1204 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001205 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1206 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001207 } else {
1208 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001209 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1210 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001211 }
Eric Laurent81784c32012-11-19 14:55:58 -08001212 } else {
1213 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001214 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1215 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001216 }
1217
Andy Hung44f27182023-07-06 20:56:16 -07001218 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001219
1220 // states to reset position info for pcm tracks
1221 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001222 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1223 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001224
1225 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1226 // Start point of track -> sink frame map. If the HAL returns a
1227 // frame position smaller than the first written frame in
1228 // updateTrackFrameInfo, the timestamp can be interpolated
1229 // instead of using a larger value.
1230 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1231 playbackThread->framesWritten());
1232 }
Andy Hunge10393e2015-06-12 13:59:33 -07001233 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001234 if (isFastTrack()) {
1235 // refresh fast track underruns on start because that field is never cleared
1236 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1237 // after stop.
1238 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1239 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001240 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001241 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001242 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001243 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001244 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001245 mState = state;
1246 }
1247 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001248
Andy Hungb68f5eb2019-12-03 16:49:17 -08001249 // Audio timing metrics are computed a few mix cycles after starting.
1250 {
1251 mLogStartCountdown = LOG_START_COUNTDOWN;
1252 mLogStartTimeNs = systemTime();
1253 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001254 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1255 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001256 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001257 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001258
Andy Hung1d3556d2018-03-29 16:30:14 -07001259 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1260 // for streaming tracks, remove the buffer read stop limit.
1261 mAudioTrackServerProxy->start();
1262 }
1263
Eric Laurentbfb1b832013-01-07 09:53:42 -08001264 // track was already in the active list, not a problem
1265 if (status == ALREADY_EXISTS) {
1266 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001267 } else {
1268 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1269 // It is usually unsafe to access the server proxy from a binder thread.
1270 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1271 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1272 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001273 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001274 ServerProxy::Buffer buffer;
1275 buffer.mFrameCount = 1;
1276 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001277 }
jiabin6e506fc2023-06-27 18:22:35 +00001278 if (status == NO_ERROR) {
1279 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
1280 }
Eric Laurent81784c32012-11-19 14:55:58 -08001281 } else {
1282 status = BAD_VALUE;
1283 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001284 if (status == NO_ERROR) {
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001285 // send format to AudioManager for playback activity monitoring
Andy Hung2cbc2722023-07-17 17:05:00 -07001286 const sp<IAudioManager> audioManager =
1287 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001288 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1289 std::unique_ptr<os::PersistableBundle> bundle =
1290 std::make_unique<os::PersistableBundle>();
1291 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1292 isSpatialized());
1293 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1294 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1295 status_t result = audioManager->portEvent(mPortId,
1296 PLAYER_UPDATE_FORMAT, bundle);
1297 if (result != OK) {
1298 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1299 __func__, mPortId, result);
1300 }
1301 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001302 }
Eric Laurent81784c32012-11-19 14:55:58 -08001303 return status;
1304}
1305
Andy Hung3ff4b552023-06-26 19:20:57 -07001306void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001307{
Andy Hungc0691382018-09-12 18:01:57 -07001308 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001309 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001310 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001311 audio_utils::lock_guard _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001312 track_state state = mState;
1313 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1314 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001315 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1316 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001317 reset();
1318 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001319 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001320 mState = STOPPED;
1321 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001322 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1323 // presentation is complete
1324 // For an offloaded track this starts a drain and state will
1325 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001326 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001327 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001328 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001329 }
Eric Laurent81784c32012-11-19 14:55:58 -08001330 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001331 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001332 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1333 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001334 }
jiabin6e506fc2023-06-27 18:22:35 +00001335 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001336 }
1337}
1338
Andy Hung3ff4b552023-06-26 19:20:57 -07001339void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001340{
Andy Hungc0691382018-09-12 18:01:57 -07001341 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001342 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001343 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001344 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001345 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001346 switch (mState) {
1347 case STOPPING_1:
1348 case STOPPING_2:
1349 if (!isOffloaded()) {
1350 /* nothing to do if track is not offloaded */
1351 break;
1352 }
1353
1354 // Offloaded track was draining, we need to carry on draining when resumed
1355 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001356 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001357 case ACTIVE:
1358 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001359 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001360 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1361 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001362 if (isOffloadedOrDirect()) {
1363 mPauseHwPending = true;
1364 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001365 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001366 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001367
Eric Laurentbfb1b832013-01-07 09:53:42 -08001368 default:
1369 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001370 }
jiabin6e506fc2023-06-27 18:22:35 +00001371 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1372 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001373 }
1374}
1375
Andy Hung3ff4b552023-06-26 19:20:57 -07001376void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001377{
Andy Hungc0691382018-09-12 18:01:57 -07001378 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001379 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001380 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001381 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001382 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001383
Phil Burk4bb650b2016-09-09 12:11:17 -07001384 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1385 // Otherwise the flush would not be done until the track is resumed.
1386 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001387 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001388 (void)mServerProxy->flushBufferIfNeeded();
1389 }
1390
Eric Laurentbfb1b832013-01-07 09:53:42 -08001391 if (isOffloaded()) {
1392 // If offloaded we allow flush during any state except terminated
1393 // and keep the track active to avoid problems if user is seeking
1394 // rapidly and underlying hardware has a significant delay handling
1395 // a pause
1396 if (isTerminated()) {
1397 return;
1398 }
1399
Andy Hung9d84af52018-09-12 18:03:44 -07001400 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001401 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001402
1403 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001404 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1405 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001406 mState = ACTIVE;
1407 }
1408
Haynes Mathew George7844f672014-01-15 12:32:55 -08001409 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001410 mResumeToStopping = false;
1411 } else {
1412 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1413 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1414 return;
1415 }
1416 // No point remaining in PAUSED state after a flush => go to
1417 // FLUSHED state
1418 mState = FLUSHED;
1419 // do not reset the track if it is still in the process of being stopped or paused.
1420 // this will be done by prepareTracks_l() when the track is stopped.
1421 // prepareTracks_l() will see mState == FLUSHED, then
1422 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001423 if (isDirect()) {
1424 mFlushHwPending = true;
1425 }
Andy Hung44f27182023-07-06 20:56:16 -07001426 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001427 reset();
1428 }
Eric Laurent81784c32012-11-19 14:55:58 -08001429 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001430 // Prevent flush being lost if the track is flushed and then resumed
1431 // before mixer thread can run. This is important when offloading
1432 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001433 playbackThread->broadcast_l();
jiabin6e506fc2023-06-27 18:22:35 +00001434 // Flush the Tee to avoid on resume playing old data and glitching on the transition to
1435 // new data
1436 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001437 }
1438}
1439
Haynes Mathew George7844f672014-01-15 12:32:55 -08001440// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001441void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001442{
Andy Hung71ba4b32022-10-06 12:09:49 -07001443 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001444 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001445 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001446
Phil Burk4bb650b2016-09-09 12:11:17 -07001447 // Clear the client ring buffer so that the app can prime the buffer while paused.
1448 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1449 mServerProxy->flushBufferIfNeeded();
1450
Haynes Mathew George7844f672014-01-15 12:32:55 -08001451 mFlushHwPending = false;
1452}
1453
Andy Hung3ff4b552023-06-26 19:20:57 -07001454void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001455{
1456 mPauseHwPending = false;
1457}
1458
Andy Hung3ff4b552023-06-26 19:20:57 -07001459void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001460{
1461 // Do not reset twice to avoid discarding data written just after a flush and before
1462 // the audioflinger thread detects the track is stopped.
1463 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001464 // Force underrun condition to avoid false underrun callback until first data is
1465 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001466 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001467 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001468 mResetDone = true;
1469 if (mState == FLUSHED) {
1470 mState = IDLE;
1471 }
1472 }
1473}
1474
Andy Hung3ff4b552023-06-26 19:20:57 -07001475status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001476{
Andy Hung44f27182023-07-06 20:56:16 -07001477 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001478 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001479 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001480 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001481 } else if (thread->type() == IAfThreadBase::DIRECT
1482 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001483 return thread->setParameters(keyValuePairs);
1484 } else {
1485 return PERMISSION_DENIED;
1486 }
1487}
1488
Andy Hung3ff4b552023-06-26 19:20:57 -07001489status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001490 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001491 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001492 if (thread == 0) {
1493 ALOGE("thread is dead");
1494 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001495 } else if (thread->type() == IAfThreadBase::DIRECT
1496 || thread->type() == IAfThreadBase::OFFLOAD) {
1497 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001498 return directOutputThread->selectPresentation(presentationId, programId);
1499 }
1500 return INVALID_OPERATION;
1501}
1502
Andy Hung3ff4b552023-06-26 19:20:57 -07001503VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001504 const sp<VolumeShaper::Configuration>& configuration,
1505 const sp<VolumeShaper::Operation>& operation)
1506{
Andy Hungee86cee2022-12-13 19:19:53 -08001507 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001508
1509 if (isOffloadedOrDirect()) {
1510 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001511 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001512 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001513 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001514 thread->broadcast_l();
1515 }
1516 }
1517 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001518}
1519
Andy Hung3ff4b552023-06-26 19:20:57 -07001520sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001521{
1522 // Note: We don't check if Thread exists.
1523
1524 // mVolumeHandler is thread safe.
1525 return mVolumeHandler->getVolumeShaperState(id);
1526}
1527
Andy Hung3ff4b552023-06-26 19:20:57 -07001528void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001529{
jiabin76d94692022-12-15 21:51:21 +00001530 mFinalVolumeLeft = volumeLeft;
1531 mFinalVolumeRight = volumeRight;
1532 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001533 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1534 mFinalVolume = volume;
1535 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001536 mLogForceVolumeUpdate = true;
1537 }
1538 if (mLogForceVolumeUpdate) {
1539 mLogForceVolumeUpdate = false;
1540 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001541 }
1542}
1543
Andy Hung3ff4b552023-06-26 19:20:57 -07001544void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001545{
Eric Laurent49e39282022-06-24 18:42:45 +02001546 // Do not forward metadata for PatchTrack with unspecified stream type
1547 if (mStreamType == AUDIO_STREAM_PATCH) {
1548 return;
1549 }
1550
Eric Laurent94579172020-11-20 18:41:04 +01001551 playback_track_metadata_v7_t metadata;
1552 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001553 .usage = mAttr.usage,
1554 .content_type = mAttr.content_type,
1555 .gain = mFinalVolume,
1556 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001557
1558 // When attributes are undefined, derive default values from stream type.
1559 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1560 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1561 switch (mStreamType) {
1562 case AUDIO_STREAM_VOICE_CALL:
1563 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1564 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1565 break;
1566 case AUDIO_STREAM_SYSTEM:
1567 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1568 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1569 break;
1570 case AUDIO_STREAM_RING:
1571 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1572 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1573 break;
1574 case AUDIO_STREAM_MUSIC:
1575 metadata.base.usage = AUDIO_USAGE_MEDIA;
1576 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1577 break;
1578 case AUDIO_STREAM_ALARM:
1579 metadata.base.usage = AUDIO_USAGE_ALARM;
1580 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1581 break;
1582 case AUDIO_STREAM_NOTIFICATION:
1583 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1584 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1585 break;
1586 case AUDIO_STREAM_DTMF:
1587 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1588 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1589 break;
1590 case AUDIO_STREAM_ACCESSIBILITY:
1591 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1592 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1593 break;
1594 case AUDIO_STREAM_ASSISTANT:
1595 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1596 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1597 break;
1598 case AUDIO_STREAM_REROUTING:
1599 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1600 // unknown content type
1601 break;
1602 case AUDIO_STREAM_CALL_ASSISTANT:
1603 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1604 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1605 break;
1606 default:
1607 break;
1608 }
1609 }
1610
Eric Laurent78b07302022-10-07 16:20:34 +02001611 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001612 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1613 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001614}
1615
jiabin6e506fc2023-06-27 18:22:35 +00001616void Track::updateTeePatches_l() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001617 if (mTeePatchesToUpdate.has_value()) {
jiabin6e506fc2023-06-27 18:22:35 +00001618 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001619 mTeePatches = mTeePatchesToUpdate.value();
1620 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1621 mState == TrackBase::STOPPING_1) {
jiabin6e506fc2023-06-27 18:22:35 +00001622 forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
Jiabin Huangfb476842022-12-06 03:18:10 +00001623 }
1624 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001625 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001626}
1627
jiabin6e506fc2023-06-27 18:22:35 +00001628void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001629 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1630 "%s, existing tee patches to update will be ignored", __func__);
1631 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1632}
1633
Vlad Popae8d99472022-06-30 16:02:48 +02001634// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001635void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001636 IAudioManager>& audioManager, mute_state_t muteState)
1637{
1638 if (mMuteState == muteState) {
1639 // mute state did not change, do nothing
1640 return;
1641 }
1642
1643 status_t result = UNKNOWN_ERROR;
1644 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1645 if (mMuteEventExtras == nullptr) {
1646 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1647 }
1648 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1649 static_cast<int>(muteState));
1650
1651 result = audioManager->portEvent(mPortId,
1652 PLAYER_UPDATE_MUTED,
1653 mMuteEventExtras);
1654 }
1655
1656 if (result == OK) {
1657 mMuteState = muteState;
1658 } else {
1659 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1660 __func__,
1661 id(),
1662 mPortId,
1663 result);
Andy Hung818e7a32016-02-16 18:08:07 -08001664 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001665}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001666
Andy Hung3ff4b552023-06-26 19:20:57 -07001667status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001668{
1669 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001670 return INVALID_OPERATION; // normal tracks handled through SSQ
1671 }
Andy Hung44f27182023-07-06 20:56:16 -07001672 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001673 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001674 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001675 }
Phil Burk6140c792015-03-19 14:30:21 -07001676
Andy Hung87e82412023-08-29 14:26:09 -07001677 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001678 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001679 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001680}
1681
Andy Hung3ff4b552023-06-26 19:20:57 -07001682status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001683{
Andy Hung44f27182023-07-06 20:56:16 -07001684 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001685 if (thread == nullptr) {
1686 return DEAD_OBJECT;
1687 }
Eric Laurent81784c32012-11-19 14:55:58 -08001688
Andy Hung44f27182023-07-06 20:56:16 -07001689 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001690 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001691 sp<IAfPlaybackThread> srcThread;
Andy Hungfa2f4f32023-07-17 12:40:43 -07001692 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001693 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001694
Eric Laurent6c796322019-04-09 14:13:17 -07001695 if (EffectId != 0 && status == NO_ERROR) {
1696 status = dstThread->attachAuxEffect(this, EffectId);
1697 if (status == NO_ERROR) {
1698 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001699 }
Eric Laurent6c796322019-04-09 14:13:17 -07001700 }
1701
1702 if (status != NO_ERROR && srcThread != nullptr) {
1703 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001704 }
1705 return status;
1706}
1707
Andy Hung3ff4b552023-06-26 19:20:57 -07001708void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001709{
1710 mAuxEffectId = EffectId;
1711 mAuxBuffer = buffer;
1712}
1713
Andy Hung59de4262021-06-14 10:53:54 -07001714// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001715bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001716 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001717{
Andy Hung818e7a32016-02-16 18:08:07 -08001718 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1719 // This assists in proper timestamp computation as well as wakelock management.
1720
Eric Laurent81784c32012-11-19 14:55:58 -08001721 // a track is considered presented when the total number of frames written to audio HAL
1722 // corresponds to the number of frames written when presentationComplete() is called for the
1723 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001724 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1725 // to detect when all frames have been played. In this case framesWritten isn't
1726 // useful because it doesn't always reflect whether there is data in the h/w
1727 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001728 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1729 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001730 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001731 if (mPresentationCompleteFrames == 0) {
1732 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001733 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001734 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1735 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001736 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001737 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001738
Andy Hungc54b1ff2016-02-23 14:07:07 -08001739 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001740 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001741 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001742 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1743 __func__, mId, (complete ? "complete" : "waiting"),
1744 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001745 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001746 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001747 && mAudioTrackServerProxy->isDrained();
1748 }
1749
1750 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001751 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001752 return true;
1753 }
1754 return false;
1755}
1756
Andy Hung59de4262021-06-14 10:53:54 -07001757// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001758bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001759{
1760 // For Offloaded or Direct tracks.
1761
1762 // For a direct track, we incorporated time based testing for presentationComplete.
1763
1764 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1765 // to detect when all frames have been played. In this case latencyMs isn't
1766 // useful because it doesn't always reflect whether there is data in the h/w
1767 // buffers, particularly if a track has been paused and resumed during draining
1768
1769 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1770 if (mPresentationCompleteTimeNs == 0) {
1771 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1772 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1773 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1774 }
1775
1776 bool complete;
1777 if (isOffloaded()) {
1778 complete = true;
1779 } else { // Direct
1780 complete = systemTime() >= mPresentationCompleteTimeNs;
1781 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1782 }
1783 if (complete) {
1784 notifyPresentationComplete();
1785 return true;
1786 }
1787 return false;
1788}
1789
Andy Hung3ff4b552023-06-26 19:20:57 -07001790void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001791{
1792 // This only triggers once. TODO: should we enforce this?
1793 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1794 mAudioTrackServerProxy->setStreamEndDone();
1795}
1796
Andy Hung3ff4b552023-06-26 19:20:57 -07001797void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001798{
Andy Hung068e08e2023-05-15 19:02:55 -07001799 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1800 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001801 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001802 (*it)->trigger();
1803 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001804 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001805 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001806 }
1807 }
1808}
1809
1810// implement VolumeBufferProvider interface
1811
Andy Hung3ff4b552023-06-26 19:20:57 -07001812gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001813{
1814 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1815 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001816 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1817 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1818 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001819 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001820 if (vl > GAIN_FLOAT_UNITY) {
1821 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001822 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001823 if (vr > GAIN_FLOAT_UNITY) {
1824 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001825 }
1826 // now apply the cached master volume and stream type volume;
1827 // this is trusted but lacks any synchronization or barrier so may be stale
1828 float v = mCachedVolume;
1829 vl *= v;
1830 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001831 // re-combine into packed minifloat
1832 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001833 // FIXME look at mute, pause, and stop flags
1834 return vlr;
1835}
1836
Andy Hung3ff4b552023-06-26 19:20:57 -07001837status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001838 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001839{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001840 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001841 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1842 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001843 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1844 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001845 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001846 event->cancel();
1847 return INVALID_OPERATION;
1848 }
1849 (void) TrackBase::setSyncEvent(event);
1850 return NO_ERROR;
1851}
1852
Andy Hung3ff4b552023-06-26 19:20:57 -07001853void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001854{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001855 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001856 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001857}
1858
Andy Hung3ff4b552023-06-26 19:20:57 -07001859void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001860{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001861 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001862 signalClientFlag(CBLK_DISABLED);
1863}
1864
Andy Hung3ff4b552023-06-26 19:20:57 -07001865void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001866{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001867 // FIXME should use proxy, and needs work
1868 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001869 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001870 android_atomic_release_store(0x40000000, &cblk->mFutex);
1871 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001872 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001873}
1874
Andy Hung3ff4b552023-06-26 19:20:57 -07001875void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001876{
Andy Hung44f27182023-07-06 20:56:16 -07001877 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001878 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001879 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001880 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001881 t->broadcast_l();
1882 }
1883}
1884
Andy Hung3ff4b552023-06-26 19:20:57 -07001885status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001886{
1887 status_t status = INVALID_OPERATION;
1888 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001889 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001890 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001891 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001892 audio_utils::lock_guard _l(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001893 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001894 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1895 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1896 }
1897 }
1898 return status;
1899}
1900
Andy Hung3ff4b552023-06-26 19:20:57 -07001901status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001902{
1903 status_t status = INVALID_OPERATION;
1904 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001905 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001906 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001907 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001908 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001909 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001910 if (status == NO_ERROR) {
1911 mDualMonoMode = mode;
1912 }
1913 }
1914 }
1915 return status;
1916}
1917
Andy Hung3ff4b552023-06-26 19:20:57 -07001918status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001919{
1920 status_t status = INVALID_OPERATION;
1921 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001922 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001923 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001924 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001925 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001926 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001927 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1928 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1929 }
1930 }
1931 return status;
1932}
1933
Andy Hung3ff4b552023-06-26 19:20:57 -07001934status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001935{
1936 status_t status = INVALID_OPERATION;
1937 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001938 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001939 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001940 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001941 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001942 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001943 if (status == NO_ERROR) {
1944 mAudioDescriptionMixLevel = leveldB;
1945 }
1946 }
1947 }
1948 return status;
1949}
1950
Andy Hung3ff4b552023-06-26 19:20:57 -07001951status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001952 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001953{
1954 status_t status = INVALID_OPERATION;
1955 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001956 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001957 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001958 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001959 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001960 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001961 ALOGD_IF((status == NO_ERROR) &&
1962 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1963 "%s: playbackRate inconsistent", __func__);
1964 }
1965 }
1966 return status;
1967}
1968
Andy Hung3ff4b552023-06-26 19:20:57 -07001969status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001970 const audio_playback_rate_t& playbackRate)
1971{
1972 status_t status = INVALID_OPERATION;
1973 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001974 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001975 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001976 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001977 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001978 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001979 if (status == NO_ERROR) {
1980 mPlaybackRateParameters = playbackRate;
1981 }
1982 }
1983 }
1984 return status;
1985}
1986
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001987//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001988bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07001989 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001990 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001991 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001992 /* Resume is pending if track was stopping before pause was called */
1993 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07001994 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001995 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001996 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001997
1998 return false;
1999}
2000
2001//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002002void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07002003 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002004 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07002005 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002006
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002007 // Other possibility of pending resume is stopping_1 state
2008 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002009 // drain being called.
2010 if (mState == STOPPING_1) {
2011 mResumeToStopping = false;
2012 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002013}
Andy Hunge10393e2015-06-12 13:59:33 -07002014
2015//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002016void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002017 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002018 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002019 // Make the kernel frametime available.
2020 const FrameTime ft{
2021 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2022 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2023 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2024 mKernelFrameTime.store(ft);
2025 if (!audio_is_linear_pcm(mFormat)) {
2026 return;
2027 }
2028
Andy Hung818e7a32016-02-16 18:08:07 -08002029 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002030 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002031
2032 // adjust server times and set drained state.
2033 //
2034 // Our timestamps are only updated when the track is on the Thread active list.
2035 // We need to ensure that tracks are not removed before full drain.
2036 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002037 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002038 bool checked = false;
2039 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2040 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2041 // Lookup the track frame corresponding to the sink frame position.
2042 if (local.mTimeNs[i] > 0) {
2043 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2044 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002045 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002046 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002047 checked = true;
2048 }
2049 }
Andy Hunge10393e2015-06-12 13:59:33 -07002050 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002051
Andy Hung93bb5732023-05-04 21:16:34 -07002052 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2053 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002054 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002055 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002056 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002057 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002058
2059 // Compute latency info.
2060 const bool useTrackTimestamp = !drained;
2061 const double latencyMs = useTrackTimestamp
2062 ? local.getOutputServerLatencyMs(sampleRate())
2063 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2064
2065 mServerLatencyFromTrack.store(useTrackTimestamp);
2066 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002067
Andy Hung62921122020-05-18 10:47:31 -07002068 if (mLogStartCountdown > 0
2069 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2070 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2071 {
2072 if (mLogStartCountdown > 1) {
2073 --mLogStartCountdown;
2074 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2075 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002076 // startup is the difference in times for the current timestamp and our start
2077 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002078 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002079 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002080 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2081 * 1e3 / mSampleRate;
2082 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2083 " localTime:%lld startTime:%lld"
2084 " localPosition:%lld startPosition:%lld",
2085 __func__, latencyMs, startUpMs,
2086 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002087 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002088 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002089 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002090 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002091 }
Andy Hung62921122020-05-18 10:47:31 -07002092 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002093 }
Andy Hunge10393e2015-06-12 13:59:33 -07002094}
2095
Andy Hung3ff4b552023-06-26 19:20:57 -07002096bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002097 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002098 if (thread != 0) {
2099 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87e82412023-08-29 14:26:09 -07002100 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002101 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002102 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002103 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002104 ALOGD("%s, haptic playback was %s for track %d",
2105 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002106 mTrack->setHapticPlaybackEnabled(!muted);
2107 return true;
jiabin57303cc2018-12-18 15:45:57 -08002108 }
2109 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002110 return false;
2111}
2112
Andy Hung3ff4b552023-06-26 19:20:57 -07002113binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002114 /*out*/ bool *ret) {
2115 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002116 return binder::Status::ok();
2117}
2118
Andy Hung3ff4b552023-06-26 19:20:57 -07002119binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002120 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002121 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002122 return binder::Status::ok();
2123}
2124
Eric Laurent81784c32012-11-19 14:55:58 -08002125// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002126#undef LOG_TAG
2127#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002128
Andy Hung3ff4b552023-06-26 19:20:57 -07002129/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002130sp<IAfOutputTrack> IAfOutputTrack::create(
2131 IAfPlaybackThread* playbackThread,
2132 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002133 uint32_t sampleRate,
2134 audio_format_t format,
2135 audio_channel_mask_t channelMask,
2136 size_t frameCount,
2137 const AttributionSourceState& attributionSource) {
2138 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002139 playbackThread,
2140 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002141 sampleRate,
2142 format,
2143 channelMask,
2144 frameCount,
2145 attributionSource);
2146}
2147
2148OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002149 IAfPlaybackThread* playbackThread,
2150 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002151 uint32_t sampleRate,
2152 audio_format_t format,
2153 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002154 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002155 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002156 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002157 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002158 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002159 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002160 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002161 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002162 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002163{
2164
2165 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002166 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002167 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002168 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002169 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002170 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002171 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002172 // since client and server are in the same process,
2173 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002174 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2175 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002176 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002177 mClientProxy->setSendLevel(0.0);
2178 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002179 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002180 ALOGW("%s(%d): Error creating output track on thread %d",
2181 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002182 }
2183}
2184
Andy Hung3ff4b552023-06-26 19:20:57 -07002185OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002186{
2187 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002188 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002189}
2190
Andy Hung3ff4b552023-06-26 19:20:57 -07002191status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002192 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002193{
2194 status_t status = Track::start(event, triggerSession);
2195 if (status != NO_ERROR) {
2196 return status;
2197 }
2198
2199 mActive = true;
2200 mRetryCount = 127;
2201 return status;
2202}
2203
Andy Hung3ff4b552023-06-26 19:20:57 -07002204void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002205{
2206 Track::stop();
2207 clearBufferQueue();
2208 mOutBuffer.frameCount = 0;
2209 mActive = false;
2210}
2211
Andy Hung3ff4b552023-06-26 19:20:57 -07002212ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002213{
Eric Laurent19952e12023-04-20 10:08:29 +02002214 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002215 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002216 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002217 // preload one silent buffer to trigger mixer on start()
2218 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2219 status_t status = mClientProxy->obtainBuffer(&buf);
2220 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2221 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2222 return 0;
2223 }
2224 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2225 mClientProxy->releaseBuffer(&buf);
2226
2227 (void) start();
2228
2229 // wait for HAL stream to start before sending actual audio. Doing this on each
2230 // OutputTrack makes that playback start on all output streams is synchronized.
2231 // If another OutputTrack has already started it can underrun but this is OK
2232 // as only silence has been played so far and the retry count is very high on
2233 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002234 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002235 if (!pt->waitForHalStart()) {
2236 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2237 stop();
2238 return 0;
2239 }
2240
2241 // enqueue the first buffer and exit so that other OutputTracks will also start before
2242 // write() is called again and this buffer actually consumed.
2243 Buffer firstBuffer;
2244 firstBuffer.frameCount = frames;
2245 firstBuffer.raw = data;
2246 queueBuffer(firstBuffer);
2247 return frames;
2248 } else {
2249 (void) start();
2250 }
2251 }
2252
Eric Laurent81784c32012-11-19 14:55:58 -08002253 Buffer *pInBuffer;
2254 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002255 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002256 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002257 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002258 while (waitTimeLeftMs) {
2259 // First write pending buffers, then new data
2260 if (mBufferQueue.size()) {
2261 pInBuffer = mBufferQueue.itemAt(0);
2262 } else {
2263 pInBuffer = &inBuffer;
2264 }
2265
2266 if (pInBuffer->frameCount == 0) {
2267 break;
2268 }
2269
2270 if (mOutBuffer.frameCount == 0) {
2271 mOutBuffer.frameCount = pInBuffer->frameCount;
2272 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002273 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002274 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002275 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2276 __func__, mId,
2277 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002278 break;
2279 }
2280 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2281 if (waitTimeLeftMs >= waitTimeMs) {
2282 waitTimeLeftMs -= waitTimeMs;
2283 } else {
2284 waitTimeLeftMs = 0;
2285 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002286 if (status == NOT_ENOUGH_DATA) {
2287 restartIfDisabled();
2288 continue;
2289 }
Eric Laurent81784c32012-11-19 14:55:58 -08002290 }
2291
2292 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2293 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002294 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002295 Proxy::Buffer buf;
2296 buf.mFrameCount = outFrames;
2297 buf.mRaw = NULL;
2298 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002299 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002300 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002301 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002302 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002303 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002304
2305 if (pInBuffer->frameCount == 0) {
2306 if (mBufferQueue.size()) {
2307 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002308 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002309 if (pInBuffer != &inBuffer) {
2310 delete pInBuffer;
2311 }
Andy Hung9d84af52018-09-12 18:03:44 -07002312 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2313 __func__, mId,
2314 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002315 } else {
2316 break;
2317 }
2318 }
2319 }
2320
2321 // If we could not write all frames, allocate a buffer and queue it for next time.
2322 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002323 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002324 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002325 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002326 }
2327 }
2328
Andy Hungc25b84a2015-01-14 19:04:10 -08002329 // Calling write() with a 0 length buffer means that no more data will be written:
2330 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2331 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2332 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002333 }
2334
Andy Hung1c86ebe2018-05-29 20:29:08 -07002335 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002336}
2337
Andy Hung3ff4b552023-06-26 19:20:57 -07002338void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002339
2340 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2341 Buffer *pInBuffer = new Buffer;
2342 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2343 pInBuffer->mBuffer = malloc(bufferSize);
2344 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2345 "%s: Unable to malloc size %zu", __func__, bufferSize);
2346 pInBuffer->frameCount = inBuffer.frameCount;
2347 pInBuffer->raw = pInBuffer->mBuffer;
2348 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2349 mBufferQueue.add(pInBuffer);
2350 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2351 (int)mThreadIoHandle, mBufferQueue.size());
2352 // audio data is consumed (stored locally); set frameCount to 0.
2353 inBuffer.frameCount = 0;
2354 } else {
2355 ALOGW("%s(%d): thread %d no more overflow buffers",
2356 __func__, mId, (int)mThreadIoHandle);
2357 // TODO: return error for this.
2358 }
2359}
2360
Andy Hung3ff4b552023-06-26 19:20:57 -07002361void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002362{
Andy Hung87e82412023-08-29 14:26:09 -07002363 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002364 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2365}
2366
Andy Hung3ff4b552023-06-26 19:20:57 -07002367void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002368 {
Andy Hung87e82412023-08-29 14:26:09 -07002369 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002370 mTrackMetadatas = metadatas;
2371 }
2372 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2373 setMetadataHasChanged();
2374}
2375
Andy Hung3ff4b552023-06-26 19:20:57 -07002376status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002377 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2378{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002379 ClientProxy::Buffer buf;
2380 buf.mFrameCount = buffer->frameCount;
2381 struct timespec timeout;
2382 timeout.tv_sec = waitTimeMs / 1000;
2383 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2384 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2385 buffer->frameCount = buf.mFrameCount;
2386 buffer->raw = buf.mRaw;
2387 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002388}
2389
Andy Hung3ff4b552023-06-26 19:20:57 -07002390void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002391{
2392 size_t size = mBufferQueue.size();
2393
2394 for (size_t i = 0; i < size; i++) {
2395 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002396 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002397 delete pBuffer;
2398 }
2399 mBufferQueue.clear();
2400}
2401
Andy Hung3ff4b552023-06-26 19:20:57 -07002402void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002403{
2404 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2405 if (mActive && (flags & CBLK_DISABLED)) {
2406 start();
2407 }
2408}
Eric Laurent81784c32012-11-19 14:55:58 -08002409
Andy Hung9d84af52018-09-12 18:03:44 -07002410// ----------------------------------------------------------------------------
2411#undef LOG_TAG
2412#define LOG_TAG "AF::PatchTrack"
2413
Andy Hung3ff4b552023-06-26 19:20:57 -07002414/* static */
2415sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002416 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002417 audio_stream_type_t streamType,
2418 uint32_t sampleRate,
2419 audio_channel_mask_t channelMask,
2420 audio_format_t format,
2421 size_t frameCount,
2422 void* buffer,
2423 size_t bufferSize,
2424 audio_output_flags_t flags,
2425 const Timeout& timeout,
2426 size_t frameCountToBeReady /** Default behaviour is to start
2427 * as soon as possible to have
2428 * the lowest possible latency
2429 * even if it might glitch. */)
2430{
2431 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002432 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002433 streamType,
2434 sampleRate,
2435 channelMask,
2436 format,
2437 frameCount,
2438 buffer,
2439 bufferSize,
2440 flags,
2441 timeout,
2442 frameCountToBeReady);
2443}
2444
Andy Hung44f27182023-07-06 20:56:16 -07002445PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002446 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002447 uint32_t sampleRate,
2448 audio_channel_mask_t channelMask,
2449 audio_format_t format,
2450 size_t frameCount,
2451 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002452 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002453 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002454 const Timeout& timeout,
2455 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002456 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002457 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002458 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002459 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002460 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002461 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002462 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2463 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07002464 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002465{
Andy Hung9d84af52018-09-12 18:03:44 -07002466 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2467 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002468 (int)mPeerTimeout.tv_sec,
2469 (int)(mPeerTimeout.tv_nsec / 1000000));
2470}
2471
Andy Hung3ff4b552023-06-26 19:20:57 -07002472PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002473{
Andy Hungabfab202019-03-07 19:45:54 -08002474 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002475}
2476
Andy Hung3ff4b552023-06-26 19:20:57 -07002477size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002478{
2479 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2480 return std::numeric_limits<size_t>::max();
2481 } else {
2482 return Track::framesReady();
2483 }
2484}
2485
Andy Hung3ff4b552023-06-26 19:20:57 -07002486status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002487 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002488{
2489 status_t status = Track::start(event, triggerSession);
2490 if (status != NO_ERROR) {
2491 return status;
2492 }
2493 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2494 return status;
2495}
2496
Eric Laurent83b88082014-06-20 18:31:16 -07002497// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002498status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002499 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002500{
Andy Hung9d84af52018-09-12 18:03:44 -07002501 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002502 Proxy::Buffer buf;
2503 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002504 if (ATRACE_ENABLED()) {
2505 std::string traceName("PTnReq");
2506 traceName += std::to_string(id());
2507 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2508 }
Eric Laurent83b88082014-06-20 18:31:16 -07002509 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002510 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002511 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002512 if (ATRACE_ENABLED()) {
2513 std::string traceName("PTnObt");
2514 traceName += std::to_string(id());
2515 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2516 }
Eric Laurent83b88082014-06-20 18:31:16 -07002517 if (buf.mFrameCount == 0) {
2518 return WOULD_BLOCK;
2519 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002520 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002521 return status;
2522}
2523
Andy Hung3ff4b552023-06-26 19:20:57 -07002524void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002525{
Andy Hung9d84af52018-09-12 18:03:44 -07002526 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002527 Proxy::Buffer buf;
2528 buf.mFrameCount = buffer->frameCount;
2529 buf.mRaw = buffer->raw;
2530 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002531 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002532}
2533
Andy Hung3ff4b552023-06-26 19:20:57 -07002534status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002535 const struct timespec *timeOut)
2536{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002537 status_t status = NO_ERROR;
2538 static const int32_t kMaxTries = 5;
2539 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002540 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002541 do {
2542 if (status == NOT_ENOUGH_DATA) {
2543 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002544 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002545 }
2546 status = mProxy->obtainBuffer(buffer, timeOut);
2547 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2548 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002549}
2550
Andy Hung3ff4b552023-06-26 19:20:57 -07002551void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002552{
2553 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002554 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002555
2556 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2557 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2558 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2559 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002560 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002561 && audio_is_linear_pcm(mFormat)
2562 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002563 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002564 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002565 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002566 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2567 / playbackThread->sampleRate();
2568 if (framesReady() < frameCount) {
2569 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002570 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002571 }
2572 }
2573 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002574}
2575
Andy Hung3ff4b552023-06-26 19:20:57 -07002576void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002577{
Eric Laurent83b88082014-06-20 18:31:16 -07002578 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002579 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002580 start();
2581 }
Eric Laurent83b88082014-06-20 18:31:16 -07002582}
2583
Eric Laurent81784c32012-11-19 14:55:58 -08002584// ----------------------------------------------------------------------------
2585// Record
2586// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002587
2588
Andy Hung9d84af52018-09-12 18:03:44 -07002589#undef LOG_TAG
2590#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002591
Andy Hungaaa18282023-06-23 19:27:19 -07002592class RecordHandle : public android::media::BnAudioRecord {
2593public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002594 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002595 ~RecordHandle() override;
2596 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2597 int /*audio_session_t*/ triggerSession) final;
2598 binder::Status stop() final;
2599 binder::Status getActiveMicrophones(
2600 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2601 binder::Status setPreferredMicrophoneDirection(
2602 int /*audio_microphone_direction_t*/ direction) final;
2603 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2604 binder::Status shareAudioHistory(
2605 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2606
2607private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002608 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002609
2610 // for use from destructor
2611 void stop_nonvirtual();
2612};
2613
2614/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002615sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2616 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002617 return sp<RecordHandle>::make(recordTrack);
2618}
2619
2620RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002621 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002622 : BnAudioRecord(),
2623 mRecordTrack(recordTrack)
2624{
Andy Hung225aef62022-12-06 16:33:20 -08002625 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002626}
2627
Andy Hungaaa18282023-06-23 19:27:19 -07002628RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002629 stop_nonvirtual();
2630 mRecordTrack->destroy();
2631}
2632
Andy Hungaaa18282023-06-23 19:27:19 -07002633binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002634 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002635 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002636 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002637 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002638}
2639
Andy Hungaaa18282023-06-23 19:27:19 -07002640binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002641 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002642 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002643}
2644
Andy Hungaaa18282023-06-23 19:27:19 -07002645void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002646 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002647 mRecordTrack->stop();
2648}
2649
Andy Hungaaa18282023-06-23 19:27:19 -07002650binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002651 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002652 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002653 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002654}
2655
Andy Hungaaa18282023-06-23 19:27:19 -07002656binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002657 int /*audio_microphone_direction_t*/ direction) {
2658 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002659 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002660 static_cast<audio_microphone_direction_t>(direction)));
2661}
2662
Andy Hungaaa18282023-06-23 19:27:19 -07002663binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002664 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002665 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002666}
2667
Andy Hungaaa18282023-06-23 19:27:19 -07002668binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002669 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2670 return binderStatusFromStatusT(
2671 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2672}
2673
Eric Laurent81784c32012-11-19 14:55:58 -08002674// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002675#undef LOG_TAG
2676#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002677
Andy Hung3ff4b552023-06-26 19:20:57 -07002678
Andy Hung56126702023-07-14 11:00:08 -07002679/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002680sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002681 const sp<Client>& client,
2682 const audio_attributes_t& attr,
2683 uint32_t sampleRate,
2684 audio_format_t format,
2685 audio_channel_mask_t channelMask,
2686 size_t frameCount,
2687 void* buffer,
2688 size_t bufferSize,
2689 audio_session_t sessionId,
2690 pid_t creatorPid,
2691 const AttributionSourceState& attributionSource,
2692 audio_input_flags_t flags,
2693 track_type type,
2694 audio_port_handle_t portId,
2695 int32_t startFrames)
2696{
2697 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002698 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002699 client,
2700 attr,
2701 sampleRate,
2702 format,
2703 channelMask,
2704 frameCount,
2705 buffer,
2706 bufferSize,
2707 sessionId,
2708 creatorPid,
2709 attributionSource,
2710 flags,
2711 type,
2712 portId,
2713 startFrames);
2714}
2715
Glenn Kasten05997e22014-03-13 15:08:33 -07002716// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002717RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002718 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002719 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002720 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002721 uint32_t sampleRate,
2722 audio_format_t format,
2723 audio_channel_mask_t channelMask,
2724 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002725 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002726 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002727 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002728 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002729 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002730 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002731 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002732 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002733 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002734 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002735 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002736 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002737 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002738 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002739 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002740 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002741 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002742 type, portId,
2743 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002744 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002745 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002746 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002747 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002748 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002749 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002750{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002751 if (mCblk == NULL) {
2752 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002753 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002754
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002755 if (!isDirect()) {
2756 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002757 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002758 channelMask, format, sampleRate);
2759 // Check if the RecordBufferConverter construction was successful.
2760 // If not, don't continue with construction.
2761 //
2762 // NOTE: It would be extremely rare that the record track cannot be created
2763 // for the current device, but a pending or future device change would make
2764 // the record track configuration valid.
2765 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002766 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002767 return;
2768 }
Andy Hung97a893e2015-03-29 01:03:07 -07002769 }
2770
Andy Hung6ae58432016-02-16 18:32:24 -08002771 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002772 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002773
Andy Hung97a893e2015-03-29 01:03:07 -07002774 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002775
Eric Laurent05067782016-06-01 18:27:28 -07002776 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002777 ALOG_ASSERT(thread->fastTrackAvailable());
2778 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002779 } else {
2780 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002781 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002782 }
Andy Hung8946a282018-04-19 20:04:56 -07002783#ifdef TEE_SINK
2784 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2785 + "_" + std::to_string(mId)
2786 + "_R");
2787#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002788
2789 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002790 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002791}
2792
Andy Hung3ff4b552023-06-26 19:20:57 -07002793RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002794{
Andy Hung9d84af52018-09-12 18:03:44 -07002795 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002796 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002797 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002798}
2799
Andy Hung3ff4b552023-06-26 19:20:57 -07002800status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002801{
2802 status_t status = TrackBase::initCheck();
2803 if (status == NO_ERROR && mServerProxy == 0) {
2804 status = BAD_VALUE;
2805 }
2806 return status;
2807}
2808
Eric Laurent81784c32012-11-19 14:55:58 -08002809// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002810status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002811{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002812 ServerProxy::Buffer buf;
2813 buf.mFrameCount = buffer->frameCount;
2814 status_t status = mServerProxy->obtainBuffer(&buf);
2815 buffer->frameCount = buf.mFrameCount;
2816 buffer->raw = buf.mRaw;
2817 if (buf.mFrameCount == 0) {
2818 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002819 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002820 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002821 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002822}
2823
Andy Hung3ff4b552023-06-26 19:20:57 -07002824status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002825 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002826{
Andy Hung44f27182023-07-06 20:56:16 -07002827 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002828 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002829 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002830 return recordThread->start(this, event, triggerSession);
2831 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002832 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2833 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002834 }
2835}
2836
Andy Hung3ff4b552023-06-26 19:20:57 -07002837void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002838{
Andy Hung44f27182023-07-06 20:56:16 -07002839 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002840 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002841 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002842 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002843 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002844 }
2845 }
2846}
2847
Andy Hung3ff4b552023-06-26 19:20:57 -07002848void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002849{
Andy Hung3ff4b552023-06-26 19:20:57 -07002850 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002851 sp<RecordTrack> keep(this);
2852 {
Andy Hungce685402018-10-05 17:23:27 -07002853 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002854 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002855 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07002856 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002857 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002858 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002859 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002860 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002861 }
Andy Hungce685402018-10-05 17:23:27 -07002862 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2863 }
2864 // APM portid/client management done outside of lock.
2865 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2866 if (isExternalTrack()) {
2867 switch (priorState) {
2868 case ACTIVE: // invalidated while still active
2869 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2870 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2871 AudioSystem::stopInput(mPortId);
2872 break;
2873
2874 case STARTING_1: // invalidated/start-aborted and startInput not successful
2875 case PAUSED: // OK, not active
2876 case IDLE: // OK, not active
2877 break;
2878
2879 case STOPPED: // unexpected (destroyed)
2880 default:
2881 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2882 }
2883 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002884 }
2885 }
2886}
2887
Andy Hung3ff4b552023-06-26 19:20:57 -07002888void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002889{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002890 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002891 // FIXME should use proxy, and needs work
2892 audio_track_cblk_t* cblk = mCblk;
2893 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2894 android_atomic_release_store(0x40000000, &cblk->mFutex);
2895 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002896 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002897}
2898
Eric Laurent81784c32012-11-19 14:55:58 -08002899
Andy Hung3ff4b552023-06-26 19:20:57 -07002900void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002901{
Eric Laurent973db022018-11-20 14:54:31 -08002902 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002903 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002904 " Server FrmCnt FrmRdy Sil%s\n",
2905 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002906}
2907
Andy Hung3ff4b552023-06-26 19:20:57 -07002908void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002909{
Eric Laurent973db022018-11-20 14:54:31 -08002910 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002911 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002912 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002913 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002914 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002915 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002916 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002917 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002918 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002919 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002920 mCblk->mFlags,
2921
Eric Laurent81784c32012-11-19 14:55:58 -08002922 mFormat,
2923 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002924 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002925 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002926
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002927 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002928 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002929 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002930 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002931 );
Andy Hung000adb52018-06-01 15:43:26 -07002932 if (isServerLatencySupported()) {
2933 double latencyMs;
2934 bool fromTrack;
2935 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2936 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2937 // or 'k' if estimated from kernel (usually for debugging).
2938 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2939 } else {
2940 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2941 }
2942 }
2943 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002944}
2945
Andy Hung93bb5732023-05-04 21:16:34 -07002946// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002947void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002948 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002949{
Andy Hung93bb5732023-05-04 21:16:34 -07002950 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002951 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002952 if (threadBase != 0) {
2953 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2954 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002955 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002956 }
Andy Hung93bb5732023-05-04 21:16:34 -07002957
2958 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002959}
2960
Andy Hung3ff4b552023-06-26 19:20:57 -07002961void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002962{
Andy Hung93bb5732023-05-04 21:16:34 -07002963 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002964}
2965
Andy Hung3ff4b552023-06-26 19:20:57 -07002966void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002967 int64_t trackFramesReleased, int64_t sourceFramesRead,
2968 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2969{
Andy Hung30282562018-08-08 18:27:03 -07002970 // Make the kernel frametime available.
2971 const FrameTime ft{
2972 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2973 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2974 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2975 mKernelFrameTime.store(ft);
2976 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002977 // Stream is direct, return provided timestamp with no conversion
2978 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002979 return;
2980 }
2981
Andy Hung3f0c9022016-01-15 17:49:46 -08002982 ExtendedTimestamp local = timestamp;
2983
2984 // Convert HAL frames to server-side track frames at track sample rate.
2985 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2986 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2987 if (local.mTimeNs[i] != 0) {
2988 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2989 const int64_t relativeTrackFrames = relativeServerFrames
2990 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2991 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2992 }
2993 }
Andy Hung6ae58432016-02-16 18:32:24 -08002994 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002995
2996 // Compute latency info.
2997 const bool useTrackTimestamp = true; // use track unless debugging.
2998 const double latencyMs = - (useTrackTimestamp
2999 ? local.getOutputServerLatencyMs(sampleRate())
3000 : timestamp.getOutputServerLatencyMs(halSampleRate));
3001
3002 mServerLatencyFromTrack.store(useTrackTimestamp);
3003 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003004}
Eric Laurent83b88082014-06-20 18:31:16 -07003005
Andy Hung3ff4b552023-06-26 19:20:57 -07003006status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003007 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003008{
Andy Hung44f27182023-07-06 20:56:16 -07003009 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003010 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003011 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003012 return recordThread->getActiveMicrophones(activeMicrophones);
3013 } else {
3014 return BAD_VALUE;
3015 }
3016}
3017
Andy Hung3ff4b552023-06-26 19:20:57 -07003018status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003019 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003020 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003021 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003022 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003023 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003024 } else {
3025 return BAD_VALUE;
3026 }
3027}
3028
Andy Hung3ff4b552023-06-26 19:20:57 -07003029status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003030 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003031 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003032 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003033 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003034 } else {
3035 return BAD_VALUE;
3036 }
3037}
3038
Andy Hung3ff4b552023-06-26 19:20:57 -07003039status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003040 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3041
3042 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3043 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3044 if (callingUid != mUid || callingPid != mCreatorPid) {
3045 return PERMISSION_DENIED;
3046 }
3047
Svet Ganov33761132021-05-13 22:51:08 +00003048 AttributionSourceState attributionSource{};
3049 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3050 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3051 attributionSource.token = sp<BBinder>::make();
3052 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003053 return PERMISSION_DENIED;
3054 }
3055
Andy Hung44f27182023-07-06 20:56:16 -07003056 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003057 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003058 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003059 status_t status = recordThread->shareAudioHistory(
3060 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3061 if (status == NO_ERROR) {
3062 mSharedAudioPackageName = sharedAudioPackageName;
3063 }
3064 return status;
3065 } else {
3066 return BAD_VALUE;
3067 }
3068}
3069
Andy Hung3ff4b552023-06-26 19:20:57 -07003070void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003071{
3072
3073 // Do not forward PatchRecord metadata with unspecified audio source
3074 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3075 return;
3076 }
3077
3078 // No track is invalid as this is called after prepareTrack_l in the same critical section
3079 record_track_metadata_v7_t metadata;
3080 metadata.base = {
3081 .source = mAttr.source,
3082 .gain = 1, // capture tracks do not have volumes
3083 };
3084 metadata.channel_mask = mChannelMask;
3085 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3086
3087 *backInserter++ = metadata;
3088}
Eric Laurentec376dc2021-04-08 20:41:22 +02003089
Andy Hung9d84af52018-09-12 18:03:44 -07003090// ----------------------------------------------------------------------------
3091#undef LOG_TAG
3092#define LOG_TAG "AF::PatchRecord"
3093
Andy Hung3ff4b552023-06-26 19:20:57 -07003094/* static */
3095sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003096 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003097 uint32_t sampleRate,
3098 audio_channel_mask_t channelMask,
3099 audio_format_t format,
3100 size_t frameCount,
3101 void *buffer,
3102 size_t bufferSize,
3103 audio_input_flags_t flags,
3104 const Timeout& timeout,
3105 audio_source_t source)
3106{
3107 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003108 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003109 sampleRate,
3110 channelMask,
3111 format,
3112 frameCount,
3113 buffer,
3114 bufferSize,
3115 flags,
3116 timeout,
3117 source);
3118}
3119
Andy Hung44f27182023-07-06 20:56:16 -07003120PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003121 uint32_t sampleRate,
3122 audio_channel_mask_t channelMask,
3123 audio_format_t format,
3124 size_t frameCount,
3125 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003126 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003127 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003128 const Timeout& timeout,
3129 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003130 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003131 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003132 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003133 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003134 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003135 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3136 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07003137 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003138{
Andy Hung9d84af52018-09-12 18:03:44 -07003139 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3140 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003141 (int)mPeerTimeout.tv_sec,
3142 (int)(mPeerTimeout.tv_nsec / 1000000));
3143}
3144
Andy Hung3ff4b552023-06-26 19:20:57 -07003145PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003146{
Andy Hungabfab202019-03-07 19:45:54 -08003147 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003148}
3149
Mikhail Naganov8296c252019-09-25 14:59:54 -07003150static size_t writeFramesHelper(
3151 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3152{
3153 AudioBufferProvider::Buffer patchBuffer;
3154 patchBuffer.frameCount = frameCount;
3155 auto status = dest->getNextBuffer(&patchBuffer);
3156 if (status != NO_ERROR) {
3157 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3158 __func__, status, strerror(-status));
3159 return 0;
3160 }
3161 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3162 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3163 size_t framesWritten = patchBuffer.frameCount;
3164 dest->releaseBuffer(&patchBuffer);
3165 return framesWritten;
3166}
3167
3168// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003169size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003170 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3171{
3172 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3173 // On buffer wrap, the buffer frame count will be less than requested,
3174 // when this happens a second buffer needs to be used to write the leftover audio
3175 const size_t framesLeft = frameCount - framesWritten;
3176 if (framesWritten != 0 && framesLeft != 0) {
3177 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3178 framesLeft, frameSize);
3179 }
3180 return framesWritten;
3181}
3182
Eric Laurent83b88082014-06-20 18:31:16 -07003183// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003184status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003185 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003186{
Andy Hung9d84af52018-09-12 18:03:44 -07003187 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003188 Proxy::Buffer buf;
3189 buf.mFrameCount = buffer->frameCount;
3190 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3191 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003192 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003193 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003194 if (ATRACE_ENABLED()) {
3195 std::string traceName("PRnObt");
3196 traceName += std::to_string(id());
3197 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3198 }
Eric Laurent83b88082014-06-20 18:31:16 -07003199 if (buf.mFrameCount == 0) {
3200 return WOULD_BLOCK;
3201 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003202 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003203 return status;
3204}
3205
Andy Hung3ff4b552023-06-26 19:20:57 -07003206void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003207{
Andy Hung9d84af52018-09-12 18:03:44 -07003208 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003209 Proxy::Buffer buf;
3210 buf.mFrameCount = buffer->frameCount;
3211 buf.mRaw = buffer->raw;
3212 mPeerProxy->releaseBuffer(&buf);
3213 TrackBase::releaseBuffer(buffer);
3214}
3215
Andy Hung3ff4b552023-06-26 19:20:57 -07003216status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003217 const struct timespec *timeOut)
3218{
3219 return mProxy->obtainBuffer(buffer, timeOut);
3220}
3221
Andy Hung3ff4b552023-06-26 19:20:57 -07003222void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003223{
3224 mProxy->releaseBuffer(buffer);
3225}
3226
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003227#undef LOG_TAG
3228#define LOG_TAG "AF::PthrPatchRecord"
3229
3230static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3231{
3232 void *ptr = nullptr;
3233 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003234 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003235}
3236
Andy Hung3ff4b552023-06-26 19:20:57 -07003237/* static */
3238sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003239 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003240 uint32_t sampleRate,
3241 audio_channel_mask_t channelMask,
3242 audio_format_t format,
3243 size_t frameCount,
3244 audio_input_flags_t flags,
3245 audio_source_t source)
3246{
3247 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003248 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003249 sampleRate,
3250 channelMask,
3251 format,
3252 frameCount,
3253 flags,
3254 source);
3255}
3256
3257PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003258 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003259 uint32_t sampleRate,
3260 audio_channel_mask_t channelMask,
3261 audio_format_t format,
3262 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003263 audio_input_flags_t flags,
3264 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003265 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003266 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003267 mPatchRecordAudioBufferProvider(*this),
3268 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3269 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3270{
3271 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3272}
3273
Andy Hung3ff4b552023-06-26 19:20:57 -07003274sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003275 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003276{
3277 *thread = mThread.promote();
3278 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003279 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07003280 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07003281 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003282}
3283
3284// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003285status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003286 Proxy::Buffer* buffer, const struct timespec* timeOut)
3287{
3288 if (mUnconsumedFrames) {
3289 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3290 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3291 return PatchRecord::obtainBuffer(buffer, timeOut);
3292 }
3293
3294 // Otherwise, execute a read from HAL and write into the buffer.
3295 nsecs_t startTimeNs = 0;
3296 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3297 // Will need to correct timeOut by elapsed time.
3298 startTimeNs = systemTime();
3299 }
3300 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3301 buffer->mFrameCount = 0;
3302 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003303 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003304 sp<StreamInHalInterface> stream = obtainStream(&thread);
3305 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3306
3307 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003308 size_t bytesRead = 0;
3309 {
3310 ATRACE_NAME("read");
3311 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3312 if (result != NO_ERROR) goto stream_error;
3313 if (bytesRead == 0) return NO_ERROR;
3314 }
3315
3316 {
Andy Hung094dc762023-08-28 19:12:14 -07003317 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003318 mReadBytes += bytesRead;
3319 mReadError = NO_ERROR;
3320 }
3321 mReadCV.notify_one();
3322 // writeFrames handles wraparound and should write all the provided frames.
3323 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3324 buffer->mFrameCount = writeFrames(
3325 &mPatchRecordAudioBufferProvider,
3326 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3327 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3328 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3329 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003330 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003331 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003332 // Correct the timeout by elapsed time.
3333 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003334 if (newTimeOutNs < 0) newTimeOutNs = 0;
3335 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3336 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003337 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003338 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003339 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003340
3341stream_error:
3342 stream->standby();
3343 {
Andy Hung094dc762023-08-28 19:12:14 -07003344 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003345 mReadError = result;
3346 }
3347 mReadCV.notify_one();
3348 return result;
3349}
3350
Andy Hung3ff4b552023-06-26 19:20:57 -07003351void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003352{
3353 if (buffer->mFrameCount <= mUnconsumedFrames) {
3354 mUnconsumedFrames -= buffer->mFrameCount;
3355 } else {
3356 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3357 buffer->mFrameCount, mUnconsumedFrames);
3358 mUnconsumedFrames = 0;
3359 }
3360 PatchRecord::releaseBuffer(buffer);
3361}
3362
3363// AudioBufferProvider and Source methods are called on RecordThread
3364// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3365// and 'releaseBuffer' are stubbed out and ignore their input.
3366// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3367// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003368status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003369 void* buffer, size_t bytes, size_t* read)
3370{
3371 bytes = std::min(bytes, mFrameCount * mFrameSize);
3372 {
Andy Hung094dc762023-08-28 19:12:14 -07003373 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003374 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3375 if (mReadError != NO_ERROR) {
3376 mLastReadFrames = 0;
3377 return mReadError;
3378 }
3379 *read = std::min(bytes, mReadBytes);
3380 mReadBytes -= *read;
3381 }
3382 mLastReadFrames = *read / mFrameSize;
3383 memset(buffer, 0, *read);
3384 return 0;
3385}
3386
Andy Hung3ff4b552023-06-26 19:20:57 -07003387status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003388 int64_t* frames, int64_t* time)
3389{
Andy Hung44f27182023-07-06 20:56:16 -07003390 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003391 sp<StreamInHalInterface> stream = obtainStream(&thread);
3392 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3393}
3394
Andy Hung3ff4b552023-06-26 19:20:57 -07003395status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003396{
3397 // RecordThread issues 'standby' command in two major cases:
3398 // 1. Error on read--this case is handled in 'obtainBuffer'.
3399 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3400 // output, this can only happen when the software patch
3401 // is being torn down. In this case, the RecordThread
3402 // will terminate and close the HAL stream.
3403 return 0;
3404}
3405
3406// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003407status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003408 AudioBufferProvider::Buffer* buffer)
3409{
3410 buffer->frameCount = mLastReadFrames;
3411 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3412 return NO_ERROR;
3413}
3414
Andy Hung3ff4b552023-06-26 19:20:57 -07003415void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003416 AudioBufferProvider::Buffer* buffer)
3417{
3418 buffer->frameCount = 0;
3419 buffer->raw = nullptr;
3420}
3421
Andy Hung9d84af52018-09-12 18:03:44 -07003422// ----------------------------------------------------------------------------
3423#undef LOG_TAG
3424#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003425
Andy Hung3ff4b552023-06-26 19:20:57 -07003426/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003427sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003428 const audio_attributes_t& attr,
3429 uint32_t sampleRate,
3430 audio_format_t format,
3431 audio_channel_mask_t channelMask,
3432 audio_session_t sessionId,
3433 bool isOut,
3434 const android::content::AttributionSourceState& attributionSource,
3435 pid_t creatorPid,
3436 audio_port_handle_t portId)
3437{
3438 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003439 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003440 attr,
3441 sampleRate,
3442 format,
3443 channelMask,
3444 sessionId,
3445 isOut,
3446 attributionSource,
3447 creatorPid,
3448 portId);
3449}
3450
Andy Hung44f27182023-07-06 20:56:16 -07003451MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003452 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003453 uint32_t sampleRate,
3454 audio_format_t format,
3455 audio_channel_mask_t channelMask,
3456 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003457 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003458 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003459 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003460 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003461 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003462 channelMask, (size_t)0 /* frameCount */,
3463 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003464 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003465 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003466 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003467 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003468 TYPE_DEFAULT, portId,
3469 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003470 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003471 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003472{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003473 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003474 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003475}
3476
Andy Hung3ff4b552023-06-26 19:20:57 -07003477MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003478{
3479}
3480
Andy Hung3ff4b552023-06-26 19:20:57 -07003481status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003482{
3483 return NO_ERROR;
3484}
3485
Andy Hung3ff4b552023-06-26 19:20:57 -07003486status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003487 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003488{
3489 return NO_ERROR;
3490}
3491
Andy Hung3ff4b552023-06-26 19:20:57 -07003492void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003493{
3494}
3495
3496// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003497status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003498{
3499 buffer->frameCount = 0;
3500 buffer->raw = nullptr;
3501 return INVALID_OPERATION;
3502}
3503
3504// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003505size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003506 return 0;
3507}
3508
Andy Hung3ff4b552023-06-26 19:20:57 -07003509int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003510{
3511 return 0;
3512}
3513
Andy Hung3ff4b552023-06-26 19:20:57 -07003514void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003515{
3516}
3517
Andy Hung3ff4b552023-06-26 19:20:57 -07003518void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003519{
3520 if (mMuteState == muteState) {
3521 // mute state did not change, do nothing
3522 return;
3523 }
3524
3525 status_t result = UNKNOWN_ERROR;
3526 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3527 if (mMuteEventExtras == nullptr) {
3528 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3529 }
3530 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3531 static_cast<int>(muteState));
3532
3533 result = audioManager->portEvent(mPortId,
3534 PLAYER_UPDATE_MUTED,
3535 mMuteEventExtras);
3536 }
3537
3538 if (result == OK) {
3539 mMuteState = muteState;
3540 } else {
3541 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3542 __func__,
3543 id(),
3544 mPortId,
3545 result);
3546 }
3547}
3548
Andy Hung3ff4b552023-06-26 19:20:57 -07003549void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003550{
Eric Laurent973db022018-11-20 14:54:31 -08003551 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003552 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003553}
3554
Andy Hung3ff4b552023-06-26 19:20:57 -07003555void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003556{
Eric Laurent973db022018-11-20 14:54:31 -08003557 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003558 mPid,
3559 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003560 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003561 mFormat,
3562 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003563 mSampleRate,
3564 mAttr.flags);
3565 if (isOut()) {
3566 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3567 } else {
3568 result.appendFormat("%6x", mAttr.source);
3569 }
3570 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003571}
3572
Glenn Kasten63238ef2015-03-02 15:50:29 -08003573} // namespace android