blob: 5f177cbfe6e7076fa8f88c3652397d0cc25eea38 [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)),
Phil Burkfdb3c072016-02-09 10:47:02 -0800116 mFrameSize(audio_has_proportional_frames(format) ?
Eric Laurent81784c32012-11-19 14:55:58 -0800117 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
118 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800119 mSessionId(sessionId),
120 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800121 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700122 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700123 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800124 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800125 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700126 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000127 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700128 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800129{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700130 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700131 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800132 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700133 "%s(%d): uid %d tried to pass itself off as %d",
134 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800135 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800136 }
137 // clientUid contains the uid of the app that is responsible for this track, so we can blame
138 // battery usage on it.
139 mUid = clientUid;
140
Eric Laurent81784c32012-11-19 14:55:58 -0800141 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800142
Andy Hung8fe68032017-06-05 16:17:51 -0700143 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800144 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700145 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800146 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700147 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800148 android_errorWriteLog(0x534e4554, "34749571");
149 return;
150 }
Andy Hung8fe68032017-06-05 16:17:51 -0700151 minBufferSize *= mFrameSize;
152
153 if (buffer == nullptr) {
154 bufferSize = minBufferSize; // allocated here.
155 } else if (minBufferSize > bufferSize) {
156 android_errorWriteLog(0x534e4554, "38340117");
157 return;
158 }
Andy Hung1883f692017-02-13 18:48:39 -0800159
Eric Laurent81784c32012-11-19 14:55:58 -0800160 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700161 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800162 // check overflow when computing allocation size for streaming tracks.
163 if (size > SIZE_MAX - bufferSize) {
164 android_errorWriteLog(0x534e4554, "34749571");
165 return;
166 }
Eric Laurent81784c32012-11-19 14:55:58 -0800167 size += bufferSize;
168 }
169
170 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400171 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
172 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700173 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700174 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700175 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400176 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700177 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800178 return;
179 }
180 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800181 mCblk = (audio_track_cblk_t *) malloc(size);
182 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700183 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800184 return;
185 }
Eric Laurent81784c32012-11-19 14:55:58 -0800186 }
187
188 // construct the shared structure in-place.
189 if (mCblk != NULL) {
190 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700191 switch (alloc) {
192 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700193 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
194 if (roHeap == 0 ||
195 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700196 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700197 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
198 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700199 if (roHeap != 0) {
200 roHeap->dump("buffer");
201 }
202 mCblkMemory.clear();
203 mBufferMemory.clear();
204 return;
205 }
Eric Laurent81784c32012-11-19 14:55:58 -0800206 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700207 } break;
208 case ALLOC_PIPE:
209 mBufferMemory = thread->pipeMemory();
210 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700211 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700212 // However in this case the TrackBase does not reference the buffer directly.
213 // It should references the buffer via the pipe.
214 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
215 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700216 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700217 break;
218 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700219 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700220 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700221 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
222 memset(mBuffer, 0, bufferSize);
223 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700224 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800225#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700226 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800227#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700228 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700229 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700230 case ALLOC_LOCAL:
231 mBuffer = calloc(1, bufferSize);
232 break;
233 case ALLOC_NONE:
234 mBuffer = buffer;
235 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700236 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700237 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800238 }
Andy Hung8fe68032017-06-05 16:17:51 -0700239 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800240
Glenn Kasten46909e72013-02-26 09:20:22 -0800241#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700242 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800243#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700244 // mState is mirrored for the client to read.
245 mState.setMirror(&mCblk->mState);
246 // ensure our state matches up until we consolidate the enumeration.
247 static_assert(CBLK_STATE_IDLE == IDLE);
248 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800249 }
250}
251
Svet Ganov33761132021-05-13 22:51:08 +0000252// TODO b/182392769: use attribution source util
253static AttributionSourceState audioServerAttributionSource(pid_t pid) {
254 AttributionSourceState attributionSource{};
255 attributionSource.uid = AID_AUDIOSERVER;
256 attributionSource.pid = pid;
257 attributionSource.token = sp<BBinder>::make();
258 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700259}
260
Andy Hung3ff4b552023-06-26 19:20:57 -0700261status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700262{
263 status_t status;
264 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
265 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
266 } else {
267 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
268 }
269 return status;
270}
271
Andy Hung3ff4b552023-06-26 19:20:57 -0700272TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800273{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800274 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700275 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700276 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800277 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
278 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700279 // Client destructor must run with AudioFlinger client mutex locked
Andy Hung2ac52f12023-08-28 18:36:53 -0700280 audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
Eric Laurent81784c32012-11-19 14:55:58 -0800281 // If the client's reference count drops to zero, the associated destructor
282 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
283 // relying on the automatic clear() at end of scope.
284 mClient.clear();
285 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700286 if (mAllocType == ALLOC_LOCAL) {
287 free(mBuffer);
288 mBuffer = nullptr;
289 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700290 // flush the binder command buffer
291 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800292}
293
294// AudioBufferProvider interface
295// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800296// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung3ff4b552023-06-26 19:20:57 -0700297void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800298{
Glenn Kasten46909e72013-02-26 09:20:22 -0800299#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700300 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800301#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800302
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800303 ServerProxy::Buffer buf;
304 buf.mFrameCount = buffer->frameCount;
305 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800306 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800307 buffer->raw = NULL;
308 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800309}
310
Andy Hung3ff4b552023-06-26 19:20:57 -0700311status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700312 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800313{
Andy Hung068e08e2023-05-15 19:02:55 -0700314 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800315 return NO_ERROR;
316}
317
Andy Hung3ff4b552023-06-26 19:20:57 -0700318PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung837229a2023-07-14 16:57:01 -0700319 IAfThreadBase* thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800320 : mProxy(proxy)
321{
322 if (timeout) {
323 setPeerTimeout(*timeout);
324 } else {
325 // Double buffer mixer
Andy Hung837229a2023-07-14 16:57:01 -0700326 uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
327 thread->sampleRate();
Kevin Rocard45986c72018-12-18 18:22:59 -0800328 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
329 }
330}
331
Andy Hung3ff4b552023-06-26 19:20:57 -0700332void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800333 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
334 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
335}
336
337
Eric Laurent81784c32012-11-19 14:55:58 -0800338// ----------------------------------------------------------------------------
339// Playback
340// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700341#undef LOG_TAG
342#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800343
Andy Hungaaa18282023-06-23 19:27:19 -0700344class TrackHandle : public android::media::BnAudioTrack {
345public:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700346 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hungaaa18282023-06-23 19:27:19 -0700347 ~TrackHandle() override;
348
349 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
350 binder::Status start(int32_t* _aidl_return) final;
351 binder::Status stop() final;
352 binder::Status flush() final;
353 binder::Status pause() final;
354 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
355 binder::Status setParameters(const std::string& keyValuePairs,
356 int32_t* _aidl_return) final;
357 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
358 int32_t* _aidl_return) final;
359 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
360 int32_t* _aidl_return) final;
361 binder::Status signal() final;
362 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
363 const media::VolumeShaperOperation& operation,
364 int32_t* _aidl_return) final;
365 binder::Status getVolumeShaperState(
366 int32_t id,
367 std::optional<media::VolumeShaperState>* _aidl_return) final;
368 binder::Status getDualMonoMode(
369 media::audio::common::AudioDualMonoMode* _aidl_return) final;
370 binder::Status setDualMonoMode(
371 media::audio::common::AudioDualMonoMode mode) final;
372 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
373 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
374 binder::Status getPlaybackRateParameters(
375 media::audio::common::AudioPlaybackRate* _aidl_return) final;
376 binder::Status setPlaybackRateParameters(
377 const media::audio::common::AudioPlaybackRate& playbackRate) final;
378
379private:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700380 const sp<IAfTrack> mTrack;
Andy Hungaaa18282023-06-23 19:27:19 -0700381};
382
383/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -0700384sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hungaaa18282023-06-23 19:27:19 -0700385 return sp<TrackHandle>::make(track);
386}
387
Andy Hung02a6c4e2023-06-23 19:27:19 -0700388TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800389 : BnAudioTrack(),
390 mTrack(track)
391{
Andy Hung225aef62022-12-06 16:33:20 -0800392 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800393}
394
Andy Hungaaa18282023-06-23 19:27:19 -0700395TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800396 // just stop the track on deletion, associated resources
397 // will be freed from the main thread once all pending buffers have
398 // been played. Unless it's not in the active track list, in which
399 // case we free everything now...
400 mTrack->destroy();
401}
402
Andy Hungaaa18282023-06-23 19:27:19 -0700403Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800404 std::optional<media::SharedFileRegion>* _aidl_return) {
405 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
406 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800407}
408
Andy Hungaaa18282023-06-23 19:27:19 -0700409Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800410 *_aidl_return = mTrack->start();
411 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800412}
413
Andy Hungaaa18282023-06-23 19:27:19 -0700414Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800415 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800416 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800417}
418
Andy Hungaaa18282023-06-23 19:27:19 -0700419Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800420 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800422}
423
Andy Hungaaa18282023-06-23 19:27:19 -0700424Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800425 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800426 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800427}
428
Andy Hungaaa18282023-06-23 19:27:19 -0700429Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800430 int32_t* _aidl_return) {
431 *_aidl_return = mTrack->attachAuxEffect(effectId);
432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hungaaa18282023-06-23 19:27:19 -0700435Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800436 int32_t* _aidl_return) {
437 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
438 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700439}
440
Andy Hungaaa18282023-06-23 19:27:19 -0700441Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800442 int32_t* _aidl_return) {
443 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
444 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800445}
446
Andy Hungaaa18282023-06-23 19:27:19 -0700447Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800448 int32_t* _aidl_return) {
449 AudioTimestamp legacy;
450 *_aidl_return = mTrack->getTimestamp(legacy);
451 if (*_aidl_return != OK) {
452 return Status::ok();
453 }
Andy Hung973638a2020-12-08 20:47:45 -0800454 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800455 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800456}
457
Andy Hungaaa18282023-06-23 19:27:19 -0700458Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 mTrack->signal();
460 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800461}
462
Andy Hungaaa18282023-06-23 19:27:19 -0700463Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800464 const media::VolumeShaperConfiguration& configuration,
465 const media::VolumeShaperOperation& operation,
466 int32_t* _aidl_return) {
467 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
468 *_aidl_return = conf->readFromParcelable(configuration);
469 if (*_aidl_return != OK) {
470 return Status::ok();
471 }
472
473 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
474 *_aidl_return = op->readFromParcelable(operation);
475 if (*_aidl_return != OK) {
476 return Status::ok();
477 }
478
479 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
480 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700481}
482
Andy Hungaaa18282023-06-23 19:27:19 -0700483Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800484 int32_t id,
485 std::optional<media::VolumeShaperState>* _aidl_return) {
486 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
487 if (legacy == nullptr) {
488 _aidl_return->reset();
489 return Status::ok();
490 }
491 media::VolumeShaperState aidl;
492 legacy->writeToParcelable(&aidl);
493 *_aidl_return = aidl;
494 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800495}
496
Andy Hungaaa18282023-06-23 19:27:19 -0700497Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000498 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800499{
500 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
501 const status_t status = mTrack->getDualMonoMode(&mode)
502 ?: AudioValidator::validateDualMonoMode(mode);
503 if (status == OK) {
504 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
505 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
506 }
507 return binderStatusFromStatusT(status);
508}
509
Andy Hungaaa18282023-06-23 19:27:19 -0700510Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000511 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800512{
513 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
514 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
515 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
516 ?: mTrack->setDualMonoMode(localMonoMode));
517}
518
Andy Hungaaa18282023-06-23 19:27:19 -0700519Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800520{
521 float leveldB = -std::numeric_limits<float>::infinity();
522 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
523 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
524 if (status == OK) *_aidl_return = leveldB;
525 return binderStatusFromStatusT(status);
526}
527
Andy Hungaaa18282023-06-23 19:27:19 -0700528Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800529{
530 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
531 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
532}
533
Andy Hungaaa18282023-06-23 19:27:19 -0700534Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000535 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800536{
537 audio_playback_rate_t localPlaybackRate{};
538 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
539 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
540 if (status == NO_ERROR) {
541 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
542 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
543 }
544 return binderStatusFromStatusT(status);
545}
546
Andy Hungaaa18282023-06-23 19:27:19 -0700547Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000548 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800549{
550 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
551 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
552 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
553 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
554}
555
Eric Laurent81784c32012-11-19 14:55:58 -0800556// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800557// AppOp for audio playback
558// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700559
560// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700561sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung44f27182023-07-06 20:56:16 -0700562 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000563 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700564 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800565{
Vlad Popa103be862023-07-10 20:27:41 -0700566 Vector<String16> packages;
567 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000568 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700569 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700570 if (packages.isEmpty()) {
571 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
572 id,
573 attr.usage,
574 uid);
575 return nullptr;
576 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800577 }
578 // stream type has been filtered by audio policy to indicate whether it can be muted
579 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700580 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700581 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800582 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700583 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
584 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
585 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
586 id, attr.flags);
587 return nullptr;
588 }
Vlad Popa103be862023-07-10 20:27:41 -0700589 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700590}
591
Andy Hung44f27182023-07-06 20:56:16 -0700592OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
593 const AttributionSourceState& attributionSource,
594 audio_usage_t usage, int id, uid_t uid)
595 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa103be862023-07-10 20:27:41 -0700596 mHasOpPlayAudio(true),
597 mAttributionSource(attributionSource),
598 mUsage((int32_t)usage),
599 mId(id),
600 mUid(uid),
601 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
602 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800603
Andy Hung3ff4b552023-06-26 19:20:57 -0700604OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800605{
606 if (mOpCallback != 0) {
607 mAppOpsManager.stopWatchingMode(mOpCallback);
608 }
609 mOpCallback.clear();
610}
611
Andy Hung3ff4b552023-06-26 19:20:57 -0700612void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700613{
Vlad Popad2152122023-08-02 18:36:04 -0700614 // make sure not to broadcast the initial state since it is not needed and could
615 // cause a deadlock since this method can be called with the mThread->mLock held
616 checkPlayAudioForUsage(/*doBroadcast=*/false);
Svet Ganov33761132021-05-13 22:51:08 +0000617 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700618 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700619 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Vlad Popa103be862023-07-10 20:27:41 -0700620 mPackageName, mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700621 }
622}
623
Andy Hung3ff4b552023-06-26 19:20:57 -0700624bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800625 return mHasOpPlayAudio.load();
626}
627
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700628// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800629// - not called from constructor due to check on UID,
630// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung3ff4b552023-06-26 19:20:57 -0700631void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800632{
Vlad Popa103be862023-07-10 20:27:41 -0700633 const bool hasAppOps = mAttributionSource.packageName.has_value()
634 && mAppOpsManager.checkAudioOpNoThrow(
635 AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
636 AppOpsManager::MODE_ALLOWED;
637
638 bool shouldChange = !hasAppOps; // check if we need to update.
639 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
640 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
Vlad Popad2152122023-08-02 18:36:04 -0700641 if (doBroadcast) {
642 auto thread = mThread.promote();
Andy Hung71742ab2023-07-07 13:47:37 -0700643 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popad2152122023-08-02 18:36:04 -0700644 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87e82412023-08-29 14:26:09 -0700645 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad2152122023-08-02 18:36:04 -0700646 thread->broadcast_l();
647 }
Vlad Popa103be862023-07-10 20:27:41 -0700648 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800649 }
650}
651
Andy Hung3ff4b552023-06-26 19:20:57 -0700652OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800653 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
654{ }
655
Andy Hung3ff4b552023-06-26 19:20:57 -0700656void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800657 const String16& packageName) {
658 // we only have uid, so we need to check all package names anyway
659 UNUSED(packageName);
660 if (op != AppOpsManager::OP_PLAY_AUDIO) {
661 return;
662 }
663 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
664 if (monitor != NULL) {
Vlad Popad2152122023-08-02 18:36:04 -0700665 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800666 }
667}
668
Eric Laurent9066ad32019-05-20 14:40:10 -0700669// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700670void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700671 uid_t uid, Vector<String16>& packages)
672{
673 PermissionController permissionController;
674 permissionController.getPackagesForUid(uid, packages);
675}
676
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800677// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700678#undef LOG_TAG
679#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800680
Andy Hung3ff4b552023-06-26 19:20:57 -0700681/* static */
Andy Hung44f27182023-07-06 20:56:16 -0700682sp<IAfTrack> IAfTrack::create(
683 IAfPlaybackThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700684 const sp<Client>& client,
685 audio_stream_type_t streamType,
686 const audio_attributes_t& attr,
687 uint32_t sampleRate,
688 audio_format_t format,
689 audio_channel_mask_t channelMask,
690 size_t frameCount,
691 void *buffer,
692 size_t bufferSize,
693 const sp<IMemory>& sharedBuffer,
694 audio_session_t sessionId,
695 pid_t creatorPid,
696 const AttributionSourceState& attributionSource,
697 audio_output_flags_t flags,
698 track_type type,
699 audio_port_handle_t portId,
700 /** default behaviour is to start when there are as many frames
701 * ready as possible (aka. Buffer is full). */
702 size_t frameCountToBeReady,
703 float speed,
704 bool isSpatialized,
705 bool isBitPerfect) {
Andy Hung44f27182023-07-06 20:56:16 -0700706 return sp<Track>::make(thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700707 client,
708 streamType,
709 attr,
710 sampleRate,
711 format,
712 channelMask,
713 frameCount,
714 buffer,
715 bufferSize,
716 sharedBuffer,
717 sessionId,
718 creatorPid,
719 attributionSource,
720 flags,
721 type,
722 portId,
723 frameCountToBeReady,
724 speed,
725 isSpatialized,
726 isBitPerfect);
727}
728
Eric Laurent81784c32012-11-19 14:55:58 -0800729// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -0700730Track::Track(
Andy Hung44f27182023-07-06 20:56:16 -0700731 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800732 const sp<Client>& client,
733 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700734 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800735 uint32_t sampleRate,
736 audio_format_t format,
737 audio_channel_mask_t channelMask,
738 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700739 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700740 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800741 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800742 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700743 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000744 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700745 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800746 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100747 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000748 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200749 float speed,
jiabinc658e452022-10-21 20:52:21 +0000750 bool isSpatialized,
751 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700752 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700753 // TODO: Using unsecurePointer() has some associated security pitfalls
754 // (see declaration for details).
755 // Either document why it is safe in this case or address the
756 // issue (e.g. by copying).
757 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700758 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700759 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000760 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700761 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800762 type,
763 portId,
764 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung3ff4b552023-06-26 19:20:57 -0700765 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800766 // mRetryCount initialized later when needed
767 mSharedBuffer(sharedBuffer),
768 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700769 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800770 mAuxBuffer(NULL),
771 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700772 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700773 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa103be862023-07-10 20:27:41 -0700774 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700775 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700776 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800777 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800778 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700779 /* The track might not play immediately after being active, similarly as if its volume was 0.
780 * When the track starts playing, its volume will be computed. */
781 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800782 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700783 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000784 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200785 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000786 mIsSpatialized(isSpatialized),
787 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800788{
Eric Laurent83b88082014-06-20 18:31:16 -0700789 // client == 0 implies sharedBuffer == 0
790 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
791
Andy Hung9d84af52018-09-12 18:03:44 -0700792 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700793 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700794
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700795 if (mCblk == NULL) {
796 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800797 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700798
Svet Ganov33761132021-05-13 22:51:08 +0000799 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700800 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
801 ALOGE("%s(%d): no more tracks available", __func__, mId);
802 releaseCblk(); // this makes the track invalid.
803 return;
804 }
805
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700806 if (sharedBuffer == 0) {
807 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700808 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700809 } else {
810 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100811 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700812 }
813 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700814 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700815
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700816 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700817 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700818 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
819 // race with setSyncEvent(). However, if we call it, we cannot properly start
820 // static fast tracks (SoundPool) immediately after stopping.
821 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung44f27182023-07-06 20:56:16 -0700822 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
823 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700824 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700825 // FIXME This is too eager. We allocate a fast track index before the
826 // fast track becomes active. Since fast tracks are a scarce resource,
827 // this means we are potentially denying other more important fast tracks from
828 // being created. It would be better to allocate the index dynamically.
829 mFastIndex = i;
Andy Hung44f27182023-07-06 20:56:16 -0700830 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700831 }
Andy Hung8946a282018-04-19 20:04:56 -0700832
Dean Wheatley7b036912020-06-18 16:22:11 +1000833 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700834#ifdef TEE_SINK
835 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800836 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700837#endif
jiabin57303cc2018-12-18 15:45:57 -0800838
jiabineb3bda02020-06-30 14:07:03 -0700839 if (thread->supportsHapticPlayback()) {
840 // If the track is attached to haptic playback thread, it is potentially to have
841 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
842 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800843 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000844 std::string packageName = attributionSource.packageName.has_value() ?
845 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800846 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700847 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800848 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800849
850 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700851 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800852 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800853}
854
Andy Hung3ff4b552023-06-26 19:20:57 -0700855Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800856{
Andy Hung9d84af52018-09-12 18:03:44 -0700857 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700858
859 // The destructor would clear mSharedBuffer,
860 // but it will not push the decremented reference count,
861 // leaving the client's IMemory dangling indefinitely.
862 // This prevents that leak.
863 if (mSharedBuffer != 0) {
864 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700865 }
Eric Laurent81784c32012-11-19 14:55:58 -0800866}
867
Andy Hung3ff4b552023-06-26 19:20:57 -0700868status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700869{
870 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700871 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700872 status = NO_MEMORY;
873 }
874 return status;
875}
876
Andy Hung3ff4b552023-06-26 19:20:57 -0700877void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800878{
879 // NOTE: destroyTrack_l() can remove a strong reference to this Track
880 // by removing it from mTracks vector, so there is a risk that this Tracks's
881 // destructor is called. As the destructor needs to lock mLock,
882 // we must acquire a strong reference on this Track before locking mLock
883 // here so that the destructor is called only when exiting this function.
884 // On the other hand, as long as Track::destroy() is only called by
885 // TrackHandle destructor, the TrackHandle still holds a strong ref on
886 // this Track with its member mTrack.
887 sp<Track> keep(this);
888 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700889 bool wasActive = false;
Andy Hung44f27182023-07-06 20:56:16 -0700890 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800891 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -0700892 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -0700893 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700894 wasActive = playbackThread->destroyTrack_l(this);
895 }
896 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700897 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800898 }
899 }
Kevin Rocardc43ea142019-01-31 18:17:37 -0800900 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
Eric Laurent81784c32012-11-19 14:55:58 -0800901}
902
Andy Hung3ff4b552023-06-26 19:20:57 -0700903void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800904{
Eric Laurent973db022018-11-20 14:54:31 -0800905 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700906 " Format Chn mask SRate "
907 "ST Usg CT "
908 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000909 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700910 "%s\n",
911 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800912}
913
Andy Hung3ff4b552023-06-26 19:20:57 -0700914void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800915{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700916 char trackType;
917 switch (mType) {
918 case TYPE_DEFAULT:
919 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700920 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700921 trackType = 'S'; // static
922 } else {
923 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800924 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700925 break;
926 case TYPE_PATCH:
927 trackType = 'P';
928 break;
929 default:
930 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800931 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700932
933 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700934 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700935 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700936 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700937 }
938
Eric Laurent81784c32012-11-19 14:55:58 -0800939 char nowInUnderrun;
940 switch (mObservedUnderruns.mBitFields.mMostRecent) {
941 case UNDERRUN_FULL:
942 nowInUnderrun = ' ';
943 break;
944 case UNDERRUN_PARTIAL:
945 nowInUnderrun = '<';
946 break;
947 case UNDERRUN_EMPTY:
948 nowInUnderrun = '*';
949 break;
950 default:
951 nowInUnderrun = '?';
952 break;
953 }
Andy Hungda540db2017-04-20 14:06:17 -0700954
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700955 char fillingStatus;
Andy Hung3ff4b552023-06-26 19:20:57 -0700956 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700957 case FS_INVALID:
958 fillingStatus = 'I';
959 break;
960 case FS_FILLING:
961 fillingStatus = 'f';
962 break;
963 case FS_FILLED:
964 fillingStatus = 'F';
965 break;
966 case FS_ACTIVE:
967 fillingStatus = 'A';
968 break;
969 default:
970 fillingStatus = '?';
971 break;
972 }
973
974 // clip framesReadySafe to max representation in dump
975 const size_t framesReadySafe =
976 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
977
978 // obtain volumes
979 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
980 const std::pair<float /* volume */, bool /* active */> vsVolume =
981 mVolumeHandler->getLastVolume();
982
983 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
984 // as it may be reduced by the application.
985 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
986 // Check whether the buffer size has been modified by the app.
987 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
988 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
989 ? 'e' /* error */ : ' ' /* identical */;
990
Eric Laurent973db022018-11-20 14:54:31 -0800991 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700992 "%08X %08X %6u "
993 "%2u %3x %2x "
994 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000995 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800996 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700997 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700998 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -0800999 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001000 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001001 mCblk->mFlags,
1002
Eric Laurent81784c32012-11-19 14:55:58 -08001003 mFormat,
1004 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001005 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001006
1007 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001008 mAttr.usage,
1009 mAttr.content_type,
1010
1011 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001012 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1013 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001014 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1015 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001016
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001017 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001018 bufferSizeInFrames,
1019 modifiedBufferChar,
1020 framesReadySafe,
1021 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001022 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001023 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001024 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1025 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001026 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001027
1028 if (isServerLatencySupported()) {
1029 double latencyMs;
1030 bool fromTrack;
1031 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1032 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1033 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1034 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001035 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001036 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001037 }
1038 }
1039 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001040}
1041
Andy Hung3ff4b552023-06-26 19:20:57 -07001042uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001043 return mAudioTrackServerProxy->getSampleRate();
1044}
1045
Eric Laurent81784c32012-11-19 14:55:58 -08001046// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001047status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001048{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001049 ServerProxy::Buffer buf;
1050 size_t desiredFrames = buffer->frameCount;
1051 buf.mFrameCount = desiredFrames;
1052 status_t status = mServerProxy->obtainBuffer(&buf);
1053 buffer->frameCount = buf.mFrameCount;
1054 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001055 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001056 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001057 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001058 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001059 } else {
1060 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001061 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001062 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001063}
1064
Andy Hung3ff4b552023-06-26 19:20:57 -07001065void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001066{
1067 interceptBuffer(*buffer);
1068 TrackBase::releaseBuffer(buffer);
1069}
1070
1071// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001072void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001073 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001074 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001075 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001076 if (frameCount == 0) {
1077 return; // No audio to intercept.
1078 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1079 // does not allow 0 frame size request contrary to getNextBuffer
1080 }
1081 for (auto& teePatch : mTeePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001082 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001083 const size_t framesWritten = patchRecord->writeFrames(
1084 sourceBuffer.i8, frameCount, mFrameSize);
1085 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001086 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001087 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001088 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001089 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001090 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1091 using namespace std::chrono_literals;
1092 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001093 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001094 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001095}
1096
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001097// ExtendedAudioBufferProvider interface
1098
Andy Hung27876c02014-09-09 18:07:55 -07001099// framesReady() may return an approximation of the number of frames if called
1100// from a different thread than the one calling Proxy->obtainBuffer() and
1101// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1102// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001103size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001104 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1105 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1106 // The remainder of the buffer is not drained.
1107 return 0;
1108 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001109 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001110}
1111
Andy Hung3ff4b552023-06-26 19:20:57 -07001112int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001113{
1114 return mAudioTrackServerProxy->framesReleased();
1115}
1116
Andy Hung3ff4b552023-06-26 19:20:57 -07001117void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001118{
1119 // This call comes from a FastTrack and should be kept lockless.
1120 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001121 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001122
Andy Hung818e7a32016-02-16 18:08:07 -08001123 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001124
1125 // Compute latency.
1126 // TODO: Consider whether the server latency may be passed in by FastMixer
1127 // as a constant for all active FastTracks.
1128 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1129 mServerLatencyFromTrack.store(true);
1130 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001131}
1132
Eric Laurent81784c32012-11-19 14:55:58 -08001133// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001134bool Track::isReady() const {
1135 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001136 return true;
1137 }
1138
Eric Laurent16498512014-03-17 17:22:08 -07001139 if (isStopping()) {
1140 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001141 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001142 }
Eric Laurent81784c32012-11-19 14:55:58 -08001143 return true;
1144 }
1145
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001146 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001147 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1148 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1149 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1150 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001151
1152 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1153 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1154 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001155 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001156 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001157 return true;
1158 }
1159 return false;
1160}
1161
Andy Hung3ff4b552023-06-26 19:20:57 -07001162status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001163 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001164{
1165 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001166 ALOGV("%s(%d): calling pid %d session %d",
1167 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001168
Andy Hung44f27182023-07-06 20:56:16 -07001169 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001170 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001171 if (isOffloaded()) {
Andy Hung2ac52f12023-08-28 18:36:53 -07001172 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hung94dfbb42023-09-06 19:41:47 -07001173 const bool nonOffloadableGlobalEffectEnabled =
1174 thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
Andy Hung87e82412023-08-29 14:26:09 -07001175 audio_utils::lock_guard _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001176 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung94dfbb42023-09-06 19:41:47 -07001177 if (nonOffloadableGlobalEffectEnabled ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001178 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001179 invalidate();
1180 return PERMISSION_DENIED;
1181 }
1182 }
Andy Hung87e82412023-08-29 14:26:09 -07001183 audio_utils::lock_guard _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001184 track_state state = mState;
1185 // here the track could be either new, or restarted
1186 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001187
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001188 // initial state-stopping. next state-pausing.
1189 // What if resume is called ?
1190
Zhou Song1ed46a22020-08-17 15:36:56 +08001191 if (state == FLUSHED) {
1192 // avoid underrun glitches when starting after flush
1193 reset();
1194 }
1195
kuowei.li576f1362021-05-11 18:02:32 +08001196 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1197 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001198 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001199 if (mResumeToStopping) {
1200 // happened we need to resume to STOPPING_1
1201 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001202 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1203 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001204 } else {
1205 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001206 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1207 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001208 }
Eric Laurent81784c32012-11-19 14:55:58 -08001209 } else {
1210 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001211 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1212 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001213 }
1214
Andy Hung44f27182023-07-06 20:56:16 -07001215 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001216
1217 // states to reset position info for pcm tracks
1218 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001219 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1220 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001221
1222 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1223 // Start point of track -> sink frame map. If the HAL returns a
1224 // frame position smaller than the first written frame in
1225 // updateTrackFrameInfo, the timestamp can be interpolated
1226 // instead of using a larger value.
1227 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1228 playbackThread->framesWritten());
1229 }
Andy Hunge10393e2015-06-12 13:59:33 -07001230 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001231 if (isFastTrack()) {
1232 // refresh fast track underruns on start because that field is never cleared
1233 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1234 // after stop.
1235 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1236 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001237 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001238 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001239 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001240 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001241 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001242 mState = state;
1243 }
1244 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001245
Andy Hungb68f5eb2019-12-03 16:49:17 -08001246 // Audio timing metrics are computed a few mix cycles after starting.
1247 {
1248 mLogStartCountdown = LOG_START_COUNTDOWN;
1249 mLogStartTimeNs = systemTime();
1250 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001251 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1252 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001253 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001254 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001255
Andy Hung1d3556d2018-03-29 16:30:14 -07001256 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1257 // for streaming tracks, remove the buffer read stop limit.
1258 mAudioTrackServerProxy->start();
1259 }
1260
Eric Laurentbfb1b832013-01-07 09:53:42 -08001261 // track was already in the active list, not a problem
1262 if (status == ALREADY_EXISTS) {
1263 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001264 } else {
1265 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1266 // It is usually unsafe to access the server proxy from a binder thread.
1267 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1268 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1269 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001270 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001271 ServerProxy::Buffer buffer;
1272 buffer.mFrameCount = 1;
1273 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001274 }
1275 } else {
1276 status = BAD_VALUE;
1277 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001278 if (status == NO_ERROR) {
1279 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001280
1281 // send format to AudioManager for playback activity monitoring
Andy Hung2cbc2722023-07-17 17:05:00 -07001282 const sp<IAudioManager> audioManager =
1283 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001284 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1285 std::unique_ptr<os::PersistableBundle> bundle =
1286 std::make_unique<os::PersistableBundle>();
1287 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1288 isSpatialized());
1289 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1290 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1291 status_t result = audioManager->portEvent(mPortId,
1292 PLAYER_UPDATE_FORMAT, bundle);
1293 if (result != OK) {
1294 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1295 __func__, mPortId, result);
1296 }
1297 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001298 }
Eric Laurent81784c32012-11-19 14:55:58 -08001299 return status;
1300}
1301
Andy Hung3ff4b552023-06-26 19:20:57 -07001302void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001303{
Andy Hungc0691382018-09-12 18:01:57 -07001304 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001305 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001306 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001307 audio_utils::lock_guard _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001308 track_state state = mState;
1309 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1310 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001311 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1312 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001313 reset();
1314 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001315 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001316 mState = STOPPED;
1317 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001318 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1319 // presentation is complete
1320 // For an offloaded track this starts a drain and state will
1321 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001322 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001323 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001324 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001325 }
Eric Laurent81784c32012-11-19 14:55:58 -08001326 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001327 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001328 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1329 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001330 }
Eric Laurent81784c32012-11-19 14:55:58 -08001331 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001332 forEachTeePatchTrack([](auto patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001333}
1334
Andy Hung3ff4b552023-06-26 19:20:57 -07001335void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001336{
Andy Hungc0691382018-09-12 18:01:57 -07001337 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001338 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001339 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001340 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001341 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001342 switch (mState) {
1343 case STOPPING_1:
1344 case STOPPING_2:
1345 if (!isOffloaded()) {
1346 /* nothing to do if track is not offloaded */
1347 break;
1348 }
1349
1350 // Offloaded track was draining, we need to carry on draining when resumed
1351 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001352 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001353 case ACTIVE:
1354 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001355 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001356 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1357 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001358 if (isOffloadedOrDirect()) {
1359 mPauseHwPending = true;
1360 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001361 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001362 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001363
Eric Laurentbfb1b832013-01-07 09:53:42 -08001364 default:
1365 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001366 }
1367 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001368 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1369 forEachTeePatchTrack([](auto patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001370}
1371
Andy Hung3ff4b552023-06-26 19:20:57 -07001372void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001373{
Andy Hungc0691382018-09-12 18:01:57 -07001374 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001375 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001376 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001377 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001378 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001379
Phil Burk4bb650b2016-09-09 12:11:17 -07001380 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1381 // Otherwise the flush would not be done until the track is resumed.
1382 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001383 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001384 (void)mServerProxy->flushBufferIfNeeded();
1385 }
1386
Eric Laurentbfb1b832013-01-07 09:53:42 -08001387 if (isOffloaded()) {
1388 // If offloaded we allow flush during any state except terminated
1389 // and keep the track active to avoid problems if user is seeking
1390 // rapidly and underlying hardware has a significant delay handling
1391 // a pause
1392 if (isTerminated()) {
1393 return;
1394 }
1395
Andy Hung9d84af52018-09-12 18:03:44 -07001396 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001397 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001398
1399 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001400 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1401 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001402 mState = ACTIVE;
1403 }
1404
Haynes Mathew George7844f672014-01-15 12:32:55 -08001405 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001406 mResumeToStopping = false;
1407 } else {
1408 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1409 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1410 return;
1411 }
1412 // No point remaining in PAUSED state after a flush => go to
1413 // FLUSHED state
1414 mState = FLUSHED;
1415 // do not reset the track if it is still in the process of being stopped or paused.
1416 // this will be done by prepareTracks_l() when the track is stopped.
1417 // prepareTracks_l() will see mState == FLUSHED, then
1418 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001419 if (isDirect()) {
1420 mFlushHwPending = true;
1421 }
Andy Hung44f27182023-07-06 20:56:16 -07001422 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001423 reset();
1424 }
Eric Laurent81784c32012-11-19 14:55:58 -08001425 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001426 // Prevent flush being lost if the track is flushed and then resumed
1427 // before mixer thread can run. This is important when offloading
1428 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001429 playbackThread->broadcast_l();
Eric Laurent81784c32012-11-19 14:55:58 -08001430 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001431 // Flush the Tee to avoid on resume playing old data and glitching on the transition to new data
1432 forEachTeePatchTrack([](auto patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001433}
1434
Haynes Mathew George7844f672014-01-15 12:32:55 -08001435// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001436void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001437{
Andy Hung71ba4b32022-10-06 12:09:49 -07001438 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001439 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001440 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001441
Phil Burk4bb650b2016-09-09 12:11:17 -07001442 // Clear the client ring buffer so that the app can prime the buffer while paused.
1443 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1444 mServerProxy->flushBufferIfNeeded();
1445
Haynes Mathew George7844f672014-01-15 12:32:55 -08001446 mFlushHwPending = false;
1447}
1448
Andy Hung3ff4b552023-06-26 19:20:57 -07001449void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001450{
1451 mPauseHwPending = false;
1452}
1453
Andy Hung3ff4b552023-06-26 19:20:57 -07001454void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001455{
1456 // Do not reset twice to avoid discarding data written just after a flush and before
1457 // the audioflinger thread detects the track is stopped.
1458 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001459 // Force underrun condition to avoid false underrun callback until first data is
1460 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001461 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001462 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001463 mResetDone = true;
1464 if (mState == FLUSHED) {
1465 mState = IDLE;
1466 }
1467 }
1468}
1469
Andy Hung3ff4b552023-06-26 19:20:57 -07001470status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001471{
Andy Hung44f27182023-07-06 20:56:16 -07001472 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001473 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001474 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001475 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001476 } else if (thread->type() == IAfThreadBase::DIRECT
1477 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001478 return thread->setParameters(keyValuePairs);
1479 } else {
1480 return PERMISSION_DENIED;
1481 }
1482}
1483
Andy Hung3ff4b552023-06-26 19:20:57 -07001484status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001485 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001486 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001487 if (thread == 0) {
1488 ALOGE("thread is dead");
1489 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001490 } else if (thread->type() == IAfThreadBase::DIRECT
1491 || thread->type() == IAfThreadBase::OFFLOAD) {
1492 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001493 return directOutputThread->selectPresentation(presentationId, programId);
1494 }
1495 return INVALID_OPERATION;
1496}
1497
Andy Hung3ff4b552023-06-26 19:20:57 -07001498VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001499 const sp<VolumeShaper::Configuration>& configuration,
1500 const sp<VolumeShaper::Operation>& operation)
1501{
Andy Hungee86cee2022-12-13 19:19:53 -08001502 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001503
1504 if (isOffloadedOrDirect()) {
1505 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001506 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001507 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001508 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001509 thread->broadcast_l();
1510 }
1511 }
1512 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001513}
1514
Andy Hung3ff4b552023-06-26 19:20:57 -07001515sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001516{
1517 // Note: We don't check if Thread exists.
1518
1519 // mVolumeHandler is thread safe.
1520 return mVolumeHandler->getVolumeShaperState(id);
1521}
1522
Andy Hung3ff4b552023-06-26 19:20:57 -07001523void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001524{
jiabin76d94692022-12-15 21:51:21 +00001525 mFinalVolumeLeft = volumeLeft;
1526 mFinalVolumeRight = volumeRight;
1527 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001528 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1529 mFinalVolume = volume;
1530 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001531 mLogForceVolumeUpdate = true;
1532 }
1533 if (mLogForceVolumeUpdate) {
1534 mLogForceVolumeUpdate = false;
1535 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001536 }
1537}
1538
Andy Hung3ff4b552023-06-26 19:20:57 -07001539void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001540{
Eric Laurent49e39282022-06-24 18:42:45 +02001541 // Do not forward metadata for PatchTrack with unspecified stream type
1542 if (mStreamType == AUDIO_STREAM_PATCH) {
1543 return;
1544 }
1545
Eric Laurent94579172020-11-20 18:41:04 +01001546 playback_track_metadata_v7_t metadata;
1547 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001548 .usage = mAttr.usage,
1549 .content_type = mAttr.content_type,
1550 .gain = mFinalVolume,
1551 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001552
1553 // When attributes are undefined, derive default values from stream type.
1554 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1555 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1556 switch (mStreamType) {
1557 case AUDIO_STREAM_VOICE_CALL:
1558 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1559 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1560 break;
1561 case AUDIO_STREAM_SYSTEM:
1562 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1563 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1564 break;
1565 case AUDIO_STREAM_RING:
1566 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1567 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1568 break;
1569 case AUDIO_STREAM_MUSIC:
1570 metadata.base.usage = AUDIO_USAGE_MEDIA;
1571 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1572 break;
1573 case AUDIO_STREAM_ALARM:
1574 metadata.base.usage = AUDIO_USAGE_ALARM;
1575 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1576 break;
1577 case AUDIO_STREAM_NOTIFICATION:
1578 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1579 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1580 break;
1581 case AUDIO_STREAM_DTMF:
1582 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1583 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1584 break;
1585 case AUDIO_STREAM_ACCESSIBILITY:
1586 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1587 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1588 break;
1589 case AUDIO_STREAM_ASSISTANT:
1590 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1591 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1592 break;
1593 case AUDIO_STREAM_REROUTING:
1594 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1595 // unknown content type
1596 break;
1597 case AUDIO_STREAM_CALL_ASSISTANT:
1598 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1599 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1600 break;
1601 default:
1602 break;
1603 }
1604 }
1605
Eric Laurent78b07302022-10-07 16:20:34 +02001606 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001607 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1608 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001609}
1610
Andy Hung3ff4b552023-06-26 19:20:57 -07001611void Track::updateTeePatches() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001612 if (mTeePatchesToUpdate.has_value()) {
1613 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
1614 mTeePatches = mTeePatchesToUpdate.value();
1615 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1616 mState == TrackBase::STOPPING_1) {
1617 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
1618 }
1619 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001620 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001621}
1622
Andy Hung34645da2023-07-14 11:45:38 -07001623void Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001624 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1625 "%s, existing tee patches to update will be ignored", __func__);
1626 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1627}
1628
Vlad Popae8d99472022-06-30 16:02:48 +02001629// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001630void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001631 IAudioManager>& audioManager, mute_state_t muteState)
1632{
1633 if (mMuteState == muteState) {
1634 // mute state did not change, do nothing
1635 return;
1636 }
1637
1638 status_t result = UNKNOWN_ERROR;
1639 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1640 if (mMuteEventExtras == nullptr) {
1641 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1642 }
1643 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1644 static_cast<int>(muteState));
1645
1646 result = audioManager->portEvent(mPortId,
1647 PLAYER_UPDATE_MUTED,
1648 mMuteEventExtras);
1649 }
1650
1651 if (result == OK) {
1652 mMuteState = muteState;
1653 } else {
1654 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1655 __func__,
1656 id(),
1657 mPortId,
1658 result);
Andy Hung818e7a32016-02-16 18:08:07 -08001659 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001660}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001661
Andy Hung3ff4b552023-06-26 19:20:57 -07001662status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001663{
1664 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001665 return INVALID_OPERATION; // normal tracks handled through SSQ
1666 }
Andy Hung44f27182023-07-06 20:56:16 -07001667 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001668 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001669 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001670 }
Phil Burk6140c792015-03-19 14:30:21 -07001671
Andy Hung87e82412023-08-29 14:26:09 -07001672 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001673 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001674 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001675}
1676
Andy Hung3ff4b552023-06-26 19:20:57 -07001677status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001678{
Andy Hung44f27182023-07-06 20:56:16 -07001679 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001680 if (thread == nullptr) {
1681 return DEAD_OBJECT;
1682 }
Eric Laurent81784c32012-11-19 14:55:58 -08001683
Andy Hung44f27182023-07-06 20:56:16 -07001684 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001685 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001686 sp<IAfPlaybackThread> srcThread;
Andy Hungfa2f4f32023-07-17 12:40:43 -07001687 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001688 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001689
Eric Laurent6c796322019-04-09 14:13:17 -07001690 if (EffectId != 0 && status == NO_ERROR) {
1691 status = dstThread->attachAuxEffect(this, EffectId);
1692 if (status == NO_ERROR) {
1693 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001694 }
Eric Laurent6c796322019-04-09 14:13:17 -07001695 }
1696
1697 if (status != NO_ERROR && srcThread != nullptr) {
1698 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001699 }
1700 return status;
1701}
1702
Andy Hung3ff4b552023-06-26 19:20:57 -07001703void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001704{
1705 mAuxEffectId = EffectId;
1706 mAuxBuffer = buffer;
1707}
1708
Andy Hung59de4262021-06-14 10:53:54 -07001709// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001710bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001711 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001712{
Andy Hung818e7a32016-02-16 18:08:07 -08001713 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1714 // This assists in proper timestamp computation as well as wakelock management.
1715
Eric Laurent81784c32012-11-19 14:55:58 -08001716 // a track is considered presented when the total number of frames written to audio HAL
1717 // corresponds to the number of frames written when presentationComplete() is called for the
1718 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001719 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1720 // to detect when all frames have been played. In this case framesWritten isn't
1721 // useful because it doesn't always reflect whether there is data in the h/w
1722 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001723 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1724 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001725 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001726 if (mPresentationCompleteFrames == 0) {
1727 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001728 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001729 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1730 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001731 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001732 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001733
Andy Hungc54b1ff2016-02-23 14:07:07 -08001734 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001735 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001736 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001737 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1738 __func__, mId, (complete ? "complete" : "waiting"),
1739 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001740 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001741 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001742 && mAudioTrackServerProxy->isDrained();
1743 }
1744
1745 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001746 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001747 return true;
1748 }
1749 return false;
1750}
1751
Andy Hung59de4262021-06-14 10:53:54 -07001752// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001753bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001754{
1755 // For Offloaded or Direct tracks.
1756
1757 // For a direct track, we incorporated time based testing for presentationComplete.
1758
1759 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1760 // to detect when all frames have been played. In this case latencyMs isn't
1761 // useful because it doesn't always reflect whether there is data in the h/w
1762 // buffers, particularly if a track has been paused and resumed during draining
1763
1764 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1765 if (mPresentationCompleteTimeNs == 0) {
1766 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1767 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1768 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1769 }
1770
1771 bool complete;
1772 if (isOffloaded()) {
1773 complete = true;
1774 } else { // Direct
1775 complete = systemTime() >= mPresentationCompleteTimeNs;
1776 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1777 }
1778 if (complete) {
1779 notifyPresentationComplete();
1780 return true;
1781 }
1782 return false;
1783}
1784
Andy Hung3ff4b552023-06-26 19:20:57 -07001785void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001786{
1787 // This only triggers once. TODO: should we enforce this?
1788 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1789 mAudioTrackServerProxy->setStreamEndDone();
1790}
1791
Andy Hung3ff4b552023-06-26 19:20:57 -07001792void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001793{
Andy Hung068e08e2023-05-15 19:02:55 -07001794 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1795 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001796 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001797 (*it)->trigger();
1798 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001799 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001800 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001801 }
1802 }
1803}
1804
1805// implement VolumeBufferProvider interface
1806
Andy Hung3ff4b552023-06-26 19:20:57 -07001807gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001808{
1809 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1810 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001811 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1812 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1813 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001814 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001815 if (vl > GAIN_FLOAT_UNITY) {
1816 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001817 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001818 if (vr > GAIN_FLOAT_UNITY) {
1819 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001820 }
1821 // now apply the cached master volume and stream type volume;
1822 // this is trusted but lacks any synchronization or barrier so may be stale
1823 float v = mCachedVolume;
1824 vl *= v;
1825 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001826 // re-combine into packed minifloat
1827 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001828 // FIXME look at mute, pause, and stop flags
1829 return vlr;
1830}
1831
Andy Hung3ff4b552023-06-26 19:20:57 -07001832status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001833 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001834{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001835 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001836 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1837 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001838 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1839 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001840 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001841 event->cancel();
1842 return INVALID_OPERATION;
1843 }
1844 (void) TrackBase::setSyncEvent(event);
1845 return NO_ERROR;
1846}
1847
Andy Hung3ff4b552023-06-26 19:20:57 -07001848void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001849{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001850 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001851 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001852}
1853
Andy Hung3ff4b552023-06-26 19:20:57 -07001854void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001855{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001856 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001857 signalClientFlag(CBLK_DISABLED);
1858}
1859
Andy Hung3ff4b552023-06-26 19:20:57 -07001860void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001861{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001862 // FIXME should use proxy, and needs work
1863 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001864 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001865 android_atomic_release_store(0x40000000, &cblk->mFutex);
1866 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001867 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001868}
1869
Andy Hung3ff4b552023-06-26 19:20:57 -07001870void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001871{
Andy Hung44f27182023-07-06 20:56:16 -07001872 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001873 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001874 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001875 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001876 t->broadcast_l();
1877 }
1878}
1879
Andy Hung3ff4b552023-06-26 19:20:57 -07001880status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001881{
1882 status_t status = INVALID_OPERATION;
1883 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001884 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001885 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001886 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001887 audio_utils::lock_guard _l(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001888 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001889 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1890 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1891 }
1892 }
1893 return status;
1894}
1895
Andy Hung3ff4b552023-06-26 19:20:57 -07001896status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001897{
1898 status_t status = INVALID_OPERATION;
1899 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001900 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001901 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001902 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001903 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001904 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001905 if (status == NO_ERROR) {
1906 mDualMonoMode = mode;
1907 }
1908 }
1909 }
1910 return status;
1911}
1912
Andy Hung3ff4b552023-06-26 19:20:57 -07001913status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001914{
1915 status_t status = INVALID_OPERATION;
1916 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001917 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001918 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001919 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001920 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001921 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001922 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1923 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1924 }
1925 }
1926 return status;
1927}
1928
Andy Hung3ff4b552023-06-26 19:20:57 -07001929status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001930{
1931 status_t status = INVALID_OPERATION;
1932 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001933 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001934 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001935 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001936 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001937 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001938 if (status == NO_ERROR) {
1939 mAudioDescriptionMixLevel = leveldB;
1940 }
1941 }
1942 }
1943 return status;
1944}
1945
Andy Hung3ff4b552023-06-26 19:20:57 -07001946status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001947 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001948{
1949 status_t status = INVALID_OPERATION;
1950 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001951 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001952 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001953 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001954 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001955 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001956 ALOGD_IF((status == NO_ERROR) &&
1957 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1958 "%s: playbackRate inconsistent", __func__);
1959 }
1960 }
1961 return status;
1962}
1963
Andy Hung3ff4b552023-06-26 19:20:57 -07001964status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001965 const audio_playback_rate_t& playbackRate)
1966{
1967 status_t status = INVALID_OPERATION;
1968 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001969 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001970 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001971 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001972 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001973 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001974 if (status == NO_ERROR) {
1975 mPlaybackRateParameters = playbackRate;
1976 }
1977 }
1978 }
1979 return status;
1980}
1981
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001982//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001983bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07001984 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001985 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001986 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001987 /* Resume is pending if track was stopping before pause was called */
1988 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07001989 mResumeToStopping) {
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
1993 return false;
1994}
1995
1996//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001997void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07001998 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001999 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07002000 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002001
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002002 // Other possibility of pending resume is stopping_1 state
2003 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002004 // drain being called.
2005 if (mState == STOPPING_1) {
2006 mResumeToStopping = false;
2007 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002008}
Andy Hunge10393e2015-06-12 13:59:33 -07002009
2010//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002011void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002012 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002013 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002014 // Make the kernel frametime available.
2015 const FrameTime ft{
2016 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2017 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2018 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2019 mKernelFrameTime.store(ft);
2020 if (!audio_is_linear_pcm(mFormat)) {
2021 return;
2022 }
2023
Andy Hung818e7a32016-02-16 18:08:07 -08002024 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002025 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002026
2027 // adjust server times and set drained state.
2028 //
2029 // Our timestamps are only updated when the track is on the Thread active list.
2030 // We need to ensure that tracks are not removed before full drain.
2031 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002032 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002033 bool checked = false;
2034 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2035 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2036 // Lookup the track frame corresponding to the sink frame position.
2037 if (local.mTimeNs[i] > 0) {
2038 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2039 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002040 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002041 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002042 checked = true;
2043 }
2044 }
Andy Hunge10393e2015-06-12 13:59:33 -07002045 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002046
Andy Hung93bb5732023-05-04 21:16:34 -07002047 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2048 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002049 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002050 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002051 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002052 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002053
2054 // Compute latency info.
2055 const bool useTrackTimestamp = !drained;
2056 const double latencyMs = useTrackTimestamp
2057 ? local.getOutputServerLatencyMs(sampleRate())
2058 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2059
2060 mServerLatencyFromTrack.store(useTrackTimestamp);
2061 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002062
Andy Hung62921122020-05-18 10:47:31 -07002063 if (mLogStartCountdown > 0
2064 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2065 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2066 {
2067 if (mLogStartCountdown > 1) {
2068 --mLogStartCountdown;
2069 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2070 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002071 // startup is the difference in times for the current timestamp and our start
2072 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002073 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002074 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002075 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2076 * 1e3 / mSampleRate;
2077 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2078 " localTime:%lld startTime:%lld"
2079 " localPosition:%lld startPosition:%lld",
2080 __func__, latencyMs, startUpMs,
2081 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002082 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002083 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002084 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002085 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002086 }
Andy Hung62921122020-05-18 10:47:31 -07002087 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002088 }
Andy Hunge10393e2015-06-12 13:59:33 -07002089}
2090
Andy Hung3ff4b552023-06-26 19:20:57 -07002091bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002092 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002093 if (thread != 0) {
2094 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87e82412023-08-29 14:26:09 -07002095 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002096 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002097 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002098 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002099 ALOGD("%s, haptic playback was %s for track %d",
2100 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002101 mTrack->setHapticPlaybackEnabled(!muted);
2102 return true;
jiabin57303cc2018-12-18 15:45:57 -08002103 }
2104 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002105 return false;
2106}
2107
Andy Hung3ff4b552023-06-26 19:20:57 -07002108binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002109 /*out*/ bool *ret) {
2110 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002111 return binder::Status::ok();
2112}
2113
Andy Hung3ff4b552023-06-26 19:20:57 -07002114binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002115 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002116 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002117 return binder::Status::ok();
2118}
2119
Eric Laurent81784c32012-11-19 14:55:58 -08002120// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002121#undef LOG_TAG
2122#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002123
Andy Hung3ff4b552023-06-26 19:20:57 -07002124/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002125sp<IAfOutputTrack> IAfOutputTrack::create(
2126 IAfPlaybackThread* playbackThread,
2127 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002128 uint32_t sampleRate,
2129 audio_format_t format,
2130 audio_channel_mask_t channelMask,
2131 size_t frameCount,
2132 const AttributionSourceState& attributionSource) {
2133 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002134 playbackThread,
2135 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002136 sampleRate,
2137 format,
2138 channelMask,
2139 frameCount,
2140 attributionSource);
2141}
2142
2143OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002144 IAfPlaybackThread* playbackThread,
2145 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002146 uint32_t sampleRate,
2147 audio_format_t format,
2148 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002149 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002150 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002151 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002152 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002153 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002154 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002155 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002156 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002157 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002158{
2159
2160 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002161 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002162 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002163 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002164 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002165 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002166 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002167 // since client and server are in the same process,
2168 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002169 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2170 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002171 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002172 mClientProxy->setSendLevel(0.0);
2173 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002174 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002175 ALOGW("%s(%d): Error creating output track on thread %d",
2176 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002177 }
2178}
2179
Andy Hung3ff4b552023-06-26 19:20:57 -07002180OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002181{
2182 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002183 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002184}
2185
Andy Hung3ff4b552023-06-26 19:20:57 -07002186status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002187 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002188{
2189 status_t status = Track::start(event, triggerSession);
2190 if (status != NO_ERROR) {
2191 return status;
2192 }
2193
2194 mActive = true;
2195 mRetryCount = 127;
2196 return status;
2197}
2198
Andy Hung3ff4b552023-06-26 19:20:57 -07002199void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002200{
2201 Track::stop();
2202 clearBufferQueue();
2203 mOutBuffer.frameCount = 0;
2204 mActive = false;
2205}
2206
Andy Hung3ff4b552023-06-26 19:20:57 -07002207ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002208{
Eric Laurent19952e12023-04-20 10:08:29 +02002209 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002210 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002211 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002212 // preload one silent buffer to trigger mixer on start()
2213 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2214 status_t status = mClientProxy->obtainBuffer(&buf);
2215 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2216 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2217 return 0;
2218 }
2219 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2220 mClientProxy->releaseBuffer(&buf);
2221
2222 (void) start();
2223
2224 // wait for HAL stream to start before sending actual audio. Doing this on each
2225 // OutputTrack makes that playback start on all output streams is synchronized.
2226 // If another OutputTrack has already started it can underrun but this is OK
2227 // as only silence has been played so far and the retry count is very high on
2228 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002229 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002230 if (!pt->waitForHalStart()) {
2231 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2232 stop();
2233 return 0;
2234 }
2235
2236 // enqueue the first buffer and exit so that other OutputTracks will also start before
2237 // write() is called again and this buffer actually consumed.
2238 Buffer firstBuffer;
2239 firstBuffer.frameCount = frames;
2240 firstBuffer.raw = data;
2241 queueBuffer(firstBuffer);
2242 return frames;
2243 } else {
2244 (void) start();
2245 }
2246 }
2247
Eric Laurent81784c32012-11-19 14:55:58 -08002248 Buffer *pInBuffer;
2249 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002250 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002251 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002252 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002253 while (waitTimeLeftMs) {
2254 // First write pending buffers, then new data
2255 if (mBufferQueue.size()) {
2256 pInBuffer = mBufferQueue.itemAt(0);
2257 } else {
2258 pInBuffer = &inBuffer;
2259 }
2260
2261 if (pInBuffer->frameCount == 0) {
2262 break;
2263 }
2264
2265 if (mOutBuffer.frameCount == 0) {
2266 mOutBuffer.frameCount = pInBuffer->frameCount;
2267 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002268 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002269 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002270 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2271 __func__, mId,
2272 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002273 break;
2274 }
2275 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2276 if (waitTimeLeftMs >= waitTimeMs) {
2277 waitTimeLeftMs -= waitTimeMs;
2278 } else {
2279 waitTimeLeftMs = 0;
2280 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002281 if (status == NOT_ENOUGH_DATA) {
2282 restartIfDisabled();
2283 continue;
2284 }
Eric Laurent81784c32012-11-19 14:55:58 -08002285 }
2286
2287 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2288 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002289 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002290 Proxy::Buffer buf;
2291 buf.mFrameCount = outFrames;
2292 buf.mRaw = NULL;
2293 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002294 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002295 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002296 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002297 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002298 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002299
2300 if (pInBuffer->frameCount == 0) {
2301 if (mBufferQueue.size()) {
2302 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002303 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002304 if (pInBuffer != &inBuffer) {
2305 delete pInBuffer;
2306 }
Andy Hung9d84af52018-09-12 18:03:44 -07002307 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2308 __func__, mId,
2309 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002310 } else {
2311 break;
2312 }
2313 }
2314 }
2315
2316 // If we could not write all frames, allocate a buffer and queue it for next time.
2317 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002318 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002319 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002320 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002321 }
2322 }
2323
Andy Hungc25b84a2015-01-14 19:04:10 -08002324 // Calling write() with a 0 length buffer means that no more data will be written:
2325 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2326 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2327 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002328 }
2329
Andy Hung1c86ebe2018-05-29 20:29:08 -07002330 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002331}
2332
Andy Hung3ff4b552023-06-26 19:20:57 -07002333void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002334
2335 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2336 Buffer *pInBuffer = new Buffer;
2337 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2338 pInBuffer->mBuffer = malloc(bufferSize);
2339 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2340 "%s: Unable to malloc size %zu", __func__, bufferSize);
2341 pInBuffer->frameCount = inBuffer.frameCount;
2342 pInBuffer->raw = pInBuffer->mBuffer;
2343 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2344 mBufferQueue.add(pInBuffer);
2345 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2346 (int)mThreadIoHandle, mBufferQueue.size());
2347 // audio data is consumed (stored locally); set frameCount to 0.
2348 inBuffer.frameCount = 0;
2349 } else {
2350 ALOGW("%s(%d): thread %d no more overflow buffers",
2351 __func__, mId, (int)mThreadIoHandle);
2352 // TODO: return error for this.
2353 }
2354}
2355
Andy Hung3ff4b552023-06-26 19:20:57 -07002356void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002357{
Andy Hung87e82412023-08-29 14:26:09 -07002358 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002359 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2360}
2361
Andy Hung3ff4b552023-06-26 19:20:57 -07002362void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002363 {
Andy Hung87e82412023-08-29 14:26:09 -07002364 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002365 mTrackMetadatas = metadatas;
2366 }
2367 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2368 setMetadataHasChanged();
2369}
2370
Andy Hung3ff4b552023-06-26 19:20:57 -07002371status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002372 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2373{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002374 ClientProxy::Buffer buf;
2375 buf.mFrameCount = buffer->frameCount;
2376 struct timespec timeout;
2377 timeout.tv_sec = waitTimeMs / 1000;
2378 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2379 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2380 buffer->frameCount = buf.mFrameCount;
2381 buffer->raw = buf.mRaw;
2382 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002383}
2384
Andy Hung3ff4b552023-06-26 19:20:57 -07002385void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002386{
2387 size_t size = mBufferQueue.size();
2388
2389 for (size_t i = 0; i < size; i++) {
2390 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002391 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002392 delete pBuffer;
2393 }
2394 mBufferQueue.clear();
2395}
2396
Andy Hung3ff4b552023-06-26 19:20:57 -07002397void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002398{
2399 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2400 if (mActive && (flags & CBLK_DISABLED)) {
2401 start();
2402 }
2403}
Eric Laurent81784c32012-11-19 14:55:58 -08002404
Andy Hung9d84af52018-09-12 18:03:44 -07002405// ----------------------------------------------------------------------------
2406#undef LOG_TAG
2407#define LOG_TAG "AF::PatchTrack"
2408
Andy Hung3ff4b552023-06-26 19:20:57 -07002409/* static */
2410sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002411 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002412 audio_stream_type_t streamType,
2413 uint32_t sampleRate,
2414 audio_channel_mask_t channelMask,
2415 audio_format_t format,
2416 size_t frameCount,
2417 void* buffer,
2418 size_t bufferSize,
2419 audio_output_flags_t flags,
2420 const Timeout& timeout,
2421 size_t frameCountToBeReady /** Default behaviour is to start
2422 * as soon as possible to have
2423 * the lowest possible latency
2424 * even if it might glitch. */)
2425{
2426 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002427 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002428 streamType,
2429 sampleRate,
2430 channelMask,
2431 format,
2432 frameCount,
2433 buffer,
2434 bufferSize,
2435 flags,
2436 timeout,
2437 frameCountToBeReady);
2438}
2439
Andy Hung44f27182023-07-06 20:56:16 -07002440PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002441 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002442 uint32_t sampleRate,
2443 audio_channel_mask_t channelMask,
2444 audio_format_t format,
2445 size_t frameCount,
2446 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002447 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002448 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002449 const Timeout& timeout,
2450 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002451 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002452 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002453 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002454 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002455 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002456 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002457 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2458 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07002459 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002460{
Andy Hung9d84af52018-09-12 18:03:44 -07002461 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2462 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002463 (int)mPeerTimeout.tv_sec,
2464 (int)(mPeerTimeout.tv_nsec / 1000000));
2465}
2466
Andy Hung3ff4b552023-06-26 19:20:57 -07002467PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002468{
Andy Hungabfab202019-03-07 19:45:54 -08002469 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002470}
2471
Andy Hung3ff4b552023-06-26 19:20:57 -07002472size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002473{
2474 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2475 return std::numeric_limits<size_t>::max();
2476 } else {
2477 return Track::framesReady();
2478 }
2479}
2480
Andy Hung3ff4b552023-06-26 19:20:57 -07002481status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002482 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002483{
2484 status_t status = Track::start(event, triggerSession);
2485 if (status != NO_ERROR) {
2486 return status;
2487 }
2488 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2489 return status;
2490}
2491
Eric Laurent83b88082014-06-20 18:31:16 -07002492// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002493status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002494 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002495{
Andy Hung9d84af52018-09-12 18:03:44 -07002496 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002497 Proxy::Buffer buf;
2498 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002499 if (ATRACE_ENABLED()) {
2500 std::string traceName("PTnReq");
2501 traceName += std::to_string(id());
2502 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2503 }
Eric Laurent83b88082014-06-20 18:31:16 -07002504 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002505 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002506 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002507 if (ATRACE_ENABLED()) {
2508 std::string traceName("PTnObt");
2509 traceName += std::to_string(id());
2510 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2511 }
Eric Laurent83b88082014-06-20 18:31:16 -07002512 if (buf.mFrameCount == 0) {
2513 return WOULD_BLOCK;
2514 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002515 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002516 return status;
2517}
2518
Andy Hung3ff4b552023-06-26 19:20:57 -07002519void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002520{
Andy Hung9d84af52018-09-12 18:03:44 -07002521 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002522 Proxy::Buffer buf;
2523 buf.mFrameCount = buffer->frameCount;
2524 buf.mRaw = buffer->raw;
2525 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002526 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002527}
2528
Andy Hung3ff4b552023-06-26 19:20:57 -07002529status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002530 const struct timespec *timeOut)
2531{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002532 status_t status = NO_ERROR;
2533 static const int32_t kMaxTries = 5;
2534 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002535 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002536 do {
2537 if (status == NOT_ENOUGH_DATA) {
2538 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002539 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002540 }
2541 status = mProxy->obtainBuffer(buffer, timeOut);
2542 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2543 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002544}
2545
Andy Hung3ff4b552023-06-26 19:20:57 -07002546void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002547{
2548 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002549 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002550
2551 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2552 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2553 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2554 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002555 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002556 && audio_is_linear_pcm(mFormat)
2557 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002558 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002559 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002560 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002561 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2562 / playbackThread->sampleRate();
2563 if (framesReady() < frameCount) {
2564 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002565 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002566 }
2567 }
2568 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002569}
2570
Andy Hung3ff4b552023-06-26 19:20:57 -07002571void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002572{
Eric Laurent83b88082014-06-20 18:31:16 -07002573 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002574 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002575 start();
2576 }
Eric Laurent83b88082014-06-20 18:31:16 -07002577}
2578
Eric Laurent81784c32012-11-19 14:55:58 -08002579// ----------------------------------------------------------------------------
2580// Record
2581// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002582
2583
Andy Hung9d84af52018-09-12 18:03:44 -07002584#undef LOG_TAG
2585#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002586
Andy Hungaaa18282023-06-23 19:27:19 -07002587class RecordHandle : public android::media::BnAudioRecord {
2588public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002589 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002590 ~RecordHandle() override;
2591 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2592 int /*audio_session_t*/ triggerSession) final;
2593 binder::Status stop() final;
2594 binder::Status getActiveMicrophones(
2595 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2596 binder::Status setPreferredMicrophoneDirection(
2597 int /*audio_microphone_direction_t*/ direction) final;
2598 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2599 binder::Status shareAudioHistory(
2600 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2601
2602private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002603 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002604
2605 // for use from destructor
2606 void stop_nonvirtual();
2607};
2608
2609/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002610sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2611 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002612 return sp<RecordHandle>::make(recordTrack);
2613}
2614
2615RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002616 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002617 : BnAudioRecord(),
2618 mRecordTrack(recordTrack)
2619{
Andy Hung225aef62022-12-06 16:33:20 -08002620 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002621}
2622
Andy Hungaaa18282023-06-23 19:27:19 -07002623RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002624 stop_nonvirtual();
2625 mRecordTrack->destroy();
2626}
2627
Andy Hungaaa18282023-06-23 19:27:19 -07002628binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002629 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002630 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002631 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002632 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002633}
2634
Andy Hungaaa18282023-06-23 19:27:19 -07002635binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002636 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002637 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002638}
2639
Andy Hungaaa18282023-06-23 19:27:19 -07002640void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002641 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002642 mRecordTrack->stop();
2643}
2644
Andy Hungaaa18282023-06-23 19:27:19 -07002645binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002646 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002647 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002648 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002649}
2650
Andy Hungaaa18282023-06-23 19:27:19 -07002651binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002652 int /*audio_microphone_direction_t*/ direction) {
2653 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002654 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002655 static_cast<audio_microphone_direction_t>(direction)));
2656}
2657
Andy Hungaaa18282023-06-23 19:27:19 -07002658binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002659 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002660 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002661}
2662
Andy Hungaaa18282023-06-23 19:27:19 -07002663binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002664 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2665 return binderStatusFromStatusT(
2666 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2667}
2668
Eric Laurent81784c32012-11-19 14:55:58 -08002669// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002670#undef LOG_TAG
2671#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002672
Andy Hung3ff4b552023-06-26 19:20:57 -07002673
Andy Hung56126702023-07-14 11:00:08 -07002674/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002675sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002676 const sp<Client>& client,
2677 const audio_attributes_t& attr,
2678 uint32_t sampleRate,
2679 audio_format_t format,
2680 audio_channel_mask_t channelMask,
2681 size_t frameCount,
2682 void* buffer,
2683 size_t bufferSize,
2684 audio_session_t sessionId,
2685 pid_t creatorPid,
2686 const AttributionSourceState& attributionSource,
2687 audio_input_flags_t flags,
2688 track_type type,
2689 audio_port_handle_t portId,
2690 int32_t startFrames)
2691{
2692 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002693 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002694 client,
2695 attr,
2696 sampleRate,
2697 format,
2698 channelMask,
2699 frameCount,
2700 buffer,
2701 bufferSize,
2702 sessionId,
2703 creatorPid,
2704 attributionSource,
2705 flags,
2706 type,
2707 portId,
2708 startFrames);
2709}
2710
Glenn Kasten05997e22014-03-13 15:08:33 -07002711// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002712RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002713 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002714 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002715 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002716 uint32_t sampleRate,
2717 audio_format_t format,
2718 audio_channel_mask_t channelMask,
2719 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002720 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002721 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002722 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002723 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002724 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002725 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002726 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002727 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002728 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002729 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002730 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002731 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002732 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002733 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002734 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002735 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002736 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002737 type, portId,
2738 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002739 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002740 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002741 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002742 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002743 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002744 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002745{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002746 if (mCblk == NULL) {
2747 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002748 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002749
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002750 if (!isDirect()) {
2751 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002752 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002753 channelMask, format, sampleRate);
2754 // Check if the RecordBufferConverter construction was successful.
2755 // If not, don't continue with construction.
2756 //
2757 // NOTE: It would be extremely rare that the record track cannot be created
2758 // for the current device, but a pending or future device change would make
2759 // the record track configuration valid.
2760 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002761 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002762 return;
2763 }
Andy Hung97a893e2015-03-29 01:03:07 -07002764 }
2765
Andy Hung6ae58432016-02-16 18:32:24 -08002766 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002767 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002768
Andy Hung97a893e2015-03-29 01:03:07 -07002769 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002770
Eric Laurent05067782016-06-01 18:27:28 -07002771 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002772 ALOG_ASSERT(thread->fastTrackAvailable());
2773 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002774 } else {
2775 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002776 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002777 }
Andy Hung8946a282018-04-19 20:04:56 -07002778#ifdef TEE_SINK
2779 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2780 + "_" + std::to_string(mId)
2781 + "_R");
2782#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002783
2784 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002785 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002786}
2787
Andy Hung3ff4b552023-06-26 19:20:57 -07002788RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002789{
Andy Hung9d84af52018-09-12 18:03:44 -07002790 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002791 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002792 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002793}
2794
Andy Hung3ff4b552023-06-26 19:20:57 -07002795status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002796{
2797 status_t status = TrackBase::initCheck();
2798 if (status == NO_ERROR && mServerProxy == 0) {
2799 status = BAD_VALUE;
2800 }
2801 return status;
2802}
2803
Eric Laurent81784c32012-11-19 14:55:58 -08002804// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002805status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002806{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002807 ServerProxy::Buffer buf;
2808 buf.mFrameCount = buffer->frameCount;
2809 status_t status = mServerProxy->obtainBuffer(&buf);
2810 buffer->frameCount = buf.mFrameCount;
2811 buffer->raw = buf.mRaw;
2812 if (buf.mFrameCount == 0) {
2813 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002814 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002815 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002816 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002817}
2818
Andy Hung3ff4b552023-06-26 19:20:57 -07002819status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002820 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002821{
Andy Hung44f27182023-07-06 20:56:16 -07002822 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002823 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002824 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002825 return recordThread->start(this, event, triggerSession);
2826 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002827 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2828 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002829 }
2830}
2831
Andy Hung3ff4b552023-06-26 19:20:57 -07002832void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002833{
Andy Hung44f27182023-07-06 20:56:16 -07002834 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002835 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002836 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002837 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002838 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002839 }
2840 }
2841}
2842
Andy Hung3ff4b552023-06-26 19:20:57 -07002843void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002844{
Andy Hung3ff4b552023-06-26 19:20:57 -07002845 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002846 sp<RecordTrack> keep(this);
2847 {
Andy Hungce685402018-10-05 17:23:27 -07002848 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002849 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002850 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07002851 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002852 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002853 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002854 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002855 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002856 }
Andy Hungce685402018-10-05 17:23:27 -07002857 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2858 }
2859 // APM portid/client management done outside of lock.
2860 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2861 if (isExternalTrack()) {
2862 switch (priorState) {
2863 case ACTIVE: // invalidated while still active
2864 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2865 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2866 AudioSystem::stopInput(mPortId);
2867 break;
2868
2869 case STARTING_1: // invalidated/start-aborted and startInput not successful
2870 case PAUSED: // OK, not active
2871 case IDLE: // OK, not active
2872 break;
2873
2874 case STOPPED: // unexpected (destroyed)
2875 default:
2876 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2877 }
2878 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002879 }
2880 }
2881}
2882
Andy Hung3ff4b552023-06-26 19:20:57 -07002883void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002884{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002885 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002886 // FIXME should use proxy, and needs work
2887 audio_track_cblk_t* cblk = mCblk;
2888 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2889 android_atomic_release_store(0x40000000, &cblk->mFutex);
2890 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002891 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002892}
2893
Eric Laurent81784c32012-11-19 14:55:58 -08002894
Andy Hung3ff4b552023-06-26 19:20:57 -07002895void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002896{
Eric Laurent973db022018-11-20 14:54:31 -08002897 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002898 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002899 " Server FrmCnt FrmRdy Sil%s\n",
2900 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002901}
2902
Andy Hung3ff4b552023-06-26 19:20:57 -07002903void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002904{
Eric Laurent973db022018-11-20 14:54:31 -08002905 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002906 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002907 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002908 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002909 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002910 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002911 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002912 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002913 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002914 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002915 mCblk->mFlags,
2916
Eric Laurent81784c32012-11-19 14:55:58 -08002917 mFormat,
2918 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002919 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002920 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002921
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002922 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002923 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002924 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002925 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002926 );
Andy Hung000adb52018-06-01 15:43:26 -07002927 if (isServerLatencySupported()) {
2928 double latencyMs;
2929 bool fromTrack;
2930 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2931 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2932 // or 'k' if estimated from kernel (usually for debugging).
2933 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2934 } else {
2935 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2936 }
2937 }
2938 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002939}
2940
Andy Hung93bb5732023-05-04 21:16:34 -07002941// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002942void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002943 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002944{
Andy Hung93bb5732023-05-04 21:16:34 -07002945 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002946 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002947 if (threadBase != 0) {
2948 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2949 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002950 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002951 }
Andy Hung93bb5732023-05-04 21:16:34 -07002952
2953 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002954}
2955
Andy Hung3ff4b552023-06-26 19:20:57 -07002956void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002957{
Andy Hung93bb5732023-05-04 21:16:34 -07002958 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002959}
2960
Andy Hung3ff4b552023-06-26 19:20:57 -07002961void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002962 int64_t trackFramesReleased, int64_t sourceFramesRead,
2963 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2964{
Andy Hung30282562018-08-08 18:27:03 -07002965 // Make the kernel frametime available.
2966 const FrameTime ft{
2967 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2968 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2969 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2970 mKernelFrameTime.store(ft);
2971 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002972 // Stream is direct, return provided timestamp with no conversion
2973 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002974 return;
2975 }
2976
Andy Hung3f0c9022016-01-15 17:49:46 -08002977 ExtendedTimestamp local = timestamp;
2978
2979 // Convert HAL frames to server-side track frames at track sample rate.
2980 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2981 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2982 if (local.mTimeNs[i] != 0) {
2983 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2984 const int64_t relativeTrackFrames = relativeServerFrames
2985 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2986 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2987 }
2988 }
Andy Hung6ae58432016-02-16 18:32:24 -08002989 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002990
2991 // Compute latency info.
2992 const bool useTrackTimestamp = true; // use track unless debugging.
2993 const double latencyMs = - (useTrackTimestamp
2994 ? local.getOutputServerLatencyMs(sampleRate())
2995 : timestamp.getOutputServerLatencyMs(halSampleRate));
2996
2997 mServerLatencyFromTrack.store(useTrackTimestamp);
2998 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08002999}
Eric Laurent83b88082014-06-20 18:31:16 -07003000
Andy Hung3ff4b552023-06-26 19:20:57 -07003001status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003002 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003003{
Andy Hung44f27182023-07-06 20:56:16 -07003004 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003005 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003006 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003007 return recordThread->getActiveMicrophones(activeMicrophones);
3008 } else {
3009 return BAD_VALUE;
3010 }
3011}
3012
Andy Hung3ff4b552023-06-26 19:20:57 -07003013status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003014 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003015 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003016 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003017 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003018 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003019 } else {
3020 return BAD_VALUE;
3021 }
3022}
3023
Andy Hung3ff4b552023-06-26 19:20:57 -07003024status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003025 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003026 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003027 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003028 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003029 } else {
3030 return BAD_VALUE;
3031 }
3032}
3033
Andy Hung3ff4b552023-06-26 19:20:57 -07003034status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003035 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3036
3037 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3038 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3039 if (callingUid != mUid || callingPid != mCreatorPid) {
3040 return PERMISSION_DENIED;
3041 }
3042
Svet Ganov33761132021-05-13 22:51:08 +00003043 AttributionSourceState attributionSource{};
3044 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3045 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3046 attributionSource.token = sp<BBinder>::make();
3047 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003048 return PERMISSION_DENIED;
3049 }
3050
Andy Hung44f27182023-07-06 20:56:16 -07003051 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003052 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003053 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003054 status_t status = recordThread->shareAudioHistory(
3055 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3056 if (status == NO_ERROR) {
3057 mSharedAudioPackageName = sharedAudioPackageName;
3058 }
3059 return status;
3060 } else {
3061 return BAD_VALUE;
3062 }
3063}
3064
Andy Hung3ff4b552023-06-26 19:20:57 -07003065void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003066{
3067
3068 // Do not forward PatchRecord metadata with unspecified audio source
3069 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3070 return;
3071 }
3072
3073 // No track is invalid as this is called after prepareTrack_l in the same critical section
3074 record_track_metadata_v7_t metadata;
3075 metadata.base = {
3076 .source = mAttr.source,
3077 .gain = 1, // capture tracks do not have volumes
3078 };
3079 metadata.channel_mask = mChannelMask;
3080 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3081
3082 *backInserter++ = metadata;
3083}
Eric Laurentec376dc2021-04-08 20:41:22 +02003084
Andy Hung9d84af52018-09-12 18:03:44 -07003085// ----------------------------------------------------------------------------
3086#undef LOG_TAG
3087#define LOG_TAG "AF::PatchRecord"
3088
Andy Hung3ff4b552023-06-26 19:20:57 -07003089/* static */
3090sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003091 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003092 uint32_t sampleRate,
3093 audio_channel_mask_t channelMask,
3094 audio_format_t format,
3095 size_t frameCount,
3096 void *buffer,
3097 size_t bufferSize,
3098 audio_input_flags_t flags,
3099 const Timeout& timeout,
3100 audio_source_t source)
3101{
3102 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003103 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003104 sampleRate,
3105 channelMask,
3106 format,
3107 frameCount,
3108 buffer,
3109 bufferSize,
3110 flags,
3111 timeout,
3112 source);
3113}
3114
Andy Hung44f27182023-07-06 20:56:16 -07003115PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003116 uint32_t sampleRate,
3117 audio_channel_mask_t channelMask,
3118 audio_format_t format,
3119 size_t frameCount,
3120 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003121 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003122 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003123 const Timeout& timeout,
3124 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003125 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003126 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003127 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003128 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003129 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003130 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3131 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07003132 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003133{
Andy Hung9d84af52018-09-12 18:03:44 -07003134 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3135 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003136 (int)mPeerTimeout.tv_sec,
3137 (int)(mPeerTimeout.tv_nsec / 1000000));
3138}
3139
Andy Hung3ff4b552023-06-26 19:20:57 -07003140PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003141{
Andy Hungabfab202019-03-07 19:45:54 -08003142 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003143}
3144
Mikhail Naganov8296c252019-09-25 14:59:54 -07003145static size_t writeFramesHelper(
3146 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3147{
3148 AudioBufferProvider::Buffer patchBuffer;
3149 patchBuffer.frameCount = frameCount;
3150 auto status = dest->getNextBuffer(&patchBuffer);
3151 if (status != NO_ERROR) {
3152 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3153 __func__, status, strerror(-status));
3154 return 0;
3155 }
3156 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3157 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3158 size_t framesWritten = patchBuffer.frameCount;
3159 dest->releaseBuffer(&patchBuffer);
3160 return framesWritten;
3161}
3162
3163// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003164size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003165 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3166{
3167 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3168 // On buffer wrap, the buffer frame count will be less than requested,
3169 // when this happens a second buffer needs to be used to write the leftover audio
3170 const size_t framesLeft = frameCount - framesWritten;
3171 if (framesWritten != 0 && framesLeft != 0) {
3172 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3173 framesLeft, frameSize);
3174 }
3175 return framesWritten;
3176}
3177
Eric Laurent83b88082014-06-20 18:31:16 -07003178// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003179status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003180 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003181{
Andy Hung9d84af52018-09-12 18:03:44 -07003182 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003183 Proxy::Buffer buf;
3184 buf.mFrameCount = buffer->frameCount;
3185 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3186 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003187 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003188 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003189 if (ATRACE_ENABLED()) {
3190 std::string traceName("PRnObt");
3191 traceName += std::to_string(id());
3192 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3193 }
Eric Laurent83b88082014-06-20 18:31:16 -07003194 if (buf.mFrameCount == 0) {
3195 return WOULD_BLOCK;
3196 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003197 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003198 return status;
3199}
3200
Andy Hung3ff4b552023-06-26 19:20:57 -07003201void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003202{
Andy Hung9d84af52018-09-12 18:03:44 -07003203 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003204 Proxy::Buffer buf;
3205 buf.mFrameCount = buffer->frameCount;
3206 buf.mRaw = buffer->raw;
3207 mPeerProxy->releaseBuffer(&buf);
3208 TrackBase::releaseBuffer(buffer);
3209}
3210
Andy Hung3ff4b552023-06-26 19:20:57 -07003211status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003212 const struct timespec *timeOut)
3213{
3214 return mProxy->obtainBuffer(buffer, timeOut);
3215}
3216
Andy Hung3ff4b552023-06-26 19:20:57 -07003217void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003218{
3219 mProxy->releaseBuffer(buffer);
3220}
3221
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003222#undef LOG_TAG
3223#define LOG_TAG "AF::PthrPatchRecord"
3224
3225static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3226{
3227 void *ptr = nullptr;
3228 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003229 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003230}
3231
Andy Hung3ff4b552023-06-26 19:20:57 -07003232/* static */
3233sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003234 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003235 uint32_t sampleRate,
3236 audio_channel_mask_t channelMask,
3237 audio_format_t format,
3238 size_t frameCount,
3239 audio_input_flags_t flags,
3240 audio_source_t source)
3241{
3242 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003243 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003244 sampleRate,
3245 channelMask,
3246 format,
3247 frameCount,
3248 flags,
3249 source);
3250}
3251
3252PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003253 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003254 uint32_t sampleRate,
3255 audio_channel_mask_t channelMask,
3256 audio_format_t format,
3257 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003258 audio_input_flags_t flags,
3259 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003260 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003261 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003262 mPatchRecordAudioBufferProvider(*this),
3263 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3264 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3265{
3266 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3267}
3268
Andy Hung3ff4b552023-06-26 19:20:57 -07003269sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003270 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003271{
3272 *thread = mThread.promote();
3273 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003274 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07003275 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07003276 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003277}
3278
3279// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003280status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003281 Proxy::Buffer* buffer, const struct timespec* timeOut)
3282{
3283 if (mUnconsumedFrames) {
3284 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3285 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3286 return PatchRecord::obtainBuffer(buffer, timeOut);
3287 }
3288
3289 // Otherwise, execute a read from HAL and write into the buffer.
3290 nsecs_t startTimeNs = 0;
3291 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3292 // Will need to correct timeOut by elapsed time.
3293 startTimeNs = systemTime();
3294 }
3295 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3296 buffer->mFrameCount = 0;
3297 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003298 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003299 sp<StreamInHalInterface> stream = obtainStream(&thread);
3300 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3301
3302 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003303 size_t bytesRead = 0;
3304 {
3305 ATRACE_NAME("read");
3306 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3307 if (result != NO_ERROR) goto stream_error;
3308 if (bytesRead == 0) return NO_ERROR;
3309 }
3310
3311 {
Andy Hung094dc762023-08-28 19:12:14 -07003312 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003313 mReadBytes += bytesRead;
3314 mReadError = NO_ERROR;
3315 }
3316 mReadCV.notify_one();
3317 // writeFrames handles wraparound and should write all the provided frames.
3318 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3319 buffer->mFrameCount = writeFrames(
3320 &mPatchRecordAudioBufferProvider,
3321 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3322 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3323 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3324 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003325 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003326 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003327 // Correct the timeout by elapsed time.
3328 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003329 if (newTimeOutNs < 0) newTimeOutNs = 0;
3330 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3331 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003332 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003333 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003334 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003335
3336stream_error:
3337 stream->standby();
3338 {
Andy Hung094dc762023-08-28 19:12:14 -07003339 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003340 mReadError = result;
3341 }
3342 mReadCV.notify_one();
3343 return result;
3344}
3345
Andy Hung3ff4b552023-06-26 19:20:57 -07003346void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003347{
3348 if (buffer->mFrameCount <= mUnconsumedFrames) {
3349 mUnconsumedFrames -= buffer->mFrameCount;
3350 } else {
3351 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3352 buffer->mFrameCount, mUnconsumedFrames);
3353 mUnconsumedFrames = 0;
3354 }
3355 PatchRecord::releaseBuffer(buffer);
3356}
3357
3358// AudioBufferProvider and Source methods are called on RecordThread
3359// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3360// and 'releaseBuffer' are stubbed out and ignore their input.
3361// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3362// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003363status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003364 void* buffer, size_t bytes, size_t* read)
3365{
3366 bytes = std::min(bytes, mFrameCount * mFrameSize);
3367 {
Andy Hung094dc762023-08-28 19:12:14 -07003368 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003369 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3370 if (mReadError != NO_ERROR) {
3371 mLastReadFrames = 0;
3372 return mReadError;
3373 }
3374 *read = std::min(bytes, mReadBytes);
3375 mReadBytes -= *read;
3376 }
3377 mLastReadFrames = *read / mFrameSize;
3378 memset(buffer, 0, *read);
3379 return 0;
3380}
3381
Andy Hung3ff4b552023-06-26 19:20:57 -07003382status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003383 int64_t* frames, int64_t* time)
3384{
Andy Hung44f27182023-07-06 20:56:16 -07003385 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003386 sp<StreamInHalInterface> stream = obtainStream(&thread);
3387 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3388}
3389
Andy Hung3ff4b552023-06-26 19:20:57 -07003390status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003391{
3392 // RecordThread issues 'standby' command in two major cases:
3393 // 1. Error on read--this case is handled in 'obtainBuffer'.
3394 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3395 // output, this can only happen when the software patch
3396 // is being torn down. In this case, the RecordThread
3397 // will terminate and close the HAL stream.
3398 return 0;
3399}
3400
3401// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003402status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003403 AudioBufferProvider::Buffer* buffer)
3404{
3405 buffer->frameCount = mLastReadFrames;
3406 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3407 return NO_ERROR;
3408}
3409
Andy Hung3ff4b552023-06-26 19:20:57 -07003410void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003411 AudioBufferProvider::Buffer* buffer)
3412{
3413 buffer->frameCount = 0;
3414 buffer->raw = nullptr;
3415}
3416
Andy Hung9d84af52018-09-12 18:03:44 -07003417// ----------------------------------------------------------------------------
3418#undef LOG_TAG
3419#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003420
Andy Hung3ff4b552023-06-26 19:20:57 -07003421/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003422sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003423 const audio_attributes_t& attr,
3424 uint32_t sampleRate,
3425 audio_format_t format,
3426 audio_channel_mask_t channelMask,
3427 audio_session_t sessionId,
3428 bool isOut,
3429 const android::content::AttributionSourceState& attributionSource,
3430 pid_t creatorPid,
3431 audio_port_handle_t portId)
3432{
3433 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003434 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003435 attr,
3436 sampleRate,
3437 format,
3438 channelMask,
3439 sessionId,
3440 isOut,
3441 attributionSource,
3442 creatorPid,
3443 portId);
3444}
3445
Andy Hung44f27182023-07-06 20:56:16 -07003446MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003447 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003448 uint32_t sampleRate,
3449 audio_format_t format,
3450 audio_channel_mask_t channelMask,
3451 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003452 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003453 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003454 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003455 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003456 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003457 channelMask, (size_t)0 /* frameCount */,
3458 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003459 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003460 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003461 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003462 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003463 TYPE_DEFAULT, portId,
3464 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003465 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003466 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003467{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003468 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003469 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003470}
3471
Andy Hung3ff4b552023-06-26 19:20:57 -07003472MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003473{
3474}
3475
Andy Hung3ff4b552023-06-26 19:20:57 -07003476status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003477{
3478 return NO_ERROR;
3479}
3480
Andy Hung3ff4b552023-06-26 19:20:57 -07003481status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003482 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003483{
3484 return NO_ERROR;
3485}
3486
Andy Hung3ff4b552023-06-26 19:20:57 -07003487void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003488{
3489}
3490
3491// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003492status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003493{
3494 buffer->frameCount = 0;
3495 buffer->raw = nullptr;
3496 return INVALID_OPERATION;
3497}
3498
3499// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003500size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003501 return 0;
3502}
3503
Andy Hung3ff4b552023-06-26 19:20:57 -07003504int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003505{
3506 return 0;
3507}
3508
Andy Hung3ff4b552023-06-26 19:20:57 -07003509void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003510{
3511}
3512
Andy Hung3ff4b552023-06-26 19:20:57 -07003513void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003514{
3515 if (mMuteState == muteState) {
3516 // mute state did not change, do nothing
3517 return;
3518 }
3519
3520 status_t result = UNKNOWN_ERROR;
3521 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3522 if (mMuteEventExtras == nullptr) {
3523 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3524 }
3525 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3526 static_cast<int>(muteState));
3527
3528 result = audioManager->portEvent(mPortId,
3529 PLAYER_UPDATE_MUTED,
3530 mMuteEventExtras);
3531 }
3532
3533 if (result == OK) {
3534 mMuteState = muteState;
3535 } else {
3536 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3537 __func__,
3538 id(),
3539 mPortId,
3540 result);
3541 }
3542}
3543
Andy Hung3ff4b552023-06-26 19:20:57 -07003544void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003545{
Eric Laurent973db022018-11-20 14:54:31 -08003546 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003547 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003548}
3549
Andy Hung3ff4b552023-06-26 19:20:57 -07003550void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003551{
Eric Laurent973db022018-11-20 14:54:31 -08003552 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003553 mPid,
3554 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003555 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003556 mFormat,
3557 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003558 mSampleRate,
3559 mAttr.flags);
3560 if (isOut()) {
3561 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3562 } else {
3563 result.appendFormat("%6x", mAttr.source);
3564 }
3565 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003566}
3567
Glenn Kasten63238ef2015-03-02 15:50:29 -08003568} // namespace android