blob: 2dd039a266abd9af73d79d85b67f46ed9096a595 [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 }
Dorin Drimusbbddde02023-11-13 15:01:33 +0000454
455 // restrict position modulo INT_MAX to avoid integer sanitization abort
456 legacy.mPosition &= INT_MAX;
457
Andy Hung973638a2020-12-08 20:47:45 -0800458 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800460}
461
Andy Hungaaa18282023-06-23 19:27:19 -0700462Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800463 mTrack->signal();
464 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800465}
466
Andy Hungaaa18282023-06-23 19:27:19 -0700467Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800468 const media::VolumeShaperConfiguration& configuration,
469 const media::VolumeShaperOperation& operation,
470 int32_t* _aidl_return) {
471 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
472 *_aidl_return = conf->readFromParcelable(configuration);
473 if (*_aidl_return != OK) {
474 return Status::ok();
475 }
476
477 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
478 *_aidl_return = op->readFromParcelable(operation);
479 if (*_aidl_return != OK) {
480 return Status::ok();
481 }
482
483 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
484 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700485}
486
Andy Hungaaa18282023-06-23 19:27:19 -0700487Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800488 int32_t id,
489 std::optional<media::VolumeShaperState>* _aidl_return) {
490 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
491 if (legacy == nullptr) {
492 _aidl_return->reset();
493 return Status::ok();
494 }
495 media::VolumeShaperState aidl;
496 legacy->writeToParcelable(&aidl);
497 *_aidl_return = aidl;
498 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800499}
500
Andy Hungaaa18282023-06-23 19:27:19 -0700501Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000502 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800503{
504 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
505 const status_t status = mTrack->getDualMonoMode(&mode)
506 ?: AudioValidator::validateDualMonoMode(mode);
507 if (status == OK) {
508 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
509 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
510 }
511 return binderStatusFromStatusT(status);
512}
513
Andy Hungaaa18282023-06-23 19:27:19 -0700514Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000515 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800516{
517 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
518 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
519 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
520 ?: mTrack->setDualMonoMode(localMonoMode));
521}
522
Andy Hungaaa18282023-06-23 19:27:19 -0700523Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800524{
525 float leveldB = -std::numeric_limits<float>::infinity();
526 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
527 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
528 if (status == OK) *_aidl_return = leveldB;
529 return binderStatusFromStatusT(status);
530}
531
Andy Hungaaa18282023-06-23 19:27:19 -0700532Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800533{
534 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
535 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
536}
537
Andy Hungaaa18282023-06-23 19:27:19 -0700538Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000539 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800540{
541 audio_playback_rate_t localPlaybackRate{};
542 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
543 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
544 if (status == NO_ERROR) {
545 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
546 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
547 }
548 return binderStatusFromStatusT(status);
549}
550
Andy Hungaaa18282023-06-23 19:27:19 -0700551Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000552 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800553{
554 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
555 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
556 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
557 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
558}
559
Eric Laurent81784c32012-11-19 14:55:58 -0800560// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800561// AppOp for audio playback
562// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700563
564// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700565sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung44f27182023-07-06 20:56:16 -0700566 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000567 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700568 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800569{
Vlad Popa103be862023-07-10 20:27:41 -0700570 Vector<String16> packages;
571 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000572 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700573 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700574 if (packages.isEmpty()) {
575 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
576 id,
577 attr.usage,
578 uid);
579 return nullptr;
580 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800581 }
582 // stream type has been filtered by audio policy to indicate whether it can be muted
583 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700584 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700585 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800586 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700587 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
588 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
589 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
590 id, attr.flags);
591 return nullptr;
592 }
Vlad Popa103be862023-07-10 20:27:41 -0700593 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700594}
595
Andy Hung44f27182023-07-06 20:56:16 -0700596OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
597 const AttributionSourceState& attributionSource,
598 audio_usage_t usage, int id, uid_t uid)
599 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa103be862023-07-10 20:27:41 -0700600 mHasOpPlayAudio(true),
601 mAttributionSource(attributionSource),
602 mUsage((int32_t)usage),
603 mId(id),
604 mUid(uid),
605 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
606 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800607
Andy Hung3ff4b552023-06-26 19:20:57 -0700608OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800609{
610 if (mOpCallback != 0) {
611 mAppOpsManager.stopWatchingMode(mOpCallback);
612 }
613 mOpCallback.clear();
614}
615
Andy Hung3ff4b552023-06-26 19:20:57 -0700616void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700617{
Vlad Popad2152122023-08-02 18:36:04 -0700618 // make sure not to broadcast the initial state since it is not needed and could
619 // cause a deadlock since this method can be called with the mThread->mLock held
620 checkPlayAudioForUsage(/*doBroadcast=*/false);
Svet Ganov33761132021-05-13 22:51:08 +0000621 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700622 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700623 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Vlad Popa103be862023-07-10 20:27:41 -0700624 mPackageName, mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700625 }
626}
627
Andy Hung3ff4b552023-06-26 19:20:57 -0700628bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800629 return mHasOpPlayAudio.load();
630}
631
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700632// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800633// - not called from constructor due to check on UID,
634// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung3ff4b552023-06-26 19:20:57 -0700635void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800636{
Vlad Popa103be862023-07-10 20:27:41 -0700637 const bool hasAppOps = mAttributionSource.packageName.has_value()
638 && mAppOpsManager.checkAudioOpNoThrow(
639 AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
640 AppOpsManager::MODE_ALLOWED;
641
642 bool shouldChange = !hasAppOps; // check if we need to update.
643 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
644 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
Vlad Popad2152122023-08-02 18:36:04 -0700645 if (doBroadcast) {
646 auto thread = mThread.promote();
Andy Hung71742ab2023-07-07 13:47:37 -0700647 if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
Vlad Popad2152122023-08-02 18:36:04 -0700648 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung87e82412023-08-29 14:26:09 -0700649 audio_utils::lock_guard _l(thread->mutex());
Vlad Popad2152122023-08-02 18:36:04 -0700650 thread->broadcast_l();
651 }
Vlad Popa103be862023-07-10 20:27:41 -0700652 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800653 }
654}
655
Andy Hung3ff4b552023-06-26 19:20:57 -0700656OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800657 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
658{ }
659
Andy Hung3ff4b552023-06-26 19:20:57 -0700660void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800661 const String16& packageName) {
662 // we only have uid, so we need to check all package names anyway
663 UNUSED(packageName);
664 if (op != AppOpsManager::OP_PLAY_AUDIO) {
665 return;
666 }
667 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
668 if (monitor != NULL) {
Vlad Popad2152122023-08-02 18:36:04 -0700669 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800670 }
671}
672
Eric Laurent9066ad32019-05-20 14:40:10 -0700673// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700674void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700675 uid_t uid, Vector<String16>& packages)
676{
677 PermissionController permissionController;
678 permissionController.getPackagesForUid(uid, packages);
679}
680
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800681// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700682#undef LOG_TAG
683#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800684
Andy Hung3ff4b552023-06-26 19:20:57 -0700685/* static */
Andy Hung44f27182023-07-06 20:56:16 -0700686sp<IAfTrack> IAfTrack::create(
687 IAfPlaybackThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700688 const sp<Client>& client,
689 audio_stream_type_t streamType,
690 const audio_attributes_t& attr,
691 uint32_t sampleRate,
692 audio_format_t format,
693 audio_channel_mask_t channelMask,
694 size_t frameCount,
695 void *buffer,
696 size_t bufferSize,
697 const sp<IMemory>& sharedBuffer,
698 audio_session_t sessionId,
699 pid_t creatorPid,
700 const AttributionSourceState& attributionSource,
701 audio_output_flags_t flags,
702 track_type type,
703 audio_port_handle_t portId,
704 /** default behaviour is to start when there are as many frames
705 * ready as possible (aka. Buffer is full). */
706 size_t frameCountToBeReady,
707 float speed,
708 bool isSpatialized,
709 bool isBitPerfect) {
Andy Hung44f27182023-07-06 20:56:16 -0700710 return sp<Track>::make(thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700711 client,
712 streamType,
713 attr,
714 sampleRate,
715 format,
716 channelMask,
717 frameCount,
718 buffer,
719 bufferSize,
720 sharedBuffer,
721 sessionId,
722 creatorPid,
723 attributionSource,
724 flags,
725 type,
726 portId,
727 frameCountToBeReady,
728 speed,
729 isSpatialized,
730 isBitPerfect);
731}
732
Eric Laurent81784c32012-11-19 14:55:58 -0800733// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -0700734Track::Track(
Andy Hung44f27182023-07-06 20:56:16 -0700735 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800736 const sp<Client>& client,
737 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700738 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800739 uint32_t sampleRate,
740 audio_format_t format,
741 audio_channel_mask_t channelMask,
742 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700743 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700744 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800745 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800746 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700747 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000748 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700749 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800750 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100751 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000752 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200753 float speed,
jiabinc658e452022-10-21 20:52:21 +0000754 bool isSpatialized,
755 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700756 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700757 // TODO: Using unsecurePointer() has some associated security pitfalls
758 // (see declaration for details).
759 // Either document why it is safe in this case or address the
760 // issue (e.g. by copying).
761 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700762 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700763 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000764 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700765 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800766 type,
767 portId,
768 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung3ff4b552023-06-26 19:20:57 -0700769 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800770 // mRetryCount initialized later when needed
771 mSharedBuffer(sharedBuffer),
772 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700773 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800774 mAuxBuffer(NULL),
775 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700776 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700777 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa103be862023-07-10 20:27:41 -0700778 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700779 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700780 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800781 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800782 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700783 /* The track might not play immediately after being active, similarly as if its volume was 0.
784 * When the track starts playing, its volume will be computed. */
785 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800786 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700787 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000788 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200789 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000790 mIsSpatialized(isSpatialized),
791 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800792{
Eric Laurent83b88082014-06-20 18:31:16 -0700793 // client == 0 implies sharedBuffer == 0
794 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
795
Andy Hung9d84af52018-09-12 18:03:44 -0700796 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700797 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700798
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700799 if (mCblk == NULL) {
800 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800801 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700802
Svet Ganov33761132021-05-13 22:51:08 +0000803 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700804 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
805 ALOGE("%s(%d): no more tracks available", __func__, mId);
806 releaseCblk(); // this makes the track invalid.
807 return;
808 }
809
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700810 if (sharedBuffer == 0) {
811 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700812 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700813 } else {
814 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100815 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700816 }
817 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700818 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700819
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700820 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700821 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700822 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
823 // race with setSyncEvent(). However, if we call it, we cannot properly start
824 // static fast tracks (SoundPool) immediately after stopping.
825 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung44f27182023-07-06 20:56:16 -0700826 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
827 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700828 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700829 // FIXME This is too eager. We allocate a fast track index before the
830 // fast track becomes active. Since fast tracks are a scarce resource,
831 // this means we are potentially denying other more important fast tracks from
832 // being created. It would be better to allocate the index dynamically.
833 mFastIndex = i;
Andy Hung44f27182023-07-06 20:56:16 -0700834 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700835 }
Andy Hung8946a282018-04-19 20:04:56 -0700836
Dean Wheatley7b036912020-06-18 16:22:11 +1000837 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700838#ifdef TEE_SINK
839 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800840 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700841#endif
jiabin57303cc2018-12-18 15:45:57 -0800842
jiabineb3bda02020-06-30 14:07:03 -0700843 if (thread->supportsHapticPlayback()) {
844 // If the track is attached to haptic playback thread, it is potentially to have
845 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
846 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800847 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000848 std::string packageName = attributionSource.packageName.has_value() ?
849 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800850 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700851 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800852 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800853
854 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700855 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800856 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800857}
858
Andy Hung3ff4b552023-06-26 19:20:57 -0700859Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800860{
Andy Hung9d84af52018-09-12 18:03:44 -0700861 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700862
863 // The destructor would clear mSharedBuffer,
864 // but it will not push the decremented reference count,
865 // leaving the client's IMemory dangling indefinitely.
866 // This prevents that leak.
867 if (mSharedBuffer != 0) {
868 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700869 }
Eric Laurent81784c32012-11-19 14:55:58 -0800870}
871
Andy Hung3ff4b552023-06-26 19:20:57 -0700872status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700873{
874 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700875 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700876 status = NO_MEMORY;
877 }
878 return status;
879}
880
Andy Hung3ff4b552023-06-26 19:20:57 -0700881void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800882{
883 // NOTE: destroyTrack_l() can remove a strong reference to this Track
884 // by removing it from mTracks vector, so there is a risk that this Tracks's
885 // destructor is called. As the destructor needs to lock mLock,
886 // we must acquire a strong reference on this Track before locking mLock
887 // here so that the destructor is called only when exiting this function.
888 // On the other hand, as long as Track::destroy() is only called by
889 // TrackHandle destructor, the TrackHandle still holds a strong ref on
890 // this Track with its member mTrack.
891 sp<Track> keep(this);
892 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700893 bool wasActive = false;
Andy Hung44f27182023-07-06 20:56:16 -0700894 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800895 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -0700896 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -0700897 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700898 wasActive = playbackThread->destroyTrack_l(this);
899 }
900 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700901 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800902 }
903 }
Kevin Rocardc43ea142019-01-31 18:17:37 -0800904 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
Eric Laurent81784c32012-11-19 14:55:58 -0800905}
906
Andy Hung3ff4b552023-06-26 19:20:57 -0700907void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800908{
Eric Laurent973db022018-11-20 14:54:31 -0800909 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700910 " Format Chn mask SRate "
911 "ST Usg CT "
912 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000913 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700914 "%s\n",
915 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800916}
917
Andy Hung3ff4b552023-06-26 19:20:57 -0700918void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800919{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700920 char trackType;
921 switch (mType) {
922 case TYPE_DEFAULT:
923 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700924 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700925 trackType = 'S'; // static
926 } else {
927 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800928 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700929 break;
930 case TYPE_PATCH:
931 trackType = 'P';
932 break;
933 default:
934 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800935 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700936
937 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700938 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700939 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700940 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700941 }
942
Eric Laurent81784c32012-11-19 14:55:58 -0800943 char nowInUnderrun;
944 switch (mObservedUnderruns.mBitFields.mMostRecent) {
945 case UNDERRUN_FULL:
946 nowInUnderrun = ' ';
947 break;
948 case UNDERRUN_PARTIAL:
949 nowInUnderrun = '<';
950 break;
951 case UNDERRUN_EMPTY:
952 nowInUnderrun = '*';
953 break;
954 default:
955 nowInUnderrun = '?';
956 break;
957 }
Andy Hungda540db2017-04-20 14:06:17 -0700958
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700959 char fillingStatus;
Andy Hung3ff4b552023-06-26 19:20:57 -0700960 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700961 case FS_INVALID:
962 fillingStatus = 'I';
963 break;
964 case FS_FILLING:
965 fillingStatus = 'f';
966 break;
967 case FS_FILLED:
968 fillingStatus = 'F';
969 break;
970 case FS_ACTIVE:
971 fillingStatus = 'A';
972 break;
973 default:
974 fillingStatus = '?';
975 break;
976 }
977
978 // clip framesReadySafe to max representation in dump
979 const size_t framesReadySafe =
980 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
981
982 // obtain volumes
983 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
984 const std::pair<float /* volume */, bool /* active */> vsVolume =
985 mVolumeHandler->getLastVolume();
986
987 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
988 // as it may be reduced by the application.
989 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
990 // Check whether the buffer size has been modified by the app.
991 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
992 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
993 ? 'e' /* error */ : ' ' /* identical */;
994
Eric Laurent973db022018-11-20 14:54:31 -0800995 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700996 "%08X %08X %6u "
997 "%2u %3x %2x "
998 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000999 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -08001000 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -07001001 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001002 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08001003 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001004 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001005 mCblk->mFlags,
1006
Eric Laurent81784c32012-11-19 14:55:58 -08001007 mFormat,
1008 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001009 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001010
1011 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001012 mAttr.usage,
1013 mAttr.content_type,
1014
1015 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001016 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1017 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001018 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1019 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001020
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001021 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001022 bufferSizeInFrames,
1023 modifiedBufferChar,
1024 framesReadySafe,
1025 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001026 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001027 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001028 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1029 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001030 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001031
1032 if (isServerLatencySupported()) {
1033 double latencyMs;
1034 bool fromTrack;
1035 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1036 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1037 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1038 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001039 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001040 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001041 }
1042 }
1043 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001044}
1045
Andy Hung3ff4b552023-06-26 19:20:57 -07001046uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001047 return mAudioTrackServerProxy->getSampleRate();
1048}
1049
Eric Laurent81784c32012-11-19 14:55:58 -08001050// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001051status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001052{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001053 ServerProxy::Buffer buf;
1054 size_t desiredFrames = buffer->frameCount;
1055 buf.mFrameCount = desiredFrames;
1056 status_t status = mServerProxy->obtainBuffer(&buf);
1057 buffer->frameCount = buf.mFrameCount;
1058 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001059 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001060 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001061 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001062 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001063 } else {
1064 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001065 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001066 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001067}
1068
Andy Hung3ff4b552023-06-26 19:20:57 -07001069void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001070{
1071 interceptBuffer(*buffer);
1072 TrackBase::releaseBuffer(buffer);
1073}
1074
1075// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001076void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001077 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001078 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001079 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001080 if (frameCount == 0) {
1081 return; // No audio to intercept.
1082 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1083 // does not allow 0 frame size request contrary to getNextBuffer
1084 }
1085 for (auto& teePatch : mTeePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001086 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001087 const size_t framesWritten = patchRecord->writeFrames(
1088 sourceBuffer.i8, frameCount, mFrameSize);
1089 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001090 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001091 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001092 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001093 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001094 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1095 using namespace std::chrono_literals;
1096 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001097 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001098 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001099}
1100
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001101// ExtendedAudioBufferProvider interface
1102
Andy Hung27876c02014-09-09 18:07:55 -07001103// framesReady() may return an approximation of the number of frames if called
1104// from a different thread than the one calling Proxy->obtainBuffer() and
1105// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1106// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001107size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001108 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1109 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1110 // The remainder of the buffer is not drained.
1111 return 0;
1112 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001113 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001114}
1115
Andy Hung3ff4b552023-06-26 19:20:57 -07001116int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001117{
1118 return mAudioTrackServerProxy->framesReleased();
1119}
1120
Andy Hung3ff4b552023-06-26 19:20:57 -07001121void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001122{
1123 // This call comes from a FastTrack and should be kept lockless.
1124 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001125 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001126
Andy Hung818e7a32016-02-16 18:08:07 -08001127 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001128
1129 // Compute latency.
1130 // TODO: Consider whether the server latency may be passed in by FastMixer
1131 // as a constant for all active FastTracks.
1132 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1133 mServerLatencyFromTrack.store(true);
1134 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001135}
1136
Eric Laurent81784c32012-11-19 14:55:58 -08001137// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001138bool Track::isReady() const {
1139 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001140 return true;
1141 }
1142
Eric Laurent16498512014-03-17 17:22:08 -07001143 if (isStopping()) {
1144 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001145 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001146 }
Eric Laurent81784c32012-11-19 14:55:58 -08001147 return true;
1148 }
1149
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001150 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001151 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1152 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1153 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1154 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001155
1156 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1157 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1158 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001159 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001160 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001161 return true;
1162 }
1163 return false;
1164}
1165
Andy Hung3ff4b552023-06-26 19:20:57 -07001166status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001167 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001168{
1169 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001170 ALOGV("%s(%d): calling pid %d session %d",
1171 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001172
Andy Hung44f27182023-07-06 20:56:16 -07001173 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001174 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001175 if (isOffloaded()) {
Andy Hung2ac52f12023-08-28 18:36:53 -07001176 audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
Andy Hung87e82412023-08-29 14:26:09 -07001177 audio_utils::lock_guard _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001178 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung2cbc2722023-07-17 17:05:00 -07001179 if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001180 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001181 invalidate();
1182 return PERMISSION_DENIED;
1183 }
1184 }
Andy Hung87e82412023-08-29 14:26:09 -07001185 audio_utils::lock_guard _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001186 track_state state = mState;
1187 // here the track could be either new, or restarted
1188 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001189
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001190 // initial state-stopping. next state-pausing.
1191 // What if resume is called ?
1192
Zhou Song1ed46a22020-08-17 15:36:56 +08001193 if (state == FLUSHED) {
1194 // avoid underrun glitches when starting after flush
1195 reset();
1196 }
1197
kuowei.li576f1362021-05-11 18:02:32 +08001198 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1199 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001200 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001201 if (mResumeToStopping) {
1202 // happened we need to resume to STOPPING_1
1203 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001204 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1205 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001206 } else {
1207 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001208 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1209 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001210 }
Eric Laurent81784c32012-11-19 14:55:58 -08001211 } else {
1212 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001213 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1214 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001215 }
1216
Andy Hung44f27182023-07-06 20:56:16 -07001217 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001218
1219 // states to reset position info for pcm tracks
1220 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001221 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1222 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001223
1224 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1225 // Start point of track -> sink frame map. If the HAL returns a
1226 // frame position smaller than the first written frame in
1227 // updateTrackFrameInfo, the timestamp can be interpolated
1228 // instead of using a larger value.
1229 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1230 playbackThread->framesWritten());
1231 }
Andy Hunge10393e2015-06-12 13:59:33 -07001232 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001233 if (isFastTrack()) {
1234 // refresh fast track underruns on start because that field is never cleared
1235 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1236 // after stop.
1237 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1238 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001239 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001240 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001241 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001242 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001243 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001244 mState = state;
1245 }
1246 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001247
Andy Hungb68f5eb2019-12-03 16:49:17 -08001248 // Audio timing metrics are computed a few mix cycles after starting.
1249 {
1250 mLogStartCountdown = LOG_START_COUNTDOWN;
1251 mLogStartTimeNs = systemTime();
1252 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001253 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1254 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001255 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001256 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001257
Andy Hung1d3556d2018-03-29 16:30:14 -07001258 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1259 // for streaming tracks, remove the buffer read stop limit.
1260 mAudioTrackServerProxy->start();
1261 }
1262
Eric Laurentbfb1b832013-01-07 09:53:42 -08001263 // track was already in the active list, not a problem
1264 if (status == ALREADY_EXISTS) {
1265 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001266 } else {
1267 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1268 // It is usually unsafe to access the server proxy from a binder thread.
1269 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1270 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1271 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001272 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001273 ServerProxy::Buffer buffer;
1274 buffer.mFrameCount = 1;
1275 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001276 }
1277 } else {
1278 status = BAD_VALUE;
1279 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001280 if (status == NO_ERROR) {
1281 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001282
1283 // send format to AudioManager for playback activity monitoring
Andy Hung2cbc2722023-07-17 17:05:00 -07001284 const sp<IAudioManager> audioManager =
1285 thread->afThreadCallback()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001286 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1287 std::unique_ptr<os::PersistableBundle> bundle =
1288 std::make_unique<os::PersistableBundle>();
1289 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1290 isSpatialized());
1291 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1292 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1293 status_t result = audioManager->portEvent(mPortId,
1294 PLAYER_UPDATE_FORMAT, bundle);
1295 if (result != OK) {
1296 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1297 __func__, mPortId, result);
1298 }
1299 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001300 }
Eric Laurent81784c32012-11-19 14:55:58 -08001301 return status;
1302}
1303
Andy Hung3ff4b552023-06-26 19:20:57 -07001304void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001305{
Andy Hungc0691382018-09-12 18:01:57 -07001306 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001307 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001308 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001309 audio_utils::lock_guard _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001310 track_state state = mState;
1311 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1312 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001313 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1314 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001315 reset();
1316 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001317 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001318 mState = STOPPED;
1319 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001320 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1321 // presentation is complete
1322 // For an offloaded track this starts a drain and state will
1323 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001324 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001325 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001326 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001327 }
Eric Laurent81784c32012-11-19 14:55:58 -08001328 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001329 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001330 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1331 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001332 }
Eric Laurent81784c32012-11-19 14:55:58 -08001333 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001334 forEachTeePatchTrack([](auto patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001335}
1336
Andy Hung3ff4b552023-06-26 19:20:57 -07001337void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001338{
Andy Hungc0691382018-09-12 18:01:57 -07001339 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001340 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001341 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001342 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001343 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001344 switch (mState) {
1345 case STOPPING_1:
1346 case STOPPING_2:
1347 if (!isOffloaded()) {
1348 /* nothing to do if track is not offloaded */
1349 break;
1350 }
1351
1352 // Offloaded track was draining, we need to carry on draining when resumed
1353 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001354 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001355 case ACTIVE:
1356 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001357 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001358 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1359 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001360 if (isOffloadedOrDirect()) {
1361 mPauseHwPending = true;
1362 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001363 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001364 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001365
Eric Laurentbfb1b832013-01-07 09:53:42 -08001366 default:
1367 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001368 }
1369 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001370 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1371 forEachTeePatchTrack([](auto patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001372}
1373
Andy Hung3ff4b552023-06-26 19:20:57 -07001374void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001375{
Andy Hungc0691382018-09-12 18:01:57 -07001376 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001377 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001378 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001379 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001380 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001381
Phil Burk4bb650b2016-09-09 12:11:17 -07001382 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1383 // Otherwise the flush would not be done until the track is resumed.
1384 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001385 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001386 (void)mServerProxy->flushBufferIfNeeded();
1387 }
1388
Eric Laurentbfb1b832013-01-07 09:53:42 -08001389 if (isOffloaded()) {
1390 // If offloaded we allow flush during any state except terminated
1391 // and keep the track active to avoid problems if user is seeking
1392 // rapidly and underlying hardware has a significant delay handling
1393 // a pause
1394 if (isTerminated()) {
1395 return;
1396 }
1397
Andy Hung9d84af52018-09-12 18:03:44 -07001398 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001399 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001400
1401 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001402 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1403 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001404 mState = ACTIVE;
1405 }
1406
Haynes Mathew George7844f672014-01-15 12:32:55 -08001407 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001408 mResumeToStopping = false;
1409 } else {
1410 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1411 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1412 return;
1413 }
1414 // No point remaining in PAUSED state after a flush => go to
1415 // FLUSHED state
1416 mState = FLUSHED;
1417 // do not reset the track if it is still in the process of being stopped or paused.
1418 // this will be done by prepareTracks_l() when the track is stopped.
1419 // prepareTracks_l() will see mState == FLUSHED, then
1420 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001421 if (isDirect()) {
1422 mFlushHwPending = true;
1423 }
Andy Hung44f27182023-07-06 20:56:16 -07001424 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001425 reset();
1426 }
Eric Laurent81784c32012-11-19 14:55:58 -08001427 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001428 // Prevent flush being lost if the track is flushed and then resumed
1429 // before mixer thread can run. This is important when offloading
1430 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001431 playbackThread->broadcast_l();
Eric Laurent81784c32012-11-19 14:55:58 -08001432 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001433 // Flush the Tee to avoid on resume playing old data and glitching on the transition to new data
1434 forEachTeePatchTrack([](auto patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001435}
1436
Haynes Mathew George7844f672014-01-15 12:32:55 -08001437// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001438void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001439{
Andy Hung71ba4b32022-10-06 12:09:49 -07001440 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001441 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001442 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001443
Phil Burk4bb650b2016-09-09 12:11:17 -07001444 // Clear the client ring buffer so that the app can prime the buffer while paused.
1445 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1446 mServerProxy->flushBufferIfNeeded();
1447
Haynes Mathew George7844f672014-01-15 12:32:55 -08001448 mFlushHwPending = false;
1449}
1450
Andy Hung3ff4b552023-06-26 19:20:57 -07001451void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001452{
1453 mPauseHwPending = false;
1454}
1455
Andy Hung3ff4b552023-06-26 19:20:57 -07001456void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001457{
1458 // Do not reset twice to avoid discarding data written just after a flush and before
1459 // the audioflinger thread detects the track is stopped.
1460 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001461 // Force underrun condition to avoid false underrun callback until first data is
1462 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001463 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001464 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001465 mResetDone = true;
1466 if (mState == FLUSHED) {
1467 mState = IDLE;
1468 }
1469 }
1470}
1471
Andy Hung3ff4b552023-06-26 19:20:57 -07001472status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001473{
Andy Hung44f27182023-07-06 20:56:16 -07001474 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001475 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001476 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001477 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001478 } else if (thread->type() == IAfThreadBase::DIRECT
1479 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001480 return thread->setParameters(keyValuePairs);
1481 } else {
1482 return PERMISSION_DENIED;
1483 }
1484}
1485
Andy Hung3ff4b552023-06-26 19:20:57 -07001486status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001487 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001488 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001489 if (thread == 0) {
1490 ALOGE("thread is dead");
1491 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001492 } else if (thread->type() == IAfThreadBase::DIRECT
1493 || thread->type() == IAfThreadBase::OFFLOAD) {
1494 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001495 return directOutputThread->selectPresentation(presentationId, programId);
1496 }
1497 return INVALID_OPERATION;
1498}
1499
Andy Hung3ff4b552023-06-26 19:20:57 -07001500VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001501 const sp<VolumeShaper::Configuration>& configuration,
1502 const sp<VolumeShaper::Operation>& operation)
1503{
Andy Hungee86cee2022-12-13 19:19:53 -08001504 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001505
1506 if (isOffloadedOrDirect()) {
1507 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001508 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001509 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07001510 audio_utils::lock_guard _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001511 thread->broadcast_l();
1512 }
1513 }
1514 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001515}
1516
Andy Hung3ff4b552023-06-26 19:20:57 -07001517sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001518{
1519 // Note: We don't check if Thread exists.
1520
1521 // mVolumeHandler is thread safe.
1522 return mVolumeHandler->getVolumeShaperState(id);
1523}
1524
Andy Hung3ff4b552023-06-26 19:20:57 -07001525void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001526{
jiabin76d94692022-12-15 21:51:21 +00001527 mFinalVolumeLeft = volumeLeft;
1528 mFinalVolumeRight = volumeRight;
1529 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001530 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1531 mFinalVolume = volume;
1532 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001533 mLogForceVolumeUpdate = true;
1534 }
1535 if (mLogForceVolumeUpdate) {
1536 mLogForceVolumeUpdate = false;
1537 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001538 }
1539}
1540
Andy Hung3ff4b552023-06-26 19:20:57 -07001541void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001542{
Eric Laurent49e39282022-06-24 18:42:45 +02001543 // Do not forward metadata for PatchTrack with unspecified stream type
1544 if (mStreamType == AUDIO_STREAM_PATCH) {
1545 return;
1546 }
1547
Eric Laurent94579172020-11-20 18:41:04 +01001548 playback_track_metadata_v7_t metadata;
1549 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001550 .usage = mAttr.usage,
1551 .content_type = mAttr.content_type,
1552 .gain = mFinalVolume,
1553 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001554
1555 // When attributes are undefined, derive default values from stream type.
1556 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1557 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1558 switch (mStreamType) {
1559 case AUDIO_STREAM_VOICE_CALL:
1560 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1561 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1562 break;
1563 case AUDIO_STREAM_SYSTEM:
1564 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1565 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1566 break;
1567 case AUDIO_STREAM_RING:
1568 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1569 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1570 break;
1571 case AUDIO_STREAM_MUSIC:
1572 metadata.base.usage = AUDIO_USAGE_MEDIA;
1573 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1574 break;
1575 case AUDIO_STREAM_ALARM:
1576 metadata.base.usage = AUDIO_USAGE_ALARM;
1577 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1578 break;
1579 case AUDIO_STREAM_NOTIFICATION:
1580 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1581 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1582 break;
1583 case AUDIO_STREAM_DTMF:
1584 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1585 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1586 break;
1587 case AUDIO_STREAM_ACCESSIBILITY:
1588 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1589 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1590 break;
1591 case AUDIO_STREAM_ASSISTANT:
1592 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1593 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1594 break;
1595 case AUDIO_STREAM_REROUTING:
1596 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1597 // unknown content type
1598 break;
1599 case AUDIO_STREAM_CALL_ASSISTANT:
1600 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1601 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1602 break;
1603 default:
1604 break;
1605 }
1606 }
1607
Eric Laurent78b07302022-10-07 16:20:34 +02001608 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001609 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1610 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001611}
1612
Andy Hung3ff4b552023-06-26 19:20:57 -07001613void Track::updateTeePatches() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001614 if (mTeePatchesToUpdate.has_value()) {
1615 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
1616 mTeePatches = mTeePatchesToUpdate.value();
1617 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1618 mState == TrackBase::STOPPING_1) {
1619 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
1620 }
1621 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001622 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001623}
1624
Andy Hung34645da2023-07-14 11:45:38 -07001625void Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001626 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1627 "%s, existing tee patches to update will be ignored", __func__);
1628 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1629}
1630
Vlad Popae8d99472022-06-30 16:02:48 +02001631// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001632void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001633 IAudioManager>& audioManager, mute_state_t muteState)
1634{
1635 if (mMuteState == muteState) {
1636 // mute state did not change, do nothing
1637 return;
1638 }
1639
1640 status_t result = UNKNOWN_ERROR;
1641 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1642 if (mMuteEventExtras == nullptr) {
1643 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1644 }
1645 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1646 static_cast<int>(muteState));
1647
1648 result = audioManager->portEvent(mPortId,
1649 PLAYER_UPDATE_MUTED,
1650 mMuteEventExtras);
1651 }
1652
1653 if (result == OK) {
1654 mMuteState = muteState;
1655 } else {
1656 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1657 __func__,
1658 id(),
1659 mPortId,
1660 result);
Andy Hung818e7a32016-02-16 18:08:07 -08001661 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001662}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001663
Andy Hung3ff4b552023-06-26 19:20:57 -07001664status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001665{
1666 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001667 return INVALID_OPERATION; // normal tracks handled through SSQ
1668 }
Andy Hung44f27182023-07-06 20:56:16 -07001669 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001670 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001671 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001672 }
Phil Burk6140c792015-03-19 14:30:21 -07001673
Andy Hung87e82412023-08-29 14:26:09 -07001674 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001675 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001676 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001677}
1678
Andy Hung3ff4b552023-06-26 19:20:57 -07001679status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001680{
Andy Hung44f27182023-07-06 20:56:16 -07001681 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001682 if (thread == nullptr) {
1683 return DEAD_OBJECT;
1684 }
Eric Laurent81784c32012-11-19 14:55:58 -08001685
Andy Hung44f27182023-07-06 20:56:16 -07001686 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001687 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001688 sp<IAfPlaybackThread> srcThread;
Andy Hungfa2f4f32023-07-17 12:40:43 -07001689 const auto& af = mClient->afClientCallback();
Eric Laurent6c796322019-04-09 14:13:17 -07001690 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001691
Eric Laurent6c796322019-04-09 14:13:17 -07001692 if (EffectId != 0 && status == NO_ERROR) {
1693 status = dstThread->attachAuxEffect(this, EffectId);
1694 if (status == NO_ERROR) {
1695 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001696 }
Eric Laurent6c796322019-04-09 14:13:17 -07001697 }
1698
1699 if (status != NO_ERROR && srcThread != nullptr) {
1700 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001701 }
1702 return status;
1703}
1704
Andy Hung3ff4b552023-06-26 19:20:57 -07001705void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001706{
1707 mAuxEffectId = EffectId;
1708 mAuxBuffer = buffer;
1709}
1710
Andy Hung59de4262021-06-14 10:53:54 -07001711// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001712bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001713 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001714{
Andy Hung818e7a32016-02-16 18:08:07 -08001715 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1716 // This assists in proper timestamp computation as well as wakelock management.
1717
Eric Laurent81784c32012-11-19 14:55:58 -08001718 // a track is considered presented when the total number of frames written to audio HAL
1719 // corresponds to the number of frames written when presentationComplete() is called for the
1720 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001721 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1722 // to detect when all frames have been played. In this case framesWritten isn't
1723 // useful because it doesn't always reflect whether there is data in the h/w
1724 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001725 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1726 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001727 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001728 if (mPresentationCompleteFrames == 0) {
1729 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001730 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001731 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1732 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001733 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001734 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001735
Andy Hungc54b1ff2016-02-23 14:07:07 -08001736 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001737 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001738 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001739 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1740 __func__, mId, (complete ? "complete" : "waiting"),
1741 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001742 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001743 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001744 && mAudioTrackServerProxy->isDrained();
1745 }
1746
1747 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001748 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001749 return true;
1750 }
1751 return false;
1752}
1753
Andy Hung59de4262021-06-14 10:53:54 -07001754// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001755bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001756{
1757 // For Offloaded or Direct tracks.
1758
1759 // For a direct track, we incorporated time based testing for presentationComplete.
1760
1761 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1762 // to detect when all frames have been played. In this case latencyMs isn't
1763 // useful because it doesn't always reflect whether there is data in the h/w
1764 // buffers, particularly if a track has been paused and resumed during draining
1765
1766 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1767 if (mPresentationCompleteTimeNs == 0) {
1768 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1769 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1770 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1771 }
1772
1773 bool complete;
1774 if (isOffloaded()) {
1775 complete = true;
1776 } else { // Direct
1777 complete = systemTime() >= mPresentationCompleteTimeNs;
1778 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1779 }
1780 if (complete) {
1781 notifyPresentationComplete();
1782 return true;
1783 }
1784 return false;
1785}
1786
Andy Hung3ff4b552023-06-26 19:20:57 -07001787void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001788{
1789 // This only triggers once. TODO: should we enforce this?
1790 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1791 mAudioTrackServerProxy->setStreamEndDone();
1792}
1793
Andy Hung3ff4b552023-06-26 19:20:57 -07001794void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001795{
Andy Hung068e08e2023-05-15 19:02:55 -07001796 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1797 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001798 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001799 (*it)->trigger();
1800 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001801 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001802 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001803 }
1804 }
1805}
1806
1807// implement VolumeBufferProvider interface
1808
Andy Hung3ff4b552023-06-26 19:20:57 -07001809gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001810{
1811 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1812 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001813 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1814 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1815 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001816 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001817 if (vl > GAIN_FLOAT_UNITY) {
1818 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001819 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001820 if (vr > GAIN_FLOAT_UNITY) {
1821 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001822 }
1823 // now apply the cached master volume and stream type volume;
1824 // this is trusted but lacks any synchronization or barrier so may be stale
1825 float v = mCachedVolume;
1826 vl *= v;
1827 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001828 // re-combine into packed minifloat
1829 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001830 // FIXME look at mute, pause, and stop flags
1831 return vlr;
1832}
1833
Andy Hung3ff4b552023-06-26 19:20:57 -07001834status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001835 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001836{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001837 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001838 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1839 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001840 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1841 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001842 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001843 event->cancel();
1844 return INVALID_OPERATION;
1845 }
1846 (void) TrackBase::setSyncEvent(event);
1847 return NO_ERROR;
1848}
1849
Andy Hung3ff4b552023-06-26 19:20:57 -07001850void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001851{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001852 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001853 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001854}
1855
Andy Hung3ff4b552023-06-26 19:20:57 -07001856void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001857{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001858 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001859 signalClientFlag(CBLK_DISABLED);
1860}
1861
Andy Hung3ff4b552023-06-26 19:20:57 -07001862void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001863{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001864 // FIXME should use proxy, and needs work
1865 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001866 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001867 android_atomic_release_store(0x40000000, &cblk->mFutex);
1868 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001869 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001870}
1871
Andy Hung3ff4b552023-06-26 19:20:57 -07001872void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001873{
Andy Hung44f27182023-07-06 20:56:16 -07001874 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001875 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001876 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001877 audio_utils::lock_guard _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001878 t->broadcast_l();
1879 }
1880}
1881
Andy Hung3ff4b552023-06-26 19:20:57 -07001882status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001883{
1884 status_t status = INVALID_OPERATION;
1885 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001886 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001887 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001888 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001889 audio_utils::lock_guard _l(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001890 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001891 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1892 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1893 }
1894 }
1895 return status;
1896}
1897
Andy Hung3ff4b552023-06-26 19:20:57 -07001898status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001899{
1900 status_t status = INVALID_OPERATION;
1901 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001902 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001903 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001904 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001905 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001906 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001907 if (status == NO_ERROR) {
1908 mDualMonoMode = mode;
1909 }
1910 }
1911 }
1912 return status;
1913}
1914
Andy Hung3ff4b552023-06-26 19:20:57 -07001915status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001916{
1917 status_t status = INVALID_OPERATION;
1918 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001919 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001920 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001921 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001922 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001923 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001924 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1925 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1926 }
1927 }
1928 return status;
1929}
1930
Andy Hung3ff4b552023-06-26 19:20:57 -07001931status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001932{
1933 status_t status = INVALID_OPERATION;
1934 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001935 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001936 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001937 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001938 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001939 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001940 if (status == NO_ERROR) {
1941 mAudioDescriptionMixLevel = leveldB;
1942 }
1943 }
1944 }
1945 return status;
1946}
1947
Andy Hung3ff4b552023-06-26 19:20:57 -07001948status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001949 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001950{
1951 status_t status = INVALID_OPERATION;
1952 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001953 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001954 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001955 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001956 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001957 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001958 ALOGD_IF((status == NO_ERROR) &&
1959 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1960 "%s: playbackRate inconsistent", __func__);
1961 }
1962 }
1963 return status;
1964}
1965
Andy Hung3ff4b552023-06-26 19:20:57 -07001966status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001967 const audio_playback_rate_t& playbackRate)
1968{
1969 status_t status = INVALID_OPERATION;
1970 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001971 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001972 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001973 auto* const t = thread->asIAfPlaybackThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07001974 audio_utils::lock_guard lock(t->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07001975 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001976 if (status == NO_ERROR) {
1977 mPlaybackRateParameters = playbackRate;
1978 }
1979 }
1980 }
1981 return status;
1982}
1983
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001984//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001985bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07001986 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001987 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001988 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001989 /* Resume is pending if track was stopping before pause was called */
1990 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07001991 mResumeToStopping) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001992 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001993 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001994
1995 return false;
1996}
1997
1998//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001999void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07002000 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002001 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07002002 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002003
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002004 // Other possibility of pending resume is stopping_1 state
2005 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002006 // drain being called.
2007 if (mState == STOPPING_1) {
2008 mResumeToStopping = false;
2009 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002010}
Andy Hunge10393e2015-06-12 13:59:33 -07002011
2012//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002013void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002014 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002015 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002016 // Make the kernel frametime available.
2017 const FrameTime ft{
2018 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2019 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2020 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2021 mKernelFrameTime.store(ft);
2022 if (!audio_is_linear_pcm(mFormat)) {
2023 return;
2024 }
2025
Andy Hung818e7a32016-02-16 18:08:07 -08002026 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002027 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002028
2029 // adjust server times and set drained state.
2030 //
2031 // Our timestamps are only updated when the track is on the Thread active list.
2032 // We need to ensure that tracks are not removed before full drain.
2033 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002034 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002035 bool checked = false;
2036 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2037 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2038 // Lookup the track frame corresponding to the sink frame position.
2039 if (local.mTimeNs[i] > 0) {
2040 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2041 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002042 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002043 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002044 checked = true;
2045 }
2046 }
Andy Hunge10393e2015-06-12 13:59:33 -07002047 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002048
Andy Hung93bb5732023-05-04 21:16:34 -07002049 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2050 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002051 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002052 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002053 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002054 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002055
2056 // Compute latency info.
2057 const bool useTrackTimestamp = !drained;
2058 const double latencyMs = useTrackTimestamp
2059 ? local.getOutputServerLatencyMs(sampleRate())
2060 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2061
2062 mServerLatencyFromTrack.store(useTrackTimestamp);
2063 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002064
Andy Hung62921122020-05-18 10:47:31 -07002065 if (mLogStartCountdown > 0
2066 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2067 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2068 {
2069 if (mLogStartCountdown > 1) {
2070 --mLogStartCountdown;
2071 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2072 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002073 // startup is the difference in times for the current timestamp and our start
2074 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002075 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002076 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002077 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2078 * 1e3 / mSampleRate;
2079 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2080 " localTime:%lld startTime:%lld"
2081 " localPosition:%lld startPosition:%lld",
2082 __func__, latencyMs, startUpMs,
2083 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002084 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002085 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002086 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002087 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002088 }
Andy Hung62921122020-05-18 10:47:31 -07002089 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002090 }
Andy Hunge10393e2015-06-12 13:59:33 -07002091}
2092
Andy Hung3ff4b552023-06-26 19:20:57 -07002093bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002094 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002095 if (thread != 0) {
2096 // Lock for updating mHapticPlaybackEnabled.
Andy Hung87e82412023-08-29 14:26:09 -07002097 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002098 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002099 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002100 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002101 ALOGD("%s, haptic playback was %s for track %d",
2102 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002103 mTrack->setHapticPlaybackEnabled(!muted);
2104 return true;
jiabin57303cc2018-12-18 15:45:57 -08002105 }
2106 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002107 return false;
2108}
2109
Andy Hung3ff4b552023-06-26 19:20:57 -07002110binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002111 /*out*/ bool *ret) {
2112 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002113 return binder::Status::ok();
2114}
2115
Andy Hung3ff4b552023-06-26 19:20:57 -07002116binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002117 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002118 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002119 return binder::Status::ok();
2120}
2121
Eric Laurent81784c32012-11-19 14:55:58 -08002122// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002123#undef LOG_TAG
2124#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002125
Andy Hung3ff4b552023-06-26 19:20:57 -07002126/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002127sp<IAfOutputTrack> IAfOutputTrack::create(
2128 IAfPlaybackThread* playbackThread,
2129 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002130 uint32_t sampleRate,
2131 audio_format_t format,
2132 audio_channel_mask_t channelMask,
2133 size_t frameCount,
2134 const AttributionSourceState& attributionSource) {
2135 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002136 playbackThread,
2137 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002138 sampleRate,
2139 format,
2140 channelMask,
2141 frameCount,
2142 attributionSource);
2143}
2144
2145OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002146 IAfPlaybackThread* playbackThread,
2147 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002148 uint32_t sampleRate,
2149 audio_format_t format,
2150 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002151 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002152 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002153 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002154 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002155 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002156 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002157 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002158 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002159 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002160{
2161
2162 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002163 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002164 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002165 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002166 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002167 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002168 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002169 // since client and server are in the same process,
2170 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002171 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2172 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002173 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002174 mClientProxy->setSendLevel(0.0);
2175 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002176 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002177 ALOGW("%s(%d): Error creating output track on thread %d",
2178 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002179 }
2180}
2181
Andy Hung3ff4b552023-06-26 19:20:57 -07002182OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002183{
2184 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002185 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002186}
2187
Andy Hung3ff4b552023-06-26 19:20:57 -07002188status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002189 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002190{
2191 status_t status = Track::start(event, triggerSession);
2192 if (status != NO_ERROR) {
2193 return status;
2194 }
2195
2196 mActive = true;
2197 mRetryCount = 127;
2198 return status;
2199}
2200
Andy Hung3ff4b552023-06-26 19:20:57 -07002201void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002202{
2203 Track::stop();
2204 clearBufferQueue();
2205 mOutBuffer.frameCount = 0;
2206 mActive = false;
2207}
2208
Andy Hung3ff4b552023-06-26 19:20:57 -07002209ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002210{
Eric Laurent19952e12023-04-20 10:08:29 +02002211 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002212 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002213 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002214 // preload one silent buffer to trigger mixer on start()
2215 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2216 status_t status = mClientProxy->obtainBuffer(&buf);
2217 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2218 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2219 return 0;
2220 }
2221 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2222 mClientProxy->releaseBuffer(&buf);
2223
2224 (void) start();
2225
2226 // wait for HAL stream to start before sending actual audio. Doing this on each
2227 // OutputTrack makes that playback start on all output streams is synchronized.
2228 // If another OutputTrack has already started it can underrun but this is OK
2229 // as only silence has been played so far and the retry count is very high on
2230 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002231 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002232 if (!pt->waitForHalStart()) {
2233 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2234 stop();
2235 return 0;
2236 }
2237
2238 // enqueue the first buffer and exit so that other OutputTracks will also start before
2239 // write() is called again and this buffer actually consumed.
2240 Buffer firstBuffer;
2241 firstBuffer.frameCount = frames;
2242 firstBuffer.raw = data;
2243 queueBuffer(firstBuffer);
2244 return frames;
2245 } else {
2246 (void) start();
2247 }
2248 }
2249
Eric Laurent81784c32012-11-19 14:55:58 -08002250 Buffer *pInBuffer;
2251 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002252 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002253 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002254 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002255 while (waitTimeLeftMs) {
2256 // First write pending buffers, then new data
2257 if (mBufferQueue.size()) {
2258 pInBuffer = mBufferQueue.itemAt(0);
2259 } else {
2260 pInBuffer = &inBuffer;
2261 }
2262
2263 if (pInBuffer->frameCount == 0) {
2264 break;
2265 }
2266
2267 if (mOutBuffer.frameCount == 0) {
2268 mOutBuffer.frameCount = pInBuffer->frameCount;
2269 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002270 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002271 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002272 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2273 __func__, mId,
2274 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002275 break;
2276 }
2277 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2278 if (waitTimeLeftMs >= waitTimeMs) {
2279 waitTimeLeftMs -= waitTimeMs;
2280 } else {
2281 waitTimeLeftMs = 0;
2282 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002283 if (status == NOT_ENOUGH_DATA) {
2284 restartIfDisabled();
2285 continue;
2286 }
Eric Laurent81784c32012-11-19 14:55:58 -08002287 }
2288
2289 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2290 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002291 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002292 Proxy::Buffer buf;
2293 buf.mFrameCount = outFrames;
2294 buf.mRaw = NULL;
2295 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002296 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002297 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002298 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002299 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002300 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002301
2302 if (pInBuffer->frameCount == 0) {
2303 if (mBufferQueue.size()) {
2304 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002305 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002306 if (pInBuffer != &inBuffer) {
2307 delete pInBuffer;
2308 }
Andy Hung9d84af52018-09-12 18:03:44 -07002309 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2310 __func__, mId,
2311 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002312 } else {
2313 break;
2314 }
2315 }
2316 }
2317
2318 // If we could not write all frames, allocate a buffer and queue it for next time.
2319 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002320 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002321 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002322 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002323 }
2324 }
2325
Andy Hungc25b84a2015-01-14 19:04:10 -08002326 // Calling write() with a 0 length buffer means that no more data will be written:
2327 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2328 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2329 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002330 }
2331
Andy Hung1c86ebe2018-05-29 20:29:08 -07002332 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002333}
2334
Andy Hung3ff4b552023-06-26 19:20:57 -07002335void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002336
2337 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2338 Buffer *pInBuffer = new Buffer;
2339 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2340 pInBuffer->mBuffer = malloc(bufferSize);
2341 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2342 "%s: Unable to malloc size %zu", __func__, bufferSize);
2343 pInBuffer->frameCount = inBuffer.frameCount;
2344 pInBuffer->raw = pInBuffer->mBuffer;
2345 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2346 mBufferQueue.add(pInBuffer);
2347 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2348 (int)mThreadIoHandle, mBufferQueue.size());
2349 // audio data is consumed (stored locally); set frameCount to 0.
2350 inBuffer.frameCount = 0;
2351 } else {
2352 ALOGW("%s(%d): thread %d no more overflow buffers",
2353 __func__, mId, (int)mThreadIoHandle);
2354 // TODO: return error for this.
2355 }
2356}
2357
Andy Hung3ff4b552023-06-26 19:20:57 -07002358void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002359{
Andy Hung87e82412023-08-29 14:26:09 -07002360 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002361 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2362}
2363
Andy Hung3ff4b552023-06-26 19:20:57 -07002364void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002365 {
Andy Hung87e82412023-08-29 14:26:09 -07002366 audio_utils::lock_guard lock(trackMetadataMutex());
Kevin Rocard12381092018-04-11 09:19:59 -07002367 mTrackMetadatas = metadatas;
2368 }
2369 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2370 setMetadataHasChanged();
2371}
2372
Andy Hung3ff4b552023-06-26 19:20:57 -07002373status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002374 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2375{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002376 ClientProxy::Buffer buf;
2377 buf.mFrameCount = buffer->frameCount;
2378 struct timespec timeout;
2379 timeout.tv_sec = waitTimeMs / 1000;
2380 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2381 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2382 buffer->frameCount = buf.mFrameCount;
2383 buffer->raw = buf.mRaw;
2384 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002385}
2386
Andy Hung3ff4b552023-06-26 19:20:57 -07002387void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002388{
2389 size_t size = mBufferQueue.size();
2390
2391 for (size_t i = 0; i < size; i++) {
2392 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002393 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002394 delete pBuffer;
2395 }
2396 mBufferQueue.clear();
2397}
2398
Andy Hung3ff4b552023-06-26 19:20:57 -07002399void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002400{
2401 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2402 if (mActive && (flags & CBLK_DISABLED)) {
2403 start();
2404 }
2405}
Eric Laurent81784c32012-11-19 14:55:58 -08002406
Andy Hung9d84af52018-09-12 18:03:44 -07002407// ----------------------------------------------------------------------------
2408#undef LOG_TAG
2409#define LOG_TAG "AF::PatchTrack"
2410
Andy Hung3ff4b552023-06-26 19:20:57 -07002411/* static */
2412sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002413 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002414 audio_stream_type_t streamType,
2415 uint32_t sampleRate,
2416 audio_channel_mask_t channelMask,
2417 audio_format_t format,
2418 size_t frameCount,
2419 void* buffer,
2420 size_t bufferSize,
2421 audio_output_flags_t flags,
2422 const Timeout& timeout,
2423 size_t frameCountToBeReady /** Default behaviour is to start
2424 * as soon as possible to have
2425 * the lowest possible latency
2426 * even if it might glitch. */)
2427{
2428 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002429 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002430 streamType,
2431 sampleRate,
2432 channelMask,
2433 format,
2434 frameCount,
2435 buffer,
2436 bufferSize,
2437 flags,
2438 timeout,
2439 frameCountToBeReady);
2440}
2441
Andy Hung44f27182023-07-06 20:56:16 -07002442PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002443 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002444 uint32_t sampleRate,
2445 audio_channel_mask_t channelMask,
2446 audio_format_t format,
2447 size_t frameCount,
2448 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002449 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002450 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002451 const Timeout& timeout,
2452 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002453 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002454 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002455 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002456 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002457 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002458 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002459 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2460 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07002461 playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002462{
Andy Hung9d84af52018-09-12 18:03:44 -07002463 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2464 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002465 (int)mPeerTimeout.tv_sec,
2466 (int)(mPeerTimeout.tv_nsec / 1000000));
2467}
2468
Andy Hung3ff4b552023-06-26 19:20:57 -07002469PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002470{
Andy Hungabfab202019-03-07 19:45:54 -08002471 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002472}
2473
Andy Hung3ff4b552023-06-26 19:20:57 -07002474size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002475{
2476 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2477 return std::numeric_limits<size_t>::max();
2478 } else {
2479 return Track::framesReady();
2480 }
2481}
2482
Andy Hung3ff4b552023-06-26 19:20:57 -07002483status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002484 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002485{
2486 status_t status = Track::start(event, triggerSession);
2487 if (status != NO_ERROR) {
2488 return status;
2489 }
2490 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2491 return status;
2492}
2493
Eric Laurent83b88082014-06-20 18:31:16 -07002494// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002495status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002496 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002497{
Andy Hung9d84af52018-09-12 18:03:44 -07002498 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002499 Proxy::Buffer buf;
2500 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002501 if (ATRACE_ENABLED()) {
2502 std::string traceName("PTnReq");
2503 traceName += std::to_string(id());
2504 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2505 }
Eric Laurent83b88082014-06-20 18:31:16 -07002506 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002507 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002508 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002509 if (ATRACE_ENABLED()) {
2510 std::string traceName("PTnObt");
2511 traceName += std::to_string(id());
2512 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2513 }
Eric Laurent83b88082014-06-20 18:31:16 -07002514 if (buf.mFrameCount == 0) {
2515 return WOULD_BLOCK;
2516 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002517 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002518 return status;
2519}
2520
Andy Hung3ff4b552023-06-26 19:20:57 -07002521void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002522{
Andy Hung9d84af52018-09-12 18:03:44 -07002523 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002524 Proxy::Buffer buf;
2525 buf.mFrameCount = buffer->frameCount;
2526 buf.mRaw = buffer->raw;
2527 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002528 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002529}
2530
Andy Hung3ff4b552023-06-26 19:20:57 -07002531status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002532 const struct timespec *timeOut)
2533{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002534 status_t status = NO_ERROR;
2535 static const int32_t kMaxTries = 5;
2536 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002537 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002538 do {
2539 if (status == NOT_ENOUGH_DATA) {
2540 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002541 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002542 }
2543 status = mProxy->obtainBuffer(buffer, timeOut);
2544 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2545 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002546}
2547
Andy Hung3ff4b552023-06-26 19:20:57 -07002548void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002549{
2550 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002551 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002552
2553 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2554 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2555 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2556 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002557 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002558 && audio_is_linear_pcm(mFormat)
2559 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002560 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002561 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002562 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002563 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2564 / playbackThread->sampleRate();
2565 if (framesReady() < frameCount) {
2566 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002567 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002568 }
2569 }
2570 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002571}
2572
Andy Hung3ff4b552023-06-26 19:20:57 -07002573void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002574{
Eric Laurent83b88082014-06-20 18:31:16 -07002575 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002576 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002577 start();
2578 }
Eric Laurent83b88082014-06-20 18:31:16 -07002579}
2580
Eric Laurent81784c32012-11-19 14:55:58 -08002581// ----------------------------------------------------------------------------
2582// Record
2583// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002584
2585
Andy Hung9d84af52018-09-12 18:03:44 -07002586#undef LOG_TAG
2587#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002588
Andy Hungaaa18282023-06-23 19:27:19 -07002589class RecordHandle : public android::media::BnAudioRecord {
2590public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002591 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002592 ~RecordHandle() override;
2593 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2594 int /*audio_session_t*/ triggerSession) final;
2595 binder::Status stop() final;
2596 binder::Status getActiveMicrophones(
2597 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2598 binder::Status setPreferredMicrophoneDirection(
2599 int /*audio_microphone_direction_t*/ direction) final;
2600 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2601 binder::Status shareAudioHistory(
2602 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2603
2604private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002605 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002606
2607 // for use from destructor
2608 void stop_nonvirtual();
2609};
2610
2611/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002612sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2613 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002614 return sp<RecordHandle>::make(recordTrack);
2615}
2616
2617RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002618 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002619 : BnAudioRecord(),
2620 mRecordTrack(recordTrack)
2621{
Andy Hung225aef62022-12-06 16:33:20 -08002622 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002623}
2624
Andy Hungaaa18282023-06-23 19:27:19 -07002625RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002626 stop_nonvirtual();
2627 mRecordTrack->destroy();
2628}
2629
Andy Hungaaa18282023-06-23 19:27:19 -07002630binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002631 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002632 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002633 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002634 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002635}
2636
Andy Hungaaa18282023-06-23 19:27:19 -07002637binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002638 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002639 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002640}
2641
Andy Hungaaa18282023-06-23 19:27:19 -07002642void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002643 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002644 mRecordTrack->stop();
2645}
2646
Andy Hungaaa18282023-06-23 19:27:19 -07002647binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002648 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002649 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002650 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002651}
2652
Andy Hungaaa18282023-06-23 19:27:19 -07002653binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002654 int /*audio_microphone_direction_t*/ direction) {
2655 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002656 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002657 static_cast<audio_microphone_direction_t>(direction)));
2658}
2659
Andy Hungaaa18282023-06-23 19:27:19 -07002660binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002661 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002662 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002663}
2664
Andy Hungaaa18282023-06-23 19:27:19 -07002665binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002666 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2667 return binderStatusFromStatusT(
2668 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2669}
2670
Eric Laurent81784c32012-11-19 14:55:58 -08002671// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002672#undef LOG_TAG
2673#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002674
Andy Hung3ff4b552023-06-26 19:20:57 -07002675
Andy Hung56126702023-07-14 11:00:08 -07002676/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002677sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002678 const sp<Client>& client,
2679 const audio_attributes_t& attr,
2680 uint32_t sampleRate,
2681 audio_format_t format,
2682 audio_channel_mask_t channelMask,
2683 size_t frameCount,
2684 void* buffer,
2685 size_t bufferSize,
2686 audio_session_t sessionId,
2687 pid_t creatorPid,
2688 const AttributionSourceState& attributionSource,
2689 audio_input_flags_t flags,
2690 track_type type,
2691 audio_port_handle_t portId,
2692 int32_t startFrames)
2693{
2694 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002695 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002696 client,
2697 attr,
2698 sampleRate,
2699 format,
2700 channelMask,
2701 frameCount,
2702 buffer,
2703 bufferSize,
2704 sessionId,
2705 creatorPid,
2706 attributionSource,
2707 flags,
2708 type,
2709 portId,
2710 startFrames);
2711}
2712
Glenn Kasten05997e22014-03-13 15:08:33 -07002713// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002714RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002715 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002716 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002717 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002718 uint32_t sampleRate,
2719 audio_format_t format,
2720 audio_channel_mask_t channelMask,
2721 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002722 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002723 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002724 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002725 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002726 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002727 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002728 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002729 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002730 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002731 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002732 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002733 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002734 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002735 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002736 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002737 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002738 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002739 type, portId,
2740 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002741 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002742 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002743 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002744 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002745 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002746 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002747{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002748 if (mCblk == NULL) {
2749 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002750 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002751
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002752 if (!isDirect()) {
2753 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002754 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002755 channelMask, format, sampleRate);
2756 // Check if the RecordBufferConverter construction was successful.
2757 // If not, don't continue with construction.
2758 //
2759 // NOTE: It would be extremely rare that the record track cannot be created
2760 // for the current device, but a pending or future device change would make
2761 // the record track configuration valid.
2762 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002763 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002764 return;
2765 }
Andy Hung97a893e2015-03-29 01:03:07 -07002766 }
2767
Andy Hung6ae58432016-02-16 18:32:24 -08002768 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002769 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002770
Andy Hung97a893e2015-03-29 01:03:07 -07002771 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002772
Eric Laurent05067782016-06-01 18:27:28 -07002773 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002774 ALOG_ASSERT(thread->fastTrackAvailable());
2775 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002776 } else {
2777 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002778 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002779 }
Andy Hung8946a282018-04-19 20:04:56 -07002780#ifdef TEE_SINK
2781 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2782 + "_" + std::to_string(mId)
2783 + "_R");
2784#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002785
2786 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002787 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002788}
2789
Andy Hung3ff4b552023-06-26 19:20:57 -07002790RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002791{
Andy Hung9d84af52018-09-12 18:03:44 -07002792 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002793 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002794 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002795}
2796
Andy Hung3ff4b552023-06-26 19:20:57 -07002797status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002798{
2799 status_t status = TrackBase::initCheck();
2800 if (status == NO_ERROR && mServerProxy == 0) {
2801 status = BAD_VALUE;
2802 }
2803 return status;
2804}
2805
Eric Laurent81784c32012-11-19 14:55:58 -08002806// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002807status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002808{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002809 ServerProxy::Buffer buf;
2810 buf.mFrameCount = buffer->frameCount;
2811 status_t status = mServerProxy->obtainBuffer(&buf);
2812 buffer->frameCount = buf.mFrameCount;
2813 buffer->raw = buf.mRaw;
2814 if (buf.mFrameCount == 0) {
2815 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002816 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002817 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002818 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002819}
2820
Andy Hung3ff4b552023-06-26 19:20:57 -07002821status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002822 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002823{
Andy Hung44f27182023-07-06 20:56:16 -07002824 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002825 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002826 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002827 return recordThread->start(this, event, triggerSession);
2828 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002829 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2830 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002831 }
2832}
2833
Andy Hung3ff4b552023-06-26 19:20:57 -07002834void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002835{
Andy Hung44f27182023-07-06 20:56:16 -07002836 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002837 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002838 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002839 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002840 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002841 }
2842 }
2843}
2844
Andy Hung3ff4b552023-06-26 19:20:57 -07002845void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002846{
Andy Hung3ff4b552023-06-26 19:20:57 -07002847 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002848 sp<RecordTrack> keep(this);
2849 {
Andy Hungce685402018-10-05 17:23:27 -07002850 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002851 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002852 if (thread != 0) {
Andy Hung87e82412023-08-29 14:26:09 -07002853 audio_utils::lock_guard _l(thread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07002854 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002855 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002856 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002857 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002858 }
Andy Hungce685402018-10-05 17:23:27 -07002859 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2860 }
2861 // APM portid/client management done outside of lock.
2862 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2863 if (isExternalTrack()) {
2864 switch (priorState) {
2865 case ACTIVE: // invalidated while still active
2866 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2867 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2868 AudioSystem::stopInput(mPortId);
2869 break;
2870
2871 case STARTING_1: // invalidated/start-aborted and startInput not successful
2872 case PAUSED: // OK, not active
2873 case IDLE: // OK, not active
2874 break;
2875
2876 case STOPPED: // unexpected (destroyed)
2877 default:
2878 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2879 }
2880 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002881 }
2882 }
2883}
2884
Andy Hung3ff4b552023-06-26 19:20:57 -07002885void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002886{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002887 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002888 // FIXME should use proxy, and needs work
2889 audio_track_cblk_t* cblk = mCblk;
2890 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2891 android_atomic_release_store(0x40000000, &cblk->mFutex);
2892 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002893 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002894}
2895
Eric Laurent81784c32012-11-19 14:55:58 -08002896
Andy Hung3ff4b552023-06-26 19:20:57 -07002897void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002898{
Eric Laurent973db022018-11-20 14:54:31 -08002899 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002900 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002901 " Server FrmCnt FrmRdy Sil%s\n",
2902 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002903}
2904
Andy Hung3ff4b552023-06-26 19:20:57 -07002905void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002906{
Eric Laurent973db022018-11-20 14:54:31 -08002907 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002908 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002909 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002910 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002911 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002912 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002913 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002914 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002915 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002916 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002917 mCblk->mFlags,
2918
Eric Laurent81784c32012-11-19 14:55:58 -08002919 mFormat,
2920 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002921 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002922 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002923
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002924 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002925 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002926 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002927 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002928 );
Andy Hung000adb52018-06-01 15:43:26 -07002929 if (isServerLatencySupported()) {
2930 double latencyMs;
2931 bool fromTrack;
2932 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2933 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2934 // or 'k' if estimated from kernel (usually for debugging).
2935 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2936 } else {
2937 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2938 }
2939 }
2940 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002941}
2942
Andy Hung93bb5732023-05-04 21:16:34 -07002943// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002944void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002945 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002946{
Andy Hung93bb5732023-05-04 21:16:34 -07002947 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002948 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002949 if (threadBase != 0) {
2950 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2951 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002952 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002953 }
Andy Hung93bb5732023-05-04 21:16:34 -07002954
2955 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002956}
2957
Andy Hung3ff4b552023-06-26 19:20:57 -07002958void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002959{
Andy Hung93bb5732023-05-04 21:16:34 -07002960 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002961}
2962
Andy Hung3ff4b552023-06-26 19:20:57 -07002963void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002964 int64_t trackFramesReleased, int64_t sourceFramesRead,
2965 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2966{
Andy Hung30282562018-08-08 18:27:03 -07002967 // Make the kernel frametime available.
2968 const FrameTime ft{
2969 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2970 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2971 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2972 mKernelFrameTime.store(ft);
2973 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002974 // Stream is direct, return provided timestamp with no conversion
2975 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002976 return;
2977 }
2978
Andy Hung3f0c9022016-01-15 17:49:46 -08002979 ExtendedTimestamp local = timestamp;
2980
2981 // Convert HAL frames to server-side track frames at track sample rate.
2982 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2983 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2984 if (local.mTimeNs[i] != 0) {
2985 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2986 const int64_t relativeTrackFrames = relativeServerFrames
2987 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2988 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2989 }
2990 }
Andy Hung6ae58432016-02-16 18:32:24 -08002991 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002992
2993 // Compute latency info.
2994 const bool useTrackTimestamp = true; // use track unless debugging.
2995 const double latencyMs = - (useTrackTimestamp
2996 ? local.getOutputServerLatencyMs(sampleRate())
2997 : timestamp.getOutputServerLatencyMs(halSampleRate));
2998
2999 mServerLatencyFromTrack.store(useTrackTimestamp);
3000 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08003001}
Eric Laurent83b88082014-06-20 18:31:16 -07003002
Andy Hung3ff4b552023-06-26 19:20:57 -07003003status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003004 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003005{
Andy Hung44f27182023-07-06 20:56:16 -07003006 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003007 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003008 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003009 return recordThread->getActiveMicrophones(activeMicrophones);
3010 } else {
3011 return BAD_VALUE;
3012 }
3013}
3014
Andy Hung3ff4b552023-06-26 19:20:57 -07003015status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003016 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003017 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003018 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003019 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003020 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003021 } else {
3022 return BAD_VALUE;
3023 }
3024}
3025
Andy Hung3ff4b552023-06-26 19:20:57 -07003026status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003027 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003028 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003029 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003030 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003031 } else {
3032 return BAD_VALUE;
3033 }
3034}
3035
Andy Hung3ff4b552023-06-26 19:20:57 -07003036status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003037 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3038
3039 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3040 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3041 if (callingUid != mUid || callingPid != mCreatorPid) {
3042 return PERMISSION_DENIED;
3043 }
3044
Svet Ganov33761132021-05-13 22:51:08 +00003045 AttributionSourceState attributionSource{};
3046 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3047 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3048 attributionSource.token = sp<BBinder>::make();
3049 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003050 return PERMISSION_DENIED;
3051 }
3052
Andy Hung44f27182023-07-06 20:56:16 -07003053 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003054 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003055 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003056 status_t status = recordThread->shareAudioHistory(
3057 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3058 if (status == NO_ERROR) {
3059 mSharedAudioPackageName = sharedAudioPackageName;
3060 }
3061 return status;
3062 } else {
3063 return BAD_VALUE;
3064 }
3065}
3066
Andy Hung3ff4b552023-06-26 19:20:57 -07003067void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003068{
3069
3070 // Do not forward PatchRecord metadata with unspecified audio source
3071 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3072 return;
3073 }
3074
3075 // No track is invalid as this is called after prepareTrack_l in the same critical section
3076 record_track_metadata_v7_t metadata;
3077 metadata.base = {
3078 .source = mAttr.source,
3079 .gain = 1, // capture tracks do not have volumes
3080 };
3081 metadata.channel_mask = mChannelMask;
3082 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3083
3084 *backInserter++ = metadata;
3085}
Eric Laurentec376dc2021-04-08 20:41:22 +02003086
Andy Hung9d84af52018-09-12 18:03:44 -07003087// ----------------------------------------------------------------------------
3088#undef LOG_TAG
3089#define LOG_TAG "AF::PatchRecord"
3090
Andy Hung3ff4b552023-06-26 19:20:57 -07003091/* static */
3092sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003093 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003094 uint32_t sampleRate,
3095 audio_channel_mask_t channelMask,
3096 audio_format_t format,
3097 size_t frameCount,
3098 void *buffer,
3099 size_t bufferSize,
3100 audio_input_flags_t flags,
3101 const Timeout& timeout,
3102 audio_source_t source)
3103{
3104 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003105 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003106 sampleRate,
3107 channelMask,
3108 format,
3109 frameCount,
3110 buffer,
3111 bufferSize,
3112 flags,
3113 timeout,
3114 source);
3115}
3116
Andy Hung44f27182023-07-06 20:56:16 -07003117PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003118 uint32_t sampleRate,
3119 audio_channel_mask_t channelMask,
3120 audio_format_t format,
3121 size_t frameCount,
3122 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003123 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003124 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003125 const Timeout& timeout,
3126 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003127 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003128 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003129 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003130 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003131 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003132 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3133 : nullptr,
Andy Hung837229a2023-07-14 16:57:01 -07003134 recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003135{
Andy Hung9d84af52018-09-12 18:03:44 -07003136 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3137 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003138 (int)mPeerTimeout.tv_sec,
3139 (int)(mPeerTimeout.tv_nsec / 1000000));
3140}
3141
Andy Hung3ff4b552023-06-26 19:20:57 -07003142PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003143{
Andy Hungabfab202019-03-07 19:45:54 -08003144 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003145}
3146
Mikhail Naganov8296c252019-09-25 14:59:54 -07003147static size_t writeFramesHelper(
3148 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3149{
3150 AudioBufferProvider::Buffer patchBuffer;
3151 patchBuffer.frameCount = frameCount;
3152 auto status = dest->getNextBuffer(&patchBuffer);
3153 if (status != NO_ERROR) {
3154 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3155 __func__, status, strerror(-status));
3156 return 0;
3157 }
3158 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3159 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3160 size_t framesWritten = patchBuffer.frameCount;
3161 dest->releaseBuffer(&patchBuffer);
3162 return framesWritten;
3163}
3164
3165// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003166size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003167 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3168{
3169 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3170 // On buffer wrap, the buffer frame count will be less than requested,
3171 // when this happens a second buffer needs to be used to write the leftover audio
3172 const size_t framesLeft = frameCount - framesWritten;
3173 if (framesWritten != 0 && framesLeft != 0) {
3174 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3175 framesLeft, frameSize);
3176 }
3177 return framesWritten;
3178}
3179
Eric Laurent83b88082014-06-20 18:31:16 -07003180// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003181status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003182 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003183{
Andy Hung9d84af52018-09-12 18:03:44 -07003184 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003185 Proxy::Buffer buf;
3186 buf.mFrameCount = buffer->frameCount;
3187 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3188 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003189 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003190 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003191 if (ATRACE_ENABLED()) {
3192 std::string traceName("PRnObt");
3193 traceName += std::to_string(id());
3194 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3195 }
Eric Laurent83b88082014-06-20 18:31:16 -07003196 if (buf.mFrameCount == 0) {
3197 return WOULD_BLOCK;
3198 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003199 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003200 return status;
3201}
3202
Andy Hung3ff4b552023-06-26 19:20:57 -07003203void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003204{
Andy Hung9d84af52018-09-12 18:03:44 -07003205 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003206 Proxy::Buffer buf;
3207 buf.mFrameCount = buffer->frameCount;
3208 buf.mRaw = buffer->raw;
3209 mPeerProxy->releaseBuffer(&buf);
3210 TrackBase::releaseBuffer(buffer);
3211}
3212
Andy Hung3ff4b552023-06-26 19:20:57 -07003213status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003214 const struct timespec *timeOut)
3215{
3216 return mProxy->obtainBuffer(buffer, timeOut);
3217}
3218
Andy Hung3ff4b552023-06-26 19:20:57 -07003219void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003220{
3221 mProxy->releaseBuffer(buffer);
3222}
3223
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003224#undef LOG_TAG
3225#define LOG_TAG "AF::PthrPatchRecord"
3226
3227static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3228{
3229 void *ptr = nullptr;
3230 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003231 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003232}
3233
Andy Hung3ff4b552023-06-26 19:20:57 -07003234/* static */
3235sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003236 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003237 uint32_t sampleRate,
3238 audio_channel_mask_t channelMask,
3239 audio_format_t format,
3240 size_t frameCount,
3241 audio_input_flags_t flags,
3242 audio_source_t source)
3243{
3244 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003245 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003246 sampleRate,
3247 channelMask,
3248 format,
3249 frameCount,
3250 flags,
3251 source);
3252}
3253
3254PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003255 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003256 uint32_t sampleRate,
3257 audio_channel_mask_t channelMask,
3258 audio_format_t format,
3259 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003260 audio_input_flags_t flags,
3261 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003262 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003263 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003264 mPatchRecordAudioBufferProvider(*this),
3265 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3266 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3267{
3268 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3269}
3270
Andy Hung3ff4b552023-06-26 19:20:57 -07003271sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003272 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003273{
3274 *thread = mThread.promote();
3275 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003276 auto* const recordThread = (*thread)->asIAfRecordThread().get();
Andy Hung87e82412023-08-29 14:26:09 -07003277 audio_utils::lock_guard _l(recordThread->mutex());
Andy Hung44f27182023-07-06 20:56:16 -07003278 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003279}
3280
3281// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003282status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003283 Proxy::Buffer* buffer, const struct timespec* timeOut)
3284{
3285 if (mUnconsumedFrames) {
3286 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3287 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3288 return PatchRecord::obtainBuffer(buffer, timeOut);
3289 }
3290
3291 // Otherwise, execute a read from HAL and write into the buffer.
3292 nsecs_t startTimeNs = 0;
3293 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3294 // Will need to correct timeOut by elapsed time.
3295 startTimeNs = systemTime();
3296 }
3297 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3298 buffer->mFrameCount = 0;
3299 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003300 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003301 sp<StreamInHalInterface> stream = obtainStream(&thread);
3302 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3303
3304 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003305 size_t bytesRead = 0;
3306 {
3307 ATRACE_NAME("read");
3308 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3309 if (result != NO_ERROR) goto stream_error;
3310 if (bytesRead == 0) return NO_ERROR;
3311 }
3312
3313 {
Andy Hung094dc762023-08-28 19:12:14 -07003314 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003315 mReadBytes += bytesRead;
3316 mReadError = NO_ERROR;
3317 }
3318 mReadCV.notify_one();
3319 // writeFrames handles wraparound and should write all the provided frames.
3320 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3321 buffer->mFrameCount = writeFrames(
3322 &mPatchRecordAudioBufferProvider,
3323 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3324 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3325 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3326 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003327 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003328 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003329 // Correct the timeout by elapsed time.
3330 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003331 if (newTimeOutNs < 0) newTimeOutNs = 0;
3332 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3333 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003334 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003335 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003336 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003337
3338stream_error:
3339 stream->standby();
3340 {
Andy Hung094dc762023-08-28 19:12:14 -07003341 audio_utils::lock_guard lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003342 mReadError = result;
3343 }
3344 mReadCV.notify_one();
3345 return result;
3346}
3347
Andy Hung3ff4b552023-06-26 19:20:57 -07003348void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003349{
3350 if (buffer->mFrameCount <= mUnconsumedFrames) {
3351 mUnconsumedFrames -= buffer->mFrameCount;
3352 } else {
3353 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3354 buffer->mFrameCount, mUnconsumedFrames);
3355 mUnconsumedFrames = 0;
3356 }
3357 PatchRecord::releaseBuffer(buffer);
3358}
3359
3360// AudioBufferProvider and Source methods are called on RecordThread
3361// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3362// and 'releaseBuffer' are stubbed out and ignore their input.
3363// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3364// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003365status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003366 void* buffer, size_t bytes, size_t* read)
3367{
3368 bytes = std::min(bytes, mFrameCount * mFrameSize);
3369 {
Andy Hung094dc762023-08-28 19:12:14 -07003370 audio_utils::unique_lock lock(readMutex());
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003371 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3372 if (mReadError != NO_ERROR) {
3373 mLastReadFrames = 0;
3374 return mReadError;
3375 }
3376 *read = std::min(bytes, mReadBytes);
3377 mReadBytes -= *read;
3378 }
3379 mLastReadFrames = *read / mFrameSize;
3380 memset(buffer, 0, *read);
3381 return 0;
3382}
3383
Andy Hung3ff4b552023-06-26 19:20:57 -07003384status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003385 int64_t* frames, int64_t* time)
3386{
Andy Hung44f27182023-07-06 20:56:16 -07003387 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003388 sp<StreamInHalInterface> stream = obtainStream(&thread);
3389 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3390}
3391
Andy Hung3ff4b552023-06-26 19:20:57 -07003392status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003393{
3394 // RecordThread issues 'standby' command in two major cases:
3395 // 1. Error on read--this case is handled in 'obtainBuffer'.
3396 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3397 // output, this can only happen when the software patch
3398 // is being torn down. In this case, the RecordThread
3399 // will terminate and close the HAL stream.
3400 return 0;
3401}
3402
3403// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003404status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003405 AudioBufferProvider::Buffer* buffer)
3406{
3407 buffer->frameCount = mLastReadFrames;
3408 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3409 return NO_ERROR;
3410}
3411
Andy Hung3ff4b552023-06-26 19:20:57 -07003412void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003413 AudioBufferProvider::Buffer* buffer)
3414{
3415 buffer->frameCount = 0;
3416 buffer->raw = nullptr;
3417}
3418
Andy Hung9d84af52018-09-12 18:03:44 -07003419// ----------------------------------------------------------------------------
3420#undef LOG_TAG
3421#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003422
Andy Hung3ff4b552023-06-26 19:20:57 -07003423/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003424sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003425 const audio_attributes_t& attr,
3426 uint32_t sampleRate,
3427 audio_format_t format,
3428 audio_channel_mask_t channelMask,
3429 audio_session_t sessionId,
3430 bool isOut,
3431 const android::content::AttributionSourceState& attributionSource,
3432 pid_t creatorPid,
3433 audio_port_handle_t portId)
3434{
3435 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003436 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003437 attr,
3438 sampleRate,
3439 format,
3440 channelMask,
3441 sessionId,
3442 isOut,
3443 attributionSource,
3444 creatorPid,
3445 portId);
3446}
3447
Andy Hung44f27182023-07-06 20:56:16 -07003448MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003449 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003450 uint32_t sampleRate,
3451 audio_format_t format,
3452 audio_channel_mask_t channelMask,
3453 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003454 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003455 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003456 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003457 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003458 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003459 channelMask, (size_t)0 /* frameCount */,
3460 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003461 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003462 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003463 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003464 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003465 TYPE_DEFAULT, portId,
3466 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003467 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003468 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003469{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003470 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003471 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003472}
3473
Andy Hung3ff4b552023-06-26 19:20:57 -07003474MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003475{
3476}
3477
Andy Hung3ff4b552023-06-26 19:20:57 -07003478status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003479{
3480 return NO_ERROR;
3481}
3482
Andy Hung3ff4b552023-06-26 19:20:57 -07003483status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003484 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003485{
3486 return NO_ERROR;
3487}
3488
Andy Hung3ff4b552023-06-26 19:20:57 -07003489void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003490{
3491}
3492
3493// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003494status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003495{
3496 buffer->frameCount = 0;
3497 buffer->raw = nullptr;
3498 return INVALID_OPERATION;
3499}
3500
3501// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003502size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003503 return 0;
3504}
3505
Andy Hung3ff4b552023-06-26 19:20:57 -07003506int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003507{
3508 return 0;
3509}
3510
Andy Hung3ff4b552023-06-26 19:20:57 -07003511void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003512{
3513}
3514
Andy Hung3ff4b552023-06-26 19:20:57 -07003515void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003516{
3517 if (mMuteState == muteState) {
3518 // mute state did not change, do nothing
3519 return;
3520 }
3521
3522 status_t result = UNKNOWN_ERROR;
3523 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3524 if (mMuteEventExtras == nullptr) {
3525 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3526 }
3527 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3528 static_cast<int>(muteState));
3529
3530 result = audioManager->portEvent(mPortId,
3531 PLAYER_UPDATE_MUTED,
3532 mMuteEventExtras);
3533 }
3534
3535 if (result == OK) {
3536 mMuteState = muteState;
3537 } else {
3538 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3539 __func__,
3540 id(),
3541 mPortId,
3542 result);
3543 }
3544}
3545
Andy Hung3ff4b552023-06-26 19:20:57 -07003546void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003547{
Eric Laurent973db022018-11-20 14:54:31 -08003548 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003549 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003550}
3551
Andy Hung3ff4b552023-06-26 19:20:57 -07003552void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003553{
Eric Laurent973db022018-11-20 14:54:31 -08003554 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003555 mPid,
3556 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003557 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003558 mFormat,
3559 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003560 mSampleRate,
3561 mAttr.flags);
3562 if (isOut()) {
3563 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3564 } else {
3565 result.appendFormat("%6x", mAttr.source);
3566 }
3567 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003568}
3569
Glenn Kasten63238ef2015-03-02 15:50:29 -08003570} // namespace android