blob: b11479f99948d99291041ce6c4f3621235c4cb65 [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
18
19#define LOG_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
Mikhail Naganov938be412019-09-04 11:38:47 -070021#define ATRACE_TAG ATRACE_TAG_AUDIO
Eric Laurent81784c32012-11-19 14:55:58 -080022
Glenn Kasten153b9fe2013-07-15 11:23:36 -070023#include "Configuration.h"
Glenn Kastenad8510a2015-02-17 16:24:07 -080024#include <linux/futex.h>
Eric Laurent81784c32012-11-19 14:55:58 -080025#include <math.h>
Elliott Hughesee499292014-05-21 17:55:51 -070026#include <sys/syscall.h>
Eric Laurent81784c32012-11-19 14:55:58 -080027#include <utils/Log.h>
Mikhail Naganov938be412019-09-04 11:38:47 -070028#include <utils/Trace.h>
Eric Laurent81784c32012-11-19 14:55:58 -080029
30#include <private/media/AudioTrackShared.h>
31
Eric Laurent81784c32012-11-19 14:55:58 -080032#include "AudioFlinger.h"
Andy Hung3ff4b552023-06-26 19:20:57 -070033#include "TrackBase.h"
34#include "PlaybackTracks.h"
35#include "RecordTracks.h"
36#include "MmapTracks.h"
Eric Laurent81784c32012-11-19 14:55:58 -080037
Glenn Kastenda6ef132013-01-10 12:31:01 -080038#include <media/nbaio/Pipe.h>
39#include <media/nbaio/PipeReader.h>
Kuowei Lid4adbdb2020-08-13 14:44:25 +080040#include <media/AudioValidator.h>
Andy Hung89816052017-01-11 17:08:23 -080041#include <media/RecordBufferConverter.h>
Andy Hungab7ef302018-05-15 19:35:29 -070042#include <mediautils/ServiceUtilities.h>
Glenn Kastenc56f3422014-03-21 17:53:17 -070043#include <audio_utils/minifloat.h>
Glenn Kastenda6ef132013-01-10 12:31:01 -080044
Eric Laurent81784c32012-11-19 14:55:58 -080045// ----------------------------------------------------------------------------
46
47// Note: the following macro is used for extremely verbose logging message. In
48// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
49// 0; but one side effect of this is to turn all LOGV's as well. Some messages
50// are so verbose that we want to suppress them even when we have ALOG_ASSERT
51// turned on. Do not uncomment the #def below unless you really know what you
52// are doing and want to see all of the extremely verbose messages.
53//#define VERY_VERY_VERBOSE_LOGGING
54#ifdef VERY_VERY_VERBOSE_LOGGING
55#define ALOGVV ALOGV
56#else
57#define ALOGVV(a...) do { } while(0)
58#endif
59
Kuowei Lid4adbdb2020-08-13 14:44:25 +080060// TODO: Remove when this is put into AidlConversionUtil.h
61#define VALUE_OR_RETURN_BINDER_STATUS(x) \
62 ({ \
63 auto _tmp = (x); \
64 if (!_tmp.ok()) return ::android::aidl_utils::binderStatusFromStatusT(_tmp.error()); \
65 std::move(_tmp.value()); \
66 })
67
Eric Laurent81784c32012-11-19 14:55:58 -080068namespace android {
69
Kuowei Lid4adbdb2020-08-13 14:44:25 +080070using ::android::aidl_utils::binderStatusFromStatusT;
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -080071using binder::Status;
Svet Ganov33761132021-05-13 22:51:08 +000072using content::AttributionSourceState;
Ivan Lozano8cf3a072017-08-09 09:01:33 -070073using media::VolumeShaper;
Eric Laurent81784c32012-11-19 14:55:58 -080074// ----------------------------------------------------------------------------
75// TrackBase
76// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -070077#undef LOG_TAG
78#define LOG_TAG "AF::TrackBase"
Eric Laurent81784c32012-11-19 14:55:58 -080079
Glenn Kastenda6ef132013-01-10 12:31:01 -080080static volatile int32_t nextTrackId = 55;
81
Eric Laurent81784c32012-11-19 14:55:58 -080082// TrackBase constructor must be called with AudioFlinger::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -070083TrackBase::TrackBase(
Andy Hung44f27182023-07-06 20:56:16 -070084 IAfThreadBase *thread,
Eric Laurent81784c32012-11-19 14:55:58 -080085 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -070086 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -080087 uint32_t sampleRate,
88 audio_format_t format,
89 audio_channel_mask_t channelMask,
90 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -070091 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -070092 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -080093 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -070094 pid_t creatorPid,
Andy Hung1f12a8a2016-11-07 16:10:30 -080095 uid_t clientUid,
Glenn Kastend776ac62014-05-07 09:16:09 -070096 bool isOut,
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -070097 const alloc_type alloc,
Eric Laurent20b9ef02016-12-05 11:03:16 -080098 track_type type,
Andy Hungb68f5eb2019-12-03 16:49:17 -080099 audio_port_handle_t portId,
100 std::string metricsId)
Andy Hung02a6c4e2023-06-23 19:27:19 -0700101 :
Eric Laurent81784c32012-11-19 14:55:58 -0800102 mThread(thread),
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700103 mAllocType(alloc),
Eric Laurent81784c32012-11-19 14:55:58 -0800104 mClient(client),
105 mCblk(NULL),
Andy Hung8fe68032017-06-05 16:17:51 -0700106 // mBuffer, mBufferSize
Eric Laurent81784c32012-11-19 14:55:58 -0800107 mState(IDLE),
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700108 mAttr(attr),
Eric Laurent81784c32012-11-19 14:55:58 -0800109 mSampleRate(sampleRate),
110 mFormat(format),
111 mChannelMask(channelMask),
Andy Hunge5412692014-05-16 11:25:07 -0700112 mChannelCount(isOut ?
113 audio_channel_count_from_out_mask(channelMask) :
114 audio_channel_count_from_in_mask(channelMask)),
Phil Burkfdb3c072016-02-09 10:47:02 -0800115 mFrameSize(audio_has_proportional_frames(format) ?
Eric Laurent81784c32012-11-19 14:55:58 -0800116 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
117 mFrameCount(frameCount),
Glenn Kastene3aa6592012-12-04 12:22:46 -0800118 mSessionId(sessionId),
119 mIsOut(isOut),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800120 mId(android_atomic_inc(&nextTrackId)),
Eric Laurent83b88082014-06-20 18:31:16 -0700121 mTerminated(false),
Eric Laurentaaa44472014-09-12 17:41:50 -0700122 mType(type),
Kevin Rocard153f92d2018-12-18 18:33:28 -0800123 mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
Eric Laurent6acd1d42017-01-04 14:23:29 -0800124 mPortId(portId),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700125 mIsInvalid(false),
Kunal Malhotra3be68902023-02-28 22:03:15 +0000126 mTrackMetrics(std::move(metricsId), isOut, clientUid),
Eric Laurent09f1ed22019-04-24 17:45:17 -0700127 mCreatorPid(creatorPid)
Eric Laurent81784c32012-11-19 14:55:58 -0800128{
Marco Nelissendcb346b2015-09-09 10:47:29 -0700129 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
Andy Hung4ef19fa2018-05-15 19:35:29 -0700130 if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
Andy Hung1f12a8a2016-11-07 16:10:30 -0800131 ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
Andy Hung9d84af52018-09-12 18:03:44 -0700132 "%s(%d): uid %d tried to pass itself off as %d",
133 __func__, mId, callingUid, clientUid);
Andy Hung1f12a8a2016-11-07 16:10:30 -0800134 clientUid = callingUid;
Marco Nelissen462fd2f2013-01-14 14:12:05 -0800135 }
136 // clientUid contains the uid of the app that is responsible for this track, so we can blame
137 // battery usage on it.
138 mUid = clientUid;
139
Eric Laurent81784c32012-11-19 14:55:58 -0800140 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
Andy Hung1883f692017-02-13 18:48:39 -0800141
Andy Hung8fe68032017-06-05 16:17:51 -0700142 size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
Andy Hung1883f692017-02-13 18:48:39 -0800143 // check overflow when computing bufferSize due to multiplication by mFrameSize.
Andy Hung8fe68032017-06-05 16:17:51 -0700144 if (minBufferSize < frameCount // roundup rounds down for values above UINT_MAX / 2
Andy Hung1883f692017-02-13 18:48:39 -0800145 || mFrameSize == 0 // format needs to be correct
Andy Hung8fe68032017-06-05 16:17:51 -0700146 || minBufferSize > SIZE_MAX / mFrameSize) {
Andy Hung1883f692017-02-13 18:48:39 -0800147 android_errorWriteLog(0x534e4554, "34749571");
148 return;
149 }
Andy Hung8fe68032017-06-05 16:17:51 -0700150 minBufferSize *= mFrameSize;
151
152 if (buffer == nullptr) {
153 bufferSize = minBufferSize; // allocated here.
154 } else if (minBufferSize > bufferSize) {
155 android_errorWriteLog(0x534e4554, "38340117");
156 return;
157 }
Andy Hung1883f692017-02-13 18:48:39 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 size_t size = sizeof(audio_track_cblk_t);
Eric Laurent83b88082014-06-20 18:31:16 -0700160 if (buffer == NULL && alloc == ALLOC_CBLK) {
Andy Hung1883f692017-02-13 18:48:39 -0800161 // check overflow when computing allocation size for streaming tracks.
162 if (size > SIZE_MAX - bufferSize) {
163 android_errorWriteLog(0x534e4554, "34749571");
164 return;
165 }
Eric Laurent81784c32012-11-19 14:55:58 -0800166 size += bufferSize;
167 }
168
169 if (client != 0) {
Atneya3c61d882021-09-20 14:52:15 -0400170 mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{{size},
171 std::string("Track ID: ").append(std::to_string(mId))});
Glenn Kasten663c2242013-09-24 11:52:37 -0700172 if (mCblkMemory == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700173 (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700174 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Atneya3c61d882021-09-20 14:52:15 -0400175 ALOGE("%s", client->allocator().dump().c_str());
Glenn Kasten663c2242013-09-24 11:52:37 -0700176 mCblkMemory.clear();
Eric Laurent81784c32012-11-19 14:55:58 -0800177 return;
178 }
179 } else {
Andy Hungafb31482017-02-13 18:50:48 -0800180 mCblk = (audio_track_cblk_t *) malloc(size);
181 if (mCblk == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700182 ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
Andy Hungafb31482017-02-13 18:50:48 -0800183 return;
184 }
Eric Laurent81784c32012-11-19 14:55:58 -0800185 }
186
187 // construct the shared structure in-place.
188 if (mCblk != NULL) {
189 new(mCblk) audio_track_cblk_t();
Glenn Kastenc263ca02014-06-04 20:31:46 -0700190 switch (alloc) {
191 case ALLOC_READONLY: {
Glenn Kastend776ac62014-05-07 09:16:09 -0700192 const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
193 if (roHeap == 0 ||
194 (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700195 (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
Andy Hung9d84af52018-09-12 18:03:44 -0700196 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
197 __func__, mId, bufferSize);
Glenn Kastend776ac62014-05-07 09:16:09 -0700198 if (roHeap != 0) {
199 roHeap->dump("buffer");
200 }
201 mCblkMemory.clear();
202 mBufferMemory.clear();
203 return;
204 }
Eric Laurent81784c32012-11-19 14:55:58 -0800205 memset(mBuffer, 0, bufferSize);
Glenn Kastenc263ca02014-06-04 20:31:46 -0700206 } break;
207 case ALLOC_PIPE:
208 mBufferMemory = thread->pipeMemory();
209 // mBuffer is the virtual address as seen from current process (mediaserver),
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700210 // and should normally be coming from mBufferMemory->unsecurePointer().
Glenn Kastenc263ca02014-06-04 20:31:46 -0700211 // However in this case the TrackBase does not reference the buffer directly.
212 // It should references the buffer via the pipe.
213 // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
214 mBuffer = NULL;
Andy Hung8fe68032017-06-05 16:17:51 -0700215 bufferSize = 0;
Glenn Kastenc263ca02014-06-04 20:31:46 -0700216 break;
217 case ALLOC_CBLK:
Glenn Kastend776ac62014-05-07 09:16:09 -0700218 // clear all buffers
Eric Laurent83b88082014-06-20 18:31:16 -0700219 if (buffer == NULL) {
Glenn Kastend776ac62014-05-07 09:16:09 -0700220 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
221 memset(mBuffer, 0, bufferSize);
222 } else {
Eric Laurent83b88082014-06-20 18:31:16 -0700223 mBuffer = buffer;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800224#if 0
Glenn Kastend776ac62014-05-07 09:16:09 -0700225 mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800226#endif
Glenn Kastend776ac62014-05-07 09:16:09 -0700227 }
Glenn Kastenc263ca02014-06-04 20:31:46 -0700228 break;
Eric Laurent83b88082014-06-20 18:31:16 -0700229 case ALLOC_LOCAL:
230 mBuffer = calloc(1, bufferSize);
231 break;
232 case ALLOC_NONE:
233 mBuffer = buffer;
234 break;
Andy Hung8fe68032017-06-05 16:17:51 -0700235 default:
Andy Hung9d84af52018-09-12 18:03:44 -0700236 LOG_ALWAYS_FATAL("%s(%d): invalid allocation type: %d", __func__, mId, (int)alloc);
Eric Laurent81784c32012-11-19 14:55:58 -0800237 }
Andy Hung8fe68032017-06-05 16:17:51 -0700238 mBufferSize = bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800239
Glenn Kasten46909e72013-02-26 09:20:22 -0800240#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700241 mTee.set(sampleRate, mChannelCount, format, NBAIO_Tee::TEE_FLAG_TRACK);
Glenn Kasten46909e72013-02-26 09:20:22 -0800242#endif
Andy Hung959b5b82021-09-24 10:46:20 -0700243 // mState is mirrored for the client to read.
244 mState.setMirror(&mCblk->mState);
245 // ensure our state matches up until we consolidate the enumeration.
246 static_assert(CBLK_STATE_IDLE == IDLE);
247 static_assert(CBLK_STATE_PAUSING == PAUSING);
Eric Laurent81784c32012-11-19 14:55:58 -0800248 }
249}
250
Svet Ganov33761132021-05-13 22:51:08 +0000251// TODO b/182392769: use attribution source util
252static AttributionSourceState audioServerAttributionSource(pid_t pid) {
253 AttributionSourceState attributionSource{};
254 attributionSource.uid = AID_AUDIOSERVER;
255 attributionSource.pid = pid;
256 attributionSource.token = sp<BBinder>::make();
257 return attributionSource;
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700258}
259
Andy Hung3ff4b552023-06-26 19:20:57 -0700260status_t TrackBase::initCheck() const
Eric Laurent83b88082014-06-20 18:31:16 -0700261{
262 status_t status;
263 if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
264 status = cblk() != NULL ? NO_ERROR : NO_MEMORY;
265 } else {
266 status = getCblk() != 0 ? NO_ERROR : NO_MEMORY;
267 }
268 return status;
269}
270
Andy Hung3ff4b552023-06-26 19:20:57 -0700271TrackBase::~TrackBase()
Eric Laurent81784c32012-11-19 14:55:58 -0800272{
Glenn Kastene3aa6592012-12-04 12:22:46 -0800273 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
Eric Laurent5bba2f62016-03-18 11:14:14 -0700274 mServerProxy.clear();
Andy Hung689e82c2019-08-21 17:53:17 -0700275 releaseCblk();
Eric Laurent81784c32012-11-19 14:55:58 -0800276 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
277 if (mClient != 0) {
Eric Laurent021cf962014-05-13 10:18:14 -0700278 // Client destructor must run with AudioFlinger client mutex locked
279 Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
Eric Laurent81784c32012-11-19 14:55:58 -0800280 // If the client's reference count drops to zero, the associated destructor
281 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
282 // relying on the automatic clear() at end of scope.
283 mClient.clear();
284 }
Dmitry Sidorenkova41c2732023-05-15 13:47:07 -0700285 if (mAllocType == ALLOC_LOCAL) {
286 free(mBuffer);
287 mBuffer = nullptr;
288 }
Eric Laurent3bcffa12014-06-12 18:38:45 -0700289 // flush the binder command buffer
290 IPCThreadState::self()->flushCommands();
Eric Laurent81784c32012-11-19 14:55:58 -0800291}
292
293// AudioBufferProvider interface
294// getNextBuffer() = 0;
Glenn Kastend79072e2016-01-06 08:41:20 -0800295// This implementation of releaseBuffer() is used by Track and RecordTrack
Andy Hung3ff4b552023-06-26 19:20:57 -0700296void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -0800297{
Glenn Kasten46909e72013-02-26 09:20:22 -0800298#ifdef TEE_SINK
Andy Hung8946a282018-04-19 20:04:56 -0700299 mTee.write(buffer->raw, buffer->frameCount);
Glenn Kasten46909e72013-02-26 09:20:22 -0800300#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800301
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800302 ServerProxy::Buffer buf;
303 buf.mFrameCount = buffer->frameCount;
304 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800305 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800306 buffer->raw = NULL;
307 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800308}
309
Andy Hung3ff4b552023-06-26 19:20:57 -0700310status_t TrackBase::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -0700311 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -0800312{
Andy Hung068e08e2023-05-15 19:02:55 -0700313 mSyncEvents.emplace_back(event);
Eric Laurent81784c32012-11-19 14:55:58 -0800314 return NO_ERROR;
315}
316
Andy Hung3ff4b552023-06-26 19:20:57 -0700317PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
Andy Hung44f27182023-07-06 20:56:16 -0700318 const IAfThreadBase& thread, const Timeout& timeout)
Kevin Rocard45986c72018-12-18 18:22:59 -0800319 : mProxy(proxy)
320{
321 if (timeout) {
322 setPeerTimeout(*timeout);
323 } else {
324 // Double buffer mixer
325 uint64_t mixBufferNs = ((uint64_t)2 * thread.frameCount() * 1000000000) /
326 thread.sampleRate();
327 setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
328 }
329}
330
Andy Hung3ff4b552023-06-26 19:20:57 -0700331void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
Kevin Rocard45986c72018-12-18 18:22:59 -0800332 mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
333 mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
334}
335
336
Eric Laurent81784c32012-11-19 14:55:58 -0800337// ----------------------------------------------------------------------------
338// Playback
339// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700340#undef LOG_TAG
341#define LOG_TAG "AF::TrackHandle"
Eric Laurent81784c32012-11-19 14:55:58 -0800342
Andy Hungaaa18282023-06-23 19:27:19 -0700343class TrackHandle : public android::media::BnAudioTrack {
344public:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700345 explicit TrackHandle(const sp<IAfTrack>& track);
Andy Hungaaa18282023-06-23 19:27:19 -0700346 ~TrackHandle() override;
347
348 binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
349 binder::Status start(int32_t* _aidl_return) final;
350 binder::Status stop() final;
351 binder::Status flush() final;
352 binder::Status pause() final;
353 binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
354 binder::Status setParameters(const std::string& keyValuePairs,
355 int32_t* _aidl_return) final;
356 binder::Status selectPresentation(int32_t presentationId, int32_t programId,
357 int32_t* _aidl_return) final;
358 binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
359 int32_t* _aidl_return) final;
360 binder::Status signal() final;
361 binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
362 const media::VolumeShaperOperation& operation,
363 int32_t* _aidl_return) final;
364 binder::Status getVolumeShaperState(
365 int32_t id,
366 std::optional<media::VolumeShaperState>* _aidl_return) final;
367 binder::Status getDualMonoMode(
368 media::audio::common::AudioDualMonoMode* _aidl_return) final;
369 binder::Status setDualMonoMode(
370 media::audio::common::AudioDualMonoMode mode) final;
371 binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
372 binder::Status setAudioDescriptionMixLevel(float leveldB) final;
373 binder::Status getPlaybackRateParameters(
374 media::audio::common::AudioPlaybackRate* _aidl_return) final;
375 binder::Status setPlaybackRateParameters(
376 const media::audio::common::AudioPlaybackRate& playbackRate) final;
377
378private:
Andy Hung02a6c4e2023-06-23 19:27:19 -0700379 const sp<IAfTrack> mTrack;
Andy Hungaaa18282023-06-23 19:27:19 -0700380};
381
382/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -0700383sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
Andy Hungaaa18282023-06-23 19:27:19 -0700384 return sp<TrackHandle>::make(track);
385}
386
Andy Hung02a6c4e2023-06-23 19:27:19 -0700387TrackHandle::TrackHandle(const sp<IAfTrack>& track)
Eric Laurent81784c32012-11-19 14:55:58 -0800388 : BnAudioTrack(),
389 mTrack(track)
390{
Andy Hungaaa18282023-06-23 19:27:19 -0700391 // TODO(b/288339104) binder thread priority change not needed.
Andy Hung225aef62022-12-06 16:33:20 -0800392 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -0800393}
394
Andy Hungaaa18282023-06-23 19:27:19 -0700395TrackHandle::~TrackHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -0800396 // just stop the track on deletion, associated resources
397 // will be freed from the main thread once all pending buffers have
398 // been played. Unless it's not in the active track list, in which
399 // case we free everything now...
400 mTrack->destroy();
401}
402
Andy Hungaaa18282023-06-23 19:27:19 -0700403Status TrackHandle::getCblk(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800404 std::optional<media::SharedFileRegion>* _aidl_return) {
405 *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
406 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800407}
408
Andy Hungaaa18282023-06-23 19:27:19 -0700409Status TrackHandle::start(int32_t* _aidl_return) {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800410 *_aidl_return = mTrack->start();
411 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800412}
413
Andy Hungaaa18282023-06-23 19:27:19 -0700414Status TrackHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -0800415 mTrack->stop();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800416 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800417}
418
Andy Hungaaa18282023-06-23 19:27:19 -0700419Status TrackHandle::flush() {
Eric Laurent81784c32012-11-19 14:55:58 -0800420 mTrack->flush();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800421 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800422}
423
Andy Hungaaa18282023-06-23 19:27:19 -0700424Status TrackHandle::pause() {
Eric Laurent81784c32012-11-19 14:55:58 -0800425 mTrack->pause();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800426 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800427}
428
Andy Hungaaa18282023-06-23 19:27:19 -0700429Status TrackHandle::attachAuxEffect(int32_t effectId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800430 int32_t* _aidl_return) {
431 *_aidl_return = mTrack->attachAuxEffect(effectId);
432 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800433}
434
Andy Hungaaa18282023-06-23 19:27:19 -0700435Status TrackHandle::setParameters(const std::string& keyValuePairs,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800436 int32_t* _aidl_return) {
437 *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
438 return Status::ok();
Glenn Kasten3dcd00d2013-07-17 10:10:23 -0700439}
440
Andy Hungaaa18282023-06-23 19:27:19 -0700441Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800442 int32_t* _aidl_return) {
443 *_aidl_return = mTrack->selectPresentation(presentationId, programId);
444 return Status::ok();
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800445}
446
Andy Hungaaa18282023-06-23 19:27:19 -0700447Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800448 int32_t* _aidl_return) {
449 AudioTimestamp legacy;
450 *_aidl_return = mTrack->getTimestamp(legacy);
451 if (*_aidl_return != OK) {
452 return Status::ok();
453 }
Andy Hung973638a2020-12-08 20:47:45 -0800454 *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800455 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800456}
457
Andy Hungaaa18282023-06-23 19:27:19 -0700458Status TrackHandle::signal() {
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800459 mTrack->signal();
460 return Status::ok();
Andy Hung9fc8b5c2017-01-24 13:36:48 -0800461}
462
Andy Hungaaa18282023-06-23 19:27:19 -0700463Status TrackHandle::applyVolumeShaper(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800464 const media::VolumeShaperConfiguration& configuration,
465 const media::VolumeShaperOperation& operation,
466 int32_t* _aidl_return) {
467 sp<VolumeShaper::Configuration> conf = new VolumeShaper::Configuration();
468 *_aidl_return = conf->readFromParcelable(configuration);
469 if (*_aidl_return != OK) {
470 return Status::ok();
471 }
472
473 sp<VolumeShaper::Operation> op = new VolumeShaper::Operation();
474 *_aidl_return = op->readFromParcelable(operation);
475 if (*_aidl_return != OK) {
476 return Status::ok();
477 }
478
479 *_aidl_return = mTrack->applyVolumeShaper(conf, op);
480 return Status::ok();
Glenn Kasten53cec222013-08-29 09:01:02 -0700481}
482
Andy Hungaaa18282023-06-23 19:27:19 -0700483Status TrackHandle::getVolumeShaperState(
Ytai Ben-Tsvibdc293a2020-11-02 17:01:38 -0800484 int32_t id,
485 std::optional<media::VolumeShaperState>* _aidl_return) {
486 sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
487 if (legacy == nullptr) {
488 _aidl_return->reset();
489 return Status::ok();
490 }
491 media::VolumeShaperState aidl;
492 legacy->writeToParcelable(&aidl);
493 *_aidl_return = aidl;
494 return Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -0800495}
496
Andy Hungaaa18282023-06-23 19:27:19 -0700497Status TrackHandle::getDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000498 media::audio::common::AudioDualMonoMode* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800499{
500 audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
501 const status_t status = mTrack->getDualMonoMode(&mode)
502 ?: AudioValidator::validateDualMonoMode(mode);
503 if (status == OK) {
504 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
505 legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
506 }
507 return binderStatusFromStatusT(status);
508}
509
Andy Hungaaa18282023-06-23 19:27:19 -0700510Status TrackHandle::setDualMonoMode(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000511 media::audio::common::AudioDualMonoMode mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800512{
513 const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
514 aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
515 return binderStatusFromStatusT(AudioValidator::validateDualMonoMode(localMonoMode)
516 ?: mTrack->setDualMonoMode(localMonoMode));
517}
518
Andy Hungaaa18282023-06-23 19:27:19 -0700519Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800520{
521 float leveldB = -std::numeric_limits<float>::infinity();
522 const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
523 ?: AudioValidator::validateAudioDescriptionMixLevel(leveldB);
524 if (status == OK) *_aidl_return = leveldB;
525 return binderStatusFromStatusT(status);
526}
527
Andy Hungaaa18282023-06-23 19:27:19 -0700528Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800529{
530 return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
531 ?: mTrack->setAudioDescriptionMixLevel(leveldB));
532}
533
Andy Hungaaa18282023-06-23 19:27:19 -0700534Status TrackHandle::getPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000535 media::audio::common::AudioPlaybackRate* _aidl_return)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800536{
537 audio_playback_rate_t localPlaybackRate{};
538 status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
539 ?: AudioValidator::validatePlaybackRate(localPlaybackRate);
540 if (status == NO_ERROR) {
541 *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
542 legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(localPlaybackRate));
543 }
544 return binderStatusFromStatusT(status);
545}
546
Andy Hungaaa18282023-06-23 19:27:19 -0700547Status TrackHandle::setPlaybackRateParameters(
Mikhail Naganova77d5552022-12-18 02:48:14 +0000548 const media::audio::common::AudioPlaybackRate& playbackRate)
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800549{
550 const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
551 aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
552 return binderStatusFromStatusT(AudioValidator::validatePlaybackRate(localPlaybackRate)
553 ?: mTrack->setPlaybackRateParameters(localPlaybackRate));
554}
555
Eric Laurent81784c32012-11-19 14:55:58 -0800556// ----------------------------------------------------------------------------
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800557// AppOp for audio playback
558// -------------------------------
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700559
560// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700561sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
Andy Hung44f27182023-07-06 20:56:16 -0700562 IAfThreadBase* thread,
Svet Ganov33761132021-05-13 22:51:08 +0000563 const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700564 audio_stream_type_t streamType)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800565{
Vlad Popa103be862023-07-10 20:27:41 -0700566 Vector<String16> packages;
567 const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000568 getPackagesForUid(uid, packages);
Eric Laurent9066ad32019-05-20 14:40:10 -0700569 if (isServiceUid(uid)) {
Eric Laurent9066ad32019-05-20 14:40:10 -0700570 if (packages.isEmpty()) {
571 ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
572 id,
573 attr.usage,
574 uid);
575 return nullptr;
576 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800577 }
578 // stream type has been filtered by audio policy to indicate whether it can be muted
579 if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
Eric Laurent2dab0302019-05-08 18:15:55 -0700580 ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, attr.usage);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700581 return nullptr;
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800582 }
Eric Laurent2dab0302019-05-08 18:15:55 -0700583 if ((attr.flags & AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY)
584 == AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY) {
585 ALOGD("OpPlayAudio: not muting track:%d flags %#x have FLAG_BYPASS_INTERRUPTION_POLICY",
586 id, attr.flags);
587 return nullptr;
588 }
Vlad Popa103be862023-07-10 20:27:41 -0700589 return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700590}
591
Andy Hung44f27182023-07-06 20:56:16 -0700592OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
593 const AttributionSourceState& attributionSource,
594 audio_usage_t usage, int id, uid_t uid)
595 : mThread(wp<IAfThreadBase>::fromExisting(thread)),
Vlad Popa103be862023-07-10 20:27:41 -0700596 mHasOpPlayAudio(true),
597 mAttributionSource(attributionSource),
598 mUsage((int32_t)usage),
599 mId(id),
600 mUid(uid),
601 mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
602 attributionSource.packageName.value_or("")))) {}
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800603
Andy Hung3ff4b552023-06-26 19:20:57 -0700604OpPlayAudioMonitor::~OpPlayAudioMonitor()
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800605{
606 if (mOpCallback != 0) {
607 mAppOpsManager.stopWatchingMode(mOpCallback);
608 }
609 mOpCallback.clear();
610}
611
Andy Hung3ff4b552023-06-26 19:20:57 -0700612void OpPlayAudioMonitor::onFirstRef()
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700613{
Vlad Popad2152122023-08-02 18:36:04 -0700614 // make sure not to broadcast the initial state since it is not needed and could
615 // cause a deadlock since this method can be called with the mThread->mLock held
616 checkPlayAudioForUsage(/*doBroadcast=*/false);
Svet Ganov33761132021-05-13 22:51:08 +0000617 if (mAttributionSource.packageName.has_value()) {
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700618 mOpCallback = new PlayAudioOpCallback(this);
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700619 mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
Vlad Popa103be862023-07-10 20:27:41 -0700620 mPackageName, mOpCallback);
Mikhail Naganovf7e3a3a2019-04-22 16:43:26 -0700621 }
622}
623
Andy Hung3ff4b552023-06-26 19:20:57 -0700624bool OpPlayAudioMonitor::hasOpPlayAudio() const {
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800625 return mHasOpPlayAudio.load();
626}
627
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -0700628// Note this method is never called (and never to be) for audio server / patch record track
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800629// - not called from constructor due to check on UID,
630// - not called from PlayAudioOpCallback because the callback is not installed in this case
Andy Hung3ff4b552023-06-26 19:20:57 -0700631void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800632{
Vlad Popa103be862023-07-10 20:27:41 -0700633 const bool hasAppOps = mAttributionSource.packageName.has_value()
634 && mAppOpsManager.checkAudioOpNoThrow(
635 AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
636 AppOpsManager::MODE_ALLOWED;
637
638 bool shouldChange = !hasAppOps; // check if we need to update.
639 if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
640 ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
Vlad Popad2152122023-08-02 18:36:04 -0700641 if (doBroadcast) {
642 auto thread = mThread.promote();
643 if (thread != nullptr && thread->type() == AudioFlinger::ThreadBase::OFFLOAD) {
644 // Wake up Thread if offloaded, otherwise it may be several seconds for update.
Andy Hung44f27182023-07-06 20:56:16 -0700645 Mutex::Autolock _l(thread->mutex());
Vlad Popad2152122023-08-02 18:36:04 -0700646 thread->broadcast_l();
647 }
Vlad Popa103be862023-07-10 20:27:41 -0700648 }
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800649 }
650}
651
Andy Hung3ff4b552023-06-26 19:20:57 -0700652OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800653 const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
654{ }
655
Andy Hung3ff4b552023-06-26 19:20:57 -0700656void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800657 const String16& packageName) {
658 // we only have uid, so we need to check all package names anyway
659 UNUSED(packageName);
660 if (op != AppOpsManager::OP_PLAY_AUDIO) {
661 return;
662 }
663 sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
664 if (monitor != NULL) {
Vlad Popad2152122023-08-02 18:36:04 -0700665 monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800666 }
667}
668
Eric Laurent9066ad32019-05-20 14:40:10 -0700669// static
Andy Hung3ff4b552023-06-26 19:20:57 -0700670void OpPlayAudioMonitor::getPackagesForUid(
Eric Laurent9066ad32019-05-20 14:40:10 -0700671 uid_t uid, Vector<String16>& packages)
672{
673 PermissionController permissionController;
674 permissionController.getPackagesForUid(uid, packages);
675}
676
Jean-Michel Trivi74e01fa2019-02-25 12:18:09 -0800677// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -0700678#undef LOG_TAG
679#define LOG_TAG "AF::Track"
Eric Laurent81784c32012-11-19 14:55:58 -0800680
Andy Hung3ff4b552023-06-26 19:20:57 -0700681/* static */
Andy Hung44f27182023-07-06 20:56:16 -0700682sp<IAfTrack> IAfTrack::create(
683 IAfPlaybackThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700684 const sp<Client>& client,
685 audio_stream_type_t streamType,
686 const audio_attributes_t& attr,
687 uint32_t sampleRate,
688 audio_format_t format,
689 audio_channel_mask_t channelMask,
690 size_t frameCount,
691 void *buffer,
692 size_t bufferSize,
693 const sp<IMemory>& sharedBuffer,
694 audio_session_t sessionId,
695 pid_t creatorPid,
696 const AttributionSourceState& attributionSource,
697 audio_output_flags_t flags,
698 track_type type,
699 audio_port_handle_t portId,
700 /** default behaviour is to start when there are as many frames
701 * ready as possible (aka. Buffer is full). */
702 size_t frameCountToBeReady,
703 float speed,
704 bool isSpatialized,
705 bool isBitPerfect) {
Andy Hung44f27182023-07-06 20:56:16 -0700706 return sp<Track>::make(thread,
Andy Hung3ff4b552023-06-26 19:20:57 -0700707 client,
708 streamType,
709 attr,
710 sampleRate,
711 format,
712 channelMask,
713 frameCount,
714 buffer,
715 bufferSize,
716 sharedBuffer,
717 sessionId,
718 creatorPid,
719 attributionSource,
720 flags,
721 type,
722 portId,
723 frameCountToBeReady,
724 speed,
725 isSpatialized,
726 isBitPerfect);
727}
728
Eric Laurent81784c32012-11-19 14:55:58 -0800729// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -0700730Track::Track(
Andy Hung44f27182023-07-06 20:56:16 -0700731 IAfPlaybackThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -0800732 const sp<Client>& client,
733 audio_stream_type_t streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700734 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -0800735 uint32_t sampleRate,
736 audio_format_t format,
737 audio_channel_mask_t channelMask,
738 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700739 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700740 size_t bufferSize,
Eric Laurent81784c32012-11-19 14:55:58 -0800741 const sp<IMemory>& sharedBuffer,
Glenn Kastend848eb42016-03-08 13:42:11 -0800742 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -0700743 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000744 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -0700745 audio_output_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -0800746 track_type type,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +0100747 audio_port_handle_t portId,
jiabinf042b9b2021-05-07 23:46:28 +0000748 size_t frameCountToBeReady,
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200749 float speed,
jiabinc658e452022-10-21 20:52:21 +0000750 bool isSpatialized,
751 bool isBitPerfect)
Kevin Rocard1f564ac2018-03-29 13:53:10 -0700752 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700753 // TODO: Using unsecurePointer() has some associated security pitfalls
754 // (see declaration for details).
755 // Either document why it is safe in this case or address the
756 // issue (e.g. by copying).
757 (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
Andy Hung8fe68032017-06-05 16:17:51 -0700758 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700759 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +0000760 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -0700761 (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
Andy Hungb68f5eb2019-12-03 16:49:17 -0800762 type,
763 portId,
764 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
Andy Hung3ff4b552023-06-26 19:20:57 -0700765 mFillingStatus(FS_INVALID),
Eric Laurent81784c32012-11-19 14:55:58 -0800766 // mRetryCount initialized later when needed
767 mSharedBuffer(sharedBuffer),
768 mStreamType(streamType),
rago94a1ee82017-07-21 15:11:02 -0700769 mMainBuffer(thread->sinkBuffer()),
Eric Laurent81784c32012-11-19 14:55:58 -0800770 mAuxBuffer(NULL),
771 mAuxEffectId(0), mHasVolumeController(false),
Andy Hunge10393e2015-06-12 13:59:33 -0700772 mFrameMap(16 /* sink-frame-to-track-frame map memory */),
Ivan Lozano8cf3a072017-08-09 09:01:33 -0700773 mVolumeHandler(new media::VolumeHandler(sampleRate)),
Vlad Popa103be862023-07-10 20:27:41 -0700774 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(),
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700775 streamType)),
Andy Hunge10393e2015-06-12 13:59:33 -0700776 // mSinkTimestamp
Eric Laurent81784c32012-11-19 14:55:58 -0800777 mFastIndex(-1),
Glenn Kasten5736c352012-12-04 12:12:34 -0800778 mCachedVolume(1.0),
Kevin Rocard12381092018-04-11 09:19:59 -0700779 /* The track might not play immediately after being active, similarly as if its volume was 0.
780 * When the track starts playing, its volume will be computed. */
781 mFinalVolume(0.f),
Haynes Mathew George7844f672014-01-15 12:32:55 -0800782 mResumeToStopping(false),
Eric Laurent05067782016-06-01 18:27:28 -0700783 mFlushHwPending(false),
jiabinf042b9b2021-05-07 23:46:28 +0000784 mFlags(flags),
Eric Laurentb0a7bc92022-04-05 15:06:08 +0200785 mSpeed(speed),
jiabinc658e452022-10-21 20:52:21 +0000786 mIsSpatialized(isSpatialized),
787 mIsBitPerfect(isBitPerfect)
Eric Laurent81784c32012-11-19 14:55:58 -0800788{
Eric Laurent83b88082014-06-20 18:31:16 -0700789 // client == 0 implies sharedBuffer == 0
790 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
791
Andy Hung9d84af52018-09-12 18:03:44 -0700792 ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700793 __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
Eric Laurent83b88082014-06-20 18:31:16 -0700794
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700795 if (mCblk == NULL) {
796 return;
Eric Laurent81784c32012-11-19 14:55:58 -0800797 }
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700798
Svet Ganov33761132021-05-13 22:51:08 +0000799 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
Andy Hung689e82c2019-08-21 17:53:17 -0700800 if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
801 ALOGE("%s(%d): no more tracks available", __func__, mId);
802 releaseCblk(); // this makes the track invalid.
803 return;
804 }
805
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700806 if (sharedBuffer == 0) {
807 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -0700808 mFrameSize, !isExternalTrack(), sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700809 } else {
810 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
Kevin Rocard36862032019-10-10 10:52:19 +0100811 mFrameSize, sampleRate);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700812 }
813 mServerProxy = mAudioTrackServerProxy;
Andy Hung3c7f47a2021-03-16 17:30:09 -0700814 mServerProxy->setStartThresholdInFrames(frameCountToBeReady); // update the Cblk value
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700815
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700816 // only allocate a fast track index if we were able to allocate a normal track name
Eric Laurent05067782016-06-01 18:27:28 -0700817 if (flags & AUDIO_OUTPUT_FLAG_FAST) {
Andy Hunga5427822015-09-11 16:15:35 -0700818 // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
819 // race with setSyncEvent(). However, if we call it, we cannot properly start
820 // static fast tracks (SoundPool) immediately after stopping.
821 //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Andy Hung44f27182023-07-06 20:56:16 -0700822 ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
823 const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
Glenn Kastendc2c50b2016-04-21 08:13:14 -0700824 ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700825 // FIXME This is too eager. We allocate a fast track index before the
826 // fast track becomes active. Since fast tracks are a scarce resource,
827 // this means we are potentially denying other more important fast tracks from
828 // being created. It would be better to allocate the index dynamically.
829 mFastIndex = i;
Andy Hung44f27182023-07-06 20:56:16 -0700830 thread->fastTrackAvailMask_l() &= ~(1 << i);
Glenn Kasten3ef14ef2014-03-13 15:08:51 -0700831 }
Andy Hung8946a282018-04-19 20:04:56 -0700832
Dean Wheatley7b036912020-06-18 16:22:11 +1000833 mServerLatencySupported = checkServerLatencySupported(format, flags);
Andy Hung8946a282018-04-19 20:04:56 -0700834#ifdef TEE_SINK
835 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
Kevin Rocard51f0e982019-02-01 19:19:11 -0800836 + "_" + std::to_string(mId) + "_T");
Andy Hung8946a282018-04-19 20:04:56 -0700837#endif
jiabin57303cc2018-12-18 15:45:57 -0800838
jiabineb3bda02020-06-30 14:07:03 -0700839 if (thread->supportsHapticPlayback()) {
840 // If the track is attached to haptic playback thread, it is potentially to have
841 // HapticGenerator effect, which will generate haptic data, on the track. In that case,
842 // external vibration is always created for all tracks attached to haptic playback thread.
jiabin57303cc2018-12-18 15:45:57 -0800843 mAudioVibrationController = new AudioVibrationController(this);
Svet Ganov33761132021-05-13 22:51:08 +0000844 std::string packageName = attributionSource.packageName.has_value() ?
845 attributionSource.packageName.value() : "";
jiabin57303cc2018-12-18 15:45:57 -0800846 mExternalVibration = new os::ExternalVibration(
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700847 mUid, packageName, mAttr, mAudioVibrationController);
jiabin57303cc2018-12-18 15:45:57 -0800848 }
Andy Hungb68f5eb2019-12-03 16:49:17 -0800849
850 // Once this item is logged by the server, the client can add properties.
Andy Hunga629bd12020-06-05 16:03:53 -0700851 const char * const traits = sharedBuffer == 0 ? "" : "static";
Andy Hung5837c7f2021-02-25 10:48:24 -0800852 mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
Eric Laurent81784c32012-11-19 14:55:58 -0800853}
854
Andy Hung3ff4b552023-06-26 19:20:57 -0700855Track::~Track()
Eric Laurent81784c32012-11-19 14:55:58 -0800856{
Andy Hung9d84af52018-09-12 18:03:44 -0700857 ALOGV("%s(%d)", __func__, mId);
Glenn Kasten0c72b242013-09-11 09:14:16 -0700858
859 // The destructor would clear mSharedBuffer,
860 // but it will not push the decremented reference count,
861 // leaving the client's IMemory dangling indefinitely.
862 // This prevents that leak.
863 if (mSharedBuffer != 0) {
864 mSharedBuffer.clear();
Glenn Kasten0c72b242013-09-11 09:14:16 -0700865 }
Eric Laurent81784c32012-11-19 14:55:58 -0800866}
867
Andy Hung3ff4b552023-06-26 19:20:57 -0700868status_t Track::initCheck() const
Glenn Kasten03003332013-08-06 15:40:54 -0700869{
870 status_t status = TrackBase::initCheck();
Andy Hungc0691382018-09-12 18:01:57 -0700871 if (status == NO_ERROR && mCblk == nullptr) {
Glenn Kasten03003332013-08-06 15:40:54 -0700872 status = NO_MEMORY;
873 }
874 return status;
875}
876
Andy Hung3ff4b552023-06-26 19:20:57 -0700877void Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -0800878{
879 // NOTE: destroyTrack_l() can remove a strong reference to this Track
880 // by removing it from mTracks vector, so there is a risk that this Tracks's
881 // destructor is called. As the destructor needs to lock mLock,
882 // we must acquire a strong reference on this Track before locking mLock
883 // here so that the destructor is called only when exiting this function.
884 // On the other hand, as long as Track::destroy() is only called by
885 // TrackHandle destructor, the TrackHandle still holds a strong ref on
886 // this Track with its member mTrack.
887 sp<Track> keep(this);
888 { // scope for mLock
Eric Laurentaaa44472014-09-12 17:41:50 -0700889 bool wasActive = false;
Andy Hung44f27182023-07-06 20:56:16 -0700890 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -0800891 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -0700892 Mutex::Autolock _l(thread->mutex());
893 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentaaa44472014-09-12 17:41:50 -0700894 wasActive = playbackThread->destroyTrack_l(this);
895 }
896 if (isExternalTrack() && !wasActive) {
Eric Laurentd7fe0862018-07-14 16:48:01 -0700897 AudioSystem::releaseOutput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -0800898 }
899 }
Kevin Rocardc43ea142019-01-31 18:17:37 -0800900 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
Eric Laurent81784c32012-11-19 14:55:58 -0800901}
902
Andy Hung3ff4b552023-06-26 19:20:57 -0700903void Track::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -0800904{
Eric Laurent973db022018-11-20 14:54:31 -0800905 result.appendFormat("Type Id Active Client Session Port Id S Flags "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700906 " Format Chn mask SRate "
907 "ST Usg CT "
908 " G db L dB R dB VS dB "
jiabin5eaf0962022-12-20 20:11:38 +0000909 " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700910 "%s\n",
911 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -0800912}
913
Andy Hung3ff4b552023-06-26 19:20:57 -0700914void Track::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -0800915{
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700916 char trackType;
917 switch (mType) {
918 case TYPE_DEFAULT:
919 case TYPE_OUTPUT:
Andy Hungf6ab58d2018-05-25 12:50:39 -0700920 if (isStatic()) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700921 trackType = 'S'; // static
922 } else {
923 trackType = ' '; // normal
Eric Laurentbfb1b832013-01-07 09:53:42 -0800924 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700925 break;
926 case TYPE_PATCH:
927 trackType = 'P';
928 break;
929 default:
930 trackType = '?';
Eric Laurent81784c32012-11-19 14:55:58 -0800931 }
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700932
933 if (isFastTrack()) {
Andy Hungc0691382018-09-12 18:01:57 -0700934 result.appendFormat("F%d %c %6d", mFastIndex, trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700935 } else {
Andy Hungc0691382018-09-12 18:01:57 -0700936 result.appendFormat(" %c %6d", trackType, mId);
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700937 }
938
Eric Laurent81784c32012-11-19 14:55:58 -0800939 char nowInUnderrun;
940 switch (mObservedUnderruns.mBitFields.mMostRecent) {
941 case UNDERRUN_FULL:
942 nowInUnderrun = ' ';
943 break;
944 case UNDERRUN_PARTIAL:
945 nowInUnderrun = '<';
946 break;
947 case UNDERRUN_EMPTY:
948 nowInUnderrun = '*';
949 break;
950 default:
951 nowInUnderrun = '?';
952 break;
953 }
Andy Hungda540db2017-04-20 14:06:17 -0700954
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700955 char fillingStatus;
Andy Hung3ff4b552023-06-26 19:20:57 -0700956 switch (mFillingStatus) {
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700957 case FS_INVALID:
958 fillingStatus = 'I';
959 break;
960 case FS_FILLING:
961 fillingStatus = 'f';
962 break;
963 case FS_FILLED:
964 fillingStatus = 'F';
965 break;
966 case FS_ACTIVE:
967 fillingStatus = 'A';
968 break;
969 default:
970 fillingStatus = '?';
971 break;
972 }
973
974 // clip framesReadySafe to max representation in dump
975 const size_t framesReadySafe =
976 std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
977
978 // obtain volumes
979 const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
980 const std::pair<float /* volume */, bool /* active */> vsVolume =
981 mVolumeHandler->getLastVolume();
982
983 // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
984 // as it may be reduced by the application.
985 const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
986 // Check whether the buffer size has been modified by the app.
987 const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
988 ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
989 ? 'e' /* error */ : ' ' /* identical */;
990
Eric Laurent973db022018-11-20 14:54:31 -0800991 result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -0700992 "%08X %08X %6u "
993 "%2u %3x %2x "
994 "%5.2g %5.2g %5.2g %5.2g%c "
jiabin5eaf0962022-12-20 20:11:38 +0000995 "%08X %6zu%c %6zu %c %9u%c %7u %10s",
Marco Nelissenb2208842014-02-07 14:00:50 -0800996 active ? "yes" : "no",
Andy Hung4ef19fa2018-05-15 19:35:29 -0700997 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -0700998 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -0800999 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08001000 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001001 mCblk->mFlags,
1002
Eric Laurent81784c32012-11-19 14:55:58 -08001003 mFormat,
1004 mChannelMask,
Andy Hungcef2daa2018-06-01 15:31:49 -07001005 sampleRate(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001006
1007 mStreamType,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07001008 mAttr.usage,
1009 mAttr.content_type,
1010
1011 20.0 * log10(mFinalVolume),
Glenn Kastenc56f3422014-03-21 17:53:17 -07001012 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
1013 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
Andy Hungda540db2017-04-20 14:06:17 -07001014 20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
1015 vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001016
Glenn Kastenf20e1d82013-07-12 09:45:18 -07001017 mCblk->mServer,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001018 bufferSizeInFrames,
1019 modifiedBufferChar,
1020 framesReadySafe,
1021 fillingStatus,
Glenn Kasten82aaf942013-07-17 16:05:07 -07001022 mAudioTrackServerProxy->getUnderrunFrames(),
Andy Hung2148bf02016-11-28 19:01:02 -08001023 nowInUnderrun,
jiabin5eaf0962022-12-20 20:11:38 +00001024 (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
1025 isBitPerfect() ? "true" : "false"
Andy Hung2c6c3bb2017-06-16 14:01:45 -07001026 );
Andy Hungcef2daa2018-06-01 15:31:49 -07001027
1028 if (isServerLatencySupported()) {
1029 double latencyMs;
1030 bool fromTrack;
1031 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
1032 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
1033 // or 'k' if estimated from kernel because track frames haven't been presented yet.
1034 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
Andy Hungf6ab58d2018-05-25 12:50:39 -07001035 } else {
Andy Hungcef2daa2018-06-01 15:31:49 -07001036 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
Andy Hungf6ab58d2018-05-25 12:50:39 -07001037 }
1038 }
1039 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001040}
1041
Andy Hung3ff4b552023-06-26 19:20:57 -07001042uint32_t Track::sampleRate() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001043 return mAudioTrackServerProxy->getSampleRate();
1044}
1045
Eric Laurent81784c32012-11-19 14:55:58 -08001046// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07001047status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001048{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001049 ServerProxy::Buffer buf;
1050 size_t desiredFrames = buffer->frameCount;
1051 buf.mFrameCount = desiredFrames;
1052 status_t status = mServerProxy->obtainBuffer(&buf);
1053 buffer->frameCount = buf.mFrameCount;
1054 buffer->raw = buf.mRaw;
Andy Hungfc629172020-06-22 10:06:23 -07001055 if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
Andy Hung9d84af52018-09-12 18:03:44 -07001056 ALOGV("%s(%d): underrun, framesReady(%zu) < framesDesired(%zd), state: %d",
Andy Hung959b5b82021-09-24 10:46:20 -07001057 __func__, mId, buf.mFrameCount, desiredFrames, (int)mState);
Glenn Kasten82aaf942013-07-17 16:05:07 -07001058 mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
Phil Burk2812d9e2016-01-04 10:34:30 -08001059 } else {
1060 mAudioTrackServerProxy->tallyUnderrunFrames(0);
Eric Laurent81784c32012-11-19 14:55:58 -08001061 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001062 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001063}
1064
Andy Hung3ff4b552023-06-26 19:20:57 -07001065void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Kevin Rocard153f92d2018-12-18 18:33:28 -08001066{
1067 interceptBuffer(*buffer);
1068 TrackBase::releaseBuffer(buffer);
1069}
1070
1071// TODO: compensate for time shift between HW modules.
Andy Hung3ff4b552023-06-26 19:20:57 -07001072void Track::interceptBuffer(
Kevin Rocarda134b002019-02-07 18:05:31 -08001073 const AudioBufferProvider::Buffer& sourceBuffer) {
Kevin Rocard6057fa22019-02-08 14:08:07 -08001074 auto start = std::chrono::steady_clock::now();
Kevin Rocarda134b002019-02-07 18:05:31 -08001075 const size_t frameCount = sourceBuffer.frameCount;
Kevin Rocardd83b08a2019-02-27 15:05:54 -08001076 if (frameCount == 0) {
1077 return; // No audio to intercept.
1078 // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
1079 // does not allow 0 frame size request contrary to getNextBuffer
1080 }
1081 for (auto& teePatch : mTeePatches) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001082 IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
Mikhail Naganov8296c252019-09-25 14:59:54 -07001083 const size_t framesWritten = patchRecord->writeFrames(
1084 sourceBuffer.i8, frameCount, mFrameSize);
1085 const size_t framesLeft = frameCount - framesWritten;
Kevin Rocarda134b002019-02-07 18:05:31 -08001086 ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
Andy Hung3ff4b552023-06-26 19:20:57 -07001087 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
Kevin Rocarda134b002019-02-07 18:05:31 -08001088 framesWritten, frameCount, framesLeft);
Kevin Rocard153f92d2018-12-18 18:33:28 -08001089 }
Kevin Rocard6057fa22019-02-08 14:08:07 -08001090 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
1091 using namespace std::chrono_literals;
1092 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001093 ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
Kevin Rocard6057fa22019-02-08 14:08:07 -08001094 spent.count(), mTeePatches.size());
Kevin Rocard153f92d2018-12-18 18:33:28 -08001095}
1096
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001097// ExtendedAudioBufferProvider interface
1098
Andy Hung27876c02014-09-09 18:07:55 -07001099// framesReady() may return an approximation of the number of frames if called
1100// from a different thread than the one calling Proxy->obtainBuffer() and
1101// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
1102// AudioTrackServerProxy so be especially careful calling with FastTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001103size_t Track::framesReady() const {
Andy Hung27876c02014-09-09 18:07:55 -07001104 if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
1105 // Static tracks return zero frames immediately upon stopping (for FastTracks).
1106 // The remainder of the buffer is not drained.
1107 return 0;
1108 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001109 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -08001110}
1111
Andy Hung3ff4b552023-06-26 19:20:57 -07001112int64_t Track::framesReleased() const
Glenn Kasten6466c9e2013-08-23 10:54:07 -07001113{
1114 return mAudioTrackServerProxy->framesReleased();
1115}
1116
Andy Hung3ff4b552023-06-26 19:20:57 -07001117void Track::onTimestamp(const ExtendedTimestamp &timestamp)
Andy Hung6ae58432016-02-16 18:32:24 -08001118{
1119 // This call comes from a FastTrack and should be kept lockless.
1120 // The server side frames are already translated to client frames.
Andy Hung818e7a32016-02-16 18:08:07 -08001121 mAudioTrackServerProxy->setTimestamp(timestamp);
Andy Hung6ae58432016-02-16 18:32:24 -08001122
Andy Hung818e7a32016-02-16 18:08:07 -08001123 // We do not set drained here, as FastTrack timestamp may not go to very last frame.
Andy Hungcef2daa2018-06-01 15:31:49 -07001124
1125 // Compute latency.
1126 // TODO: Consider whether the server latency may be passed in by FastMixer
1127 // as a constant for all active FastTracks.
1128 const double latencyMs = timestamp.getOutputServerLatencyMs(sampleRate());
1129 mServerLatencyFromTrack.store(true);
1130 mServerLatencyMs.store(latencyMs);
Andy Hung6ae58432016-02-16 18:32:24 -08001131}
1132
Eric Laurent81784c32012-11-19 14:55:58 -08001133// Don't call for fast tracks; the framesReady() could result in priority inversion
Andy Hung3ff4b552023-06-26 19:20:57 -07001134bool Track::isReady() const {
1135 if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001136 return true;
1137 }
1138
Eric Laurent16498512014-03-17 17:22:08 -07001139 if (isStopping()) {
1140 if (framesReady() > 0) {
Andy Hung3ff4b552023-06-26 19:20:57 -07001141 mFillingStatus = FS_FILLED;
Eric Laurent16498512014-03-17 17:22:08 -07001142 }
Eric Laurent81784c32012-11-19 14:55:58 -08001143 return true;
1144 }
1145
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001146 size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
Andy Hung3c7f47a2021-03-16 17:30:09 -07001147 // Note: mServerProxy->getStartThresholdInFrames() is clamped.
1148 const size_t startThresholdInFrames = mServerProxy->getStartThresholdInFrames();
1149 const size_t framesToBeReady = std::clamp( // clamp again to validate client values.
1150 std::min(startThresholdInFrames, bufferSizeInFrames), size_t(1), mFrameCount);
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001151
1152 if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
1153 ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
1154 __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
Andy Hung3ff4b552023-06-26 19:20:57 -07001155 mFillingStatus = FS_FILLED;
Glenn Kasten96f60d82013-07-12 10:21:18 -07001156 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08001157 return true;
1158 }
1159 return false;
1160}
1161
Andy Hung3ff4b552023-06-26 19:20:57 -07001162status_t Track::start(AudioSystem::sync_event_t event __unused,
Glenn Kastend848eb42016-03-08 13:42:11 -08001163 audio_session_t triggerSession __unused)
Eric Laurent81784c32012-11-19 14:55:58 -08001164{
1165 status_t status = NO_ERROR;
Andy Hungc0691382018-09-12 18:01:57 -07001166 ALOGV("%s(%d): calling pid %d session %d",
1167 __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
Eric Laurent81784c32012-11-19 14:55:58 -08001168
Andy Hung44f27182023-07-06 20:56:16 -07001169 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001170 if (thread != 0) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001171 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001172 Mutex::Autolock _laf(thread->audioFlinger()->mLock);
1173 Mutex::Autolock _lth(thread->mutex());
Andy Hungbd72c542023-06-20 18:56:17 -07001174 sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
Andy Hung44f27182023-07-06 20:56:16 -07001175 if (thread->audioFlinger()->isNonOffloadableGlobalEffectEnabled_l() ||
Eric Laurent5baf2af2013-09-12 17:37:00 -07001176 (ec != 0 && ec->isNonOffloadableEnabled())) {
Eric Laurent813e2a72013-08-31 12:59:48 -07001177 invalidate();
1178 return PERMISSION_DENIED;
1179 }
1180 }
Andy Hung44f27182023-07-06 20:56:16 -07001181 Mutex::Autolock _lth(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001182 track_state state = mState;
1183 // here the track could be either new, or restarted
1184 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -08001185
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001186 // initial state-stopping. next state-pausing.
1187 // What if resume is called ?
1188
Zhou Song1ed46a22020-08-17 15:36:56 +08001189 if (state == FLUSHED) {
1190 // avoid underrun glitches when starting after flush
1191 reset();
1192 }
1193
kuowei.li576f1362021-05-11 18:02:32 +08001194 // clear mPauseHwPending because of pause (and possibly flush) during underrun.
1195 mPauseHwPending = false;
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001196 if (state == PAUSED || state == PAUSING) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001197 if (mResumeToStopping) {
1198 // happened we need to resume to STOPPING_1
1199 mState = TrackBase::STOPPING_1;
Andy Hungc0691382018-09-12 18:01:57 -07001200 ALOGV("%s(%d): PAUSED => STOPPING_1 on thread %d",
1201 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001202 } else {
1203 mState = TrackBase::RESUMING;
Andy Hungc0691382018-09-12 18:01:57 -07001204 ALOGV("%s(%d): PAUSED => RESUMING on thread %d",
1205 __func__, mId, (int)mThreadIoHandle);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001206 }
Eric Laurent81784c32012-11-19 14:55:58 -08001207 } else {
1208 mState = TrackBase::ACTIVE;
Andy Hungc0691382018-09-12 18:01:57 -07001209 ALOGV("%s(%d): ? => ACTIVE on thread %d",
1210 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001211 }
1212
Andy Hung44f27182023-07-06 20:56:16 -07001213 auto* const playbackThread = thread->asIAfPlaybackThread().get();
yucliu91503922022-07-20 17:40:39 -07001214
1215 // states to reset position info for pcm tracks
1216 if (audio_is_linear_pcm(mFormat)
Andy Hunge10393e2015-06-12 13:59:33 -07001217 && (state == IDLE || state == STOPPED || state == FLUSHED)) {
1218 mFrameMap.reset();
yucliu91503922022-07-20 17:40:39 -07001219
1220 if (!isFastTrack() && (isDirect() || isOffloaded())) {
1221 // Start point of track -> sink frame map. If the HAL returns a
1222 // frame position smaller than the first written frame in
1223 // updateTrackFrameInfo, the timestamp can be interpolated
1224 // instead of using a larger value.
1225 mFrameMap.push(mAudioTrackServerProxy->framesReleased(),
1226 playbackThread->framesWritten());
1227 }
Andy Hunge10393e2015-06-12 13:59:33 -07001228 }
Haynes Mathew George240934b2015-03-11 18:25:50 -07001229 if (isFastTrack()) {
1230 // refresh fast track underruns on start because that field is never cleared
1231 // by the fast mixer; furthermore, the same track can be recycled, i.e. start
1232 // after stop.
1233 mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
1234 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001235 status = playbackThread->addTrack_l(this);
jiabina84c3d32022-12-02 18:59:55 +00001236 if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurent81784c32012-11-19 14:55:58 -08001237 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001238 // restore previous state if start was rejected by policy manager
jiabina84c3d32022-12-02 18:59:55 +00001239 if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001240 mState = state;
1241 }
1242 }
Andy Hung1d3556d2018-03-29 16:30:14 -07001243
Andy Hungb68f5eb2019-12-03 16:49:17 -08001244 // Audio timing metrics are computed a few mix cycles after starting.
1245 {
1246 mLogStartCountdown = LOG_START_COUNTDOWN;
1247 mLogStartTimeNs = systemTime();
1248 mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
Andy Hung62921122020-05-18 10:47:31 -07001249 .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
1250 mLogLatencyMs = 0.;
Andy Hungb68f5eb2019-12-03 16:49:17 -08001251 }
Andy Hungcb6cc752022-05-19 19:24:51 -07001252 mLogForceVolumeUpdate = true; // at least one volume logged for metrics when starting.
Andy Hungb68f5eb2019-12-03 16:49:17 -08001253
Andy Hung1d3556d2018-03-29 16:30:14 -07001254 if (status == NO_ERROR || status == ALREADY_EXISTS) {
1255 // for streaming tracks, remove the buffer read stop limit.
1256 mAudioTrackServerProxy->start();
1257 }
1258
Eric Laurentbfb1b832013-01-07 09:53:42 -08001259 // track was already in the active list, not a problem
1260 if (status == ALREADY_EXISTS) {
1261 status = NO_ERROR;
Glenn Kasten12022ff2013-10-17 11:32:39 -07001262 } else {
1263 // Acknowledge any pending flush(), so that subsequent new data isn't discarded.
1264 // It is usually unsafe to access the server proxy from a binder thread.
1265 // But in this case we know the mixer thread (whether normal mixer or fast mixer)
1266 // isn't looking at this track yet: we still hold the normal mixer thread lock,
1267 // and for fast tracks the track is not yet in the fast mixer thread's active set.
Andy Hunge6fb82a2015-09-09 14:39:02 -07001268 // For static tracks, this is used to acknowledge change in position or loop.
Eric Laurent564d1442015-09-09 12:26:52 -07001269 ServerProxy::Buffer buffer;
1270 buffer.mFrameCount = 1;
1271 (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001272 }
1273 } else {
1274 status = BAD_VALUE;
1275 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001276 if (status == NO_ERROR) {
1277 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001278
1279 // send format to AudioManager for playback activity monitoring
Andy Hung44f27182023-07-06 20:56:16 -07001280 const sp<IAudioManager> audioManager = thread->audioFlinger()->getOrCreateAudioManager();
Jean-Michel Trivi16395ca2022-12-11 22:10:11 +00001281 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1282 std::unique_ptr<os::PersistableBundle> bundle =
1283 std::make_unique<os::PersistableBundle>();
1284 bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
1285 isSpatialized());
1286 bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
1287 bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
1288 status_t result = audioManager->portEvent(mPortId,
1289 PLAYER_UPDATE_FORMAT, bundle);
1290 if (result != OK) {
1291 ALOGE("%s: unable to send playback format for port ID %d, status error %d",
1292 __func__, mPortId, result);
1293 }
1294 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001295 }
Eric Laurent81784c32012-11-19 14:55:58 -08001296 return status;
1297}
1298
Andy Hung3ff4b552023-06-26 19:20:57 -07001299void Track::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08001300{
Andy Hungc0691382018-09-12 18:01:57 -07001301 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001302 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001303 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001304 Mutex::Autolock _l(thread->mutex());
Eric Laurent81784c32012-11-19 14:55:58 -08001305 track_state state = mState;
1306 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
1307 // If the track is not active (PAUSED and buffers full), flush buffers
Andy Hung44f27182023-07-06 20:56:16 -07001308 auto* const playbackThread = thread->asIAfPlaybackThread().get();
1309 if (!playbackThread->isTrackActive(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001310 reset();
1311 mState = STOPPED;
Eric Laurentab5cdba2014-06-09 17:22:27 -07001312 } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
Eric Laurent81784c32012-11-19 14:55:58 -08001313 mState = STOPPED;
1314 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001315 // For fast tracks prepareTracks_l() will set state to STOPPING_2
1316 // presentation is complete
1317 // For an offloaded track this starts a drain and state will
1318 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -08001319 mState = STOPPING_1;
Eric Laurente93cc032016-05-05 10:15:10 -07001320 if (isOffloaded()) {
Andy Hung44f27182023-07-06 20:56:16 -07001321 mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
Eric Laurente93cc032016-05-05 10:15:10 -07001322 }
Eric Laurent81784c32012-11-19 14:55:58 -08001323 }
Eric Laurentb369caf2015-03-30 20:51:47 -07001324 playbackThread->broadcast_l();
Andy Hungc0691382018-09-12 18:01:57 -07001325 ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
1326 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08001327 }
Eric Laurent81784c32012-11-19 14:55:58 -08001328 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001329 forEachTeePatchTrack([](auto patchTrack) { patchTrack->stop(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001330}
1331
Andy Hung3ff4b552023-06-26 19:20:57 -07001332void Track::pause()
Eric Laurent81784c32012-11-19 14:55:58 -08001333{
Andy Hungc0691382018-09-12 18:01:57 -07001334 ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
Andy Hung44f27182023-07-06 20:56:16 -07001335 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001336 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001337 Mutex::Autolock _l(thread->mutex());
1338 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001339 switch (mState) {
1340 case STOPPING_1:
1341 case STOPPING_2:
1342 if (!isOffloaded()) {
1343 /* nothing to do if track is not offloaded */
1344 break;
1345 }
1346
1347 // Offloaded track was draining, we need to carry on draining when resumed
1348 mResumeToStopping = true;
Chih-Hung Hsieh2b487032018-09-13 14:16:02 -07001349 FALLTHROUGH_INTENDED;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001350 case ACTIVE:
1351 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -08001352 mState = PAUSING;
Andy Hungc0691382018-09-12 18:01:57 -07001353 ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
1354 __func__, mId, (int)mThreadIoHandle);
Kuowei Li23666472021-01-20 10:23:25 +08001355 if (isOffloadedOrDirect()) {
1356 mPauseHwPending = true;
1357 }
Eric Laurentede6c3b2013-09-19 14:37:46 -07001358 playbackThread->broadcast_l();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001359 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001360
Eric Laurentbfb1b832013-01-07 09:53:42 -08001361 default:
1362 break;
Eric Laurent81784c32012-11-19 14:55:58 -08001363 }
1364 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001365 // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
1366 forEachTeePatchTrack([](auto patchTrack) { patchTrack->pause(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001367}
1368
Andy Hung3ff4b552023-06-26 19:20:57 -07001369void Track::flush()
Eric Laurent81784c32012-11-19 14:55:58 -08001370{
Andy Hungc0691382018-09-12 18:01:57 -07001371 ALOGV("%s(%d)", __func__, mId);
Andy Hung44f27182023-07-06 20:56:16 -07001372 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08001373 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001374 Mutex::Autolock _l(thread->mutex());
1375 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001376
Phil Burk4bb650b2016-09-09 12:11:17 -07001377 // Flush the ring buffer now if the track is not active in the PlaybackThread.
1378 // Otherwise the flush would not be done until the track is resumed.
1379 // Requires FastTrack removal be BLOCK_UNTIL_ACKED
Andy Hung44f27182023-07-06 20:56:16 -07001380 if (!playbackThread->isTrackActive(this)) {
Phil Burk4bb650b2016-09-09 12:11:17 -07001381 (void)mServerProxy->flushBufferIfNeeded();
1382 }
1383
Eric Laurentbfb1b832013-01-07 09:53:42 -08001384 if (isOffloaded()) {
1385 // If offloaded we allow flush during any state except terminated
1386 // and keep the track active to avoid problems if user is seeking
1387 // rapidly and underlying hardware has a significant delay handling
1388 // a pause
1389 if (isTerminated()) {
1390 return;
1391 }
1392
Andy Hung9d84af52018-09-12 18:03:44 -07001393 ALOGV("%s(%d): offload flush", __func__, mId);
Eric Laurent81784c32012-11-19 14:55:58 -08001394 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001395
1396 if (mState == STOPPING_1 || mState == STOPPING_2) {
Andy Hung9d84af52018-09-12 18:03:44 -07001397 ALOGV("%s(%d): flushed in STOPPING_1 or 2 state, change state to ACTIVE",
1398 __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001399 mState = ACTIVE;
1400 }
1401
Haynes Mathew George7844f672014-01-15 12:32:55 -08001402 mFlushHwPending = true;
Eric Laurentbfb1b832013-01-07 09:53:42 -08001403 mResumeToStopping = false;
1404 } else {
1405 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
1406 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
1407 return;
1408 }
1409 // No point remaining in PAUSED state after a flush => go to
1410 // FLUSHED state
1411 mState = FLUSHED;
1412 // do not reset the track if it is still in the process of being stopped or paused.
1413 // this will be done by prepareTracks_l() when the track is stopped.
1414 // prepareTracks_l() will see mState == FLUSHED, then
1415 // remove from active track list, reset(), and trigger presentation complete
Eric Laurentd1f69b02014-12-15 14:33:13 -08001416 if (isDirect()) {
1417 mFlushHwPending = true;
1418 }
Andy Hung44f27182023-07-06 20:56:16 -07001419 if (!playbackThread->isTrackActive(this)) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001420 reset();
1421 }
Eric Laurent81784c32012-11-19 14:55:58 -08001422 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001423 // Prevent flush being lost if the track is flushed and then resumed
1424 // before mixer thread can run. This is important when offloading
1425 // because the hardware buffer could hold a large amount of audio
Eric Laurentede6c3b2013-09-19 14:37:46 -07001426 playbackThread->broadcast_l();
Eric Laurent81784c32012-11-19 14:55:58 -08001427 }
Kevin Rocardc43ea142019-01-31 18:17:37 -08001428 // Flush the Tee to avoid on resume playing old data and glitching on the transition to new data
1429 forEachTeePatchTrack([](auto patchTrack) { patchTrack->flush(); });
Eric Laurent81784c32012-11-19 14:55:58 -08001430}
1431
Haynes Mathew George7844f672014-01-15 12:32:55 -08001432// must be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001433void Track::flushAck()
Haynes Mathew George7844f672014-01-15 12:32:55 -08001434{
Andy Hung71ba4b32022-10-06 12:09:49 -07001435 if (!isOffloaded() && !isDirect()) {
Haynes Mathew George7844f672014-01-15 12:32:55 -08001436 return;
Andy Hung71ba4b32022-10-06 12:09:49 -07001437 }
Haynes Mathew George7844f672014-01-15 12:32:55 -08001438
Phil Burk4bb650b2016-09-09 12:11:17 -07001439 // Clear the client ring buffer so that the app can prime the buffer while paused.
1440 // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
1441 mServerProxy->flushBufferIfNeeded();
1442
Haynes Mathew George7844f672014-01-15 12:32:55 -08001443 mFlushHwPending = false;
1444}
1445
Andy Hung3ff4b552023-06-26 19:20:57 -07001446void Track::pauseAck()
Kuowei Li23666472021-01-20 10:23:25 +08001447{
1448 mPauseHwPending = false;
1449}
1450
Andy Hung3ff4b552023-06-26 19:20:57 -07001451void Track::reset()
Eric Laurent81784c32012-11-19 14:55:58 -08001452{
1453 // Do not reset twice to avoid discarding data written just after a flush and before
1454 // the audioflinger thread detects the track is stopped.
1455 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -08001456 // Force underrun condition to avoid false underrun callback until first data is
1457 // written to buffer
Glenn Kasten96f60d82013-07-12 10:21:18 -07001458 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
Andy Hung3ff4b552023-06-26 19:20:57 -07001459 mFillingStatus = FS_FILLING;
Eric Laurent81784c32012-11-19 14:55:58 -08001460 mResetDone = true;
1461 if (mState == FLUSHED) {
1462 mState = IDLE;
1463 }
1464 }
1465}
1466
Andy Hung3ff4b552023-06-26 19:20:57 -07001467status_t Track::setParameters(const String8& keyValuePairs)
Eric Laurentbfb1b832013-01-07 09:53:42 -08001468{
Andy Hung44f27182023-07-06 20:56:16 -07001469 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentbfb1b832013-01-07 09:53:42 -08001470 if (thread == 0) {
Andy Hung9d84af52018-09-12 18:03:44 -07001471 ALOGE("%s(%d): thread is dead", __func__, mId);
Eric Laurentbfb1b832013-01-07 09:53:42 -08001472 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001473 } else if (thread->type() == IAfThreadBase::DIRECT
1474 || thread->type() == IAfThreadBase::OFFLOAD) {
Eric Laurentbfb1b832013-01-07 09:53:42 -08001475 return thread->setParameters(keyValuePairs);
1476 } else {
1477 return PERMISSION_DENIED;
1478 }
1479}
1480
Andy Hung3ff4b552023-06-26 19:20:57 -07001481status_t Track::selectPresentation(int presentationId,
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001482 int programId) {
Andy Hung44f27182023-07-06 20:56:16 -07001483 const sp<IAfThreadBase> thread = mThread.promote();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001484 if (thread == 0) {
1485 ALOGE("thread is dead");
1486 return FAILED_TRANSACTION;
Andy Hung44f27182023-07-06 20:56:16 -07001487 } else if (thread->type() == IAfThreadBase::DIRECT
1488 || thread->type() == IAfThreadBase::OFFLOAD) {
1489 auto directOutputThread = thread->asIAfDirectOutputThread().get();
Mikhail Naganovac917ac2018-11-28 14:03:52 -08001490 return directOutputThread->selectPresentation(presentationId, programId);
1491 }
1492 return INVALID_OPERATION;
1493}
1494
Andy Hung3ff4b552023-06-26 19:20:57 -07001495VolumeShaper::Status Track::applyVolumeShaper(
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001496 const sp<VolumeShaper::Configuration>& configuration,
1497 const sp<VolumeShaper::Operation>& operation)
1498{
Andy Hungee86cee2022-12-13 19:19:53 -08001499 VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
Andy Hung10cbff12017-02-21 17:30:14 -08001500
1501 if (isOffloadedOrDirect()) {
1502 // Signal thread to fetch new volume.
Andy Hung44f27182023-07-06 20:56:16 -07001503 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung10cbff12017-02-21 17:30:14 -08001504 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001505 Mutex::Autolock _l(thread->mutex());
Andy Hung10cbff12017-02-21 17:30:14 -08001506 thread->broadcast_l();
1507 }
1508 }
1509 return status;
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001510}
1511
Andy Hung3ff4b552023-06-26 19:20:57 -07001512sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
Andy Hung9fc8b5c2017-01-24 13:36:48 -08001513{
1514 // Note: We don't check if Thread exists.
1515
1516 // mVolumeHandler is thread safe.
1517 return mVolumeHandler->getVolumeShaperState(id);
1518}
1519
Andy Hung3ff4b552023-06-26 19:20:57 -07001520void Track::setFinalVolume(float volumeLeft, float volumeRight)
Kevin Rocard12381092018-04-11 09:19:59 -07001521{
jiabin76d94692022-12-15 21:51:21 +00001522 mFinalVolumeLeft = volumeLeft;
1523 mFinalVolumeRight = volumeRight;
1524 const float volume = (volumeLeft + volumeRight) * 0.5f;
Kevin Rocard12381092018-04-11 09:19:59 -07001525 if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
1526 mFinalVolume = volume;
1527 setMetadataHasChanged();
Andy Hungcb6cc752022-05-19 19:24:51 -07001528 mLogForceVolumeUpdate = true;
1529 }
1530 if (mLogForceVolumeUpdate) {
1531 mLogForceVolumeUpdate = false;
1532 mTrackMetrics.logVolume(mFinalVolume);
Kevin Rocard12381092018-04-11 09:19:59 -07001533 }
1534}
1535
Andy Hung3ff4b552023-06-26 19:20:57 -07001536void Track::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07001537{
Eric Laurent49e39282022-06-24 18:42:45 +02001538 // Do not forward metadata for PatchTrack with unspecified stream type
1539 if (mStreamType == AUDIO_STREAM_PATCH) {
1540 return;
1541 }
1542
Eric Laurent94579172020-11-20 18:41:04 +01001543 playback_track_metadata_v7_t metadata;
1544 metadata.base = {
Kevin Rocard12381092018-04-11 09:19:59 -07001545 .usage = mAttr.usage,
1546 .content_type = mAttr.content_type,
1547 .gain = mFinalVolume,
1548 };
Eric Laurentfdf99502021-11-26 19:05:02 +01001549
1550 // When attributes are undefined, derive default values from stream type.
1551 // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
1552 if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
1553 switch (mStreamType) {
1554 case AUDIO_STREAM_VOICE_CALL:
1555 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
1556 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1557 break;
1558 case AUDIO_STREAM_SYSTEM:
1559 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
1560 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1561 break;
1562 case AUDIO_STREAM_RING:
1563 metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
1564 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1565 break;
1566 case AUDIO_STREAM_MUSIC:
1567 metadata.base.usage = AUDIO_USAGE_MEDIA;
1568 metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
1569 break;
1570 case AUDIO_STREAM_ALARM:
1571 metadata.base.usage = AUDIO_USAGE_ALARM;
1572 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1573 break;
1574 case AUDIO_STREAM_NOTIFICATION:
1575 metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
1576 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1577 break;
1578 case AUDIO_STREAM_DTMF:
1579 metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
1580 metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
1581 break;
1582 case AUDIO_STREAM_ACCESSIBILITY:
1583 metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
1584 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1585 break;
1586 case AUDIO_STREAM_ASSISTANT:
1587 metadata.base.usage = AUDIO_USAGE_ASSISTANT;
1588 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1589 break;
1590 case AUDIO_STREAM_REROUTING:
1591 metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
1592 // unknown content type
1593 break;
1594 case AUDIO_STREAM_CALL_ASSISTANT:
1595 metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
1596 metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
1597 break;
1598 default:
1599 break;
1600 }
1601 }
1602
Eric Laurent78b07302022-10-07 16:20:34 +02001603 metadata.channel_mask = mChannelMask;
Eric Laurent94579172020-11-20 18:41:04 +01001604 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
1605 *backInserter++ = metadata;
Kevin Rocard12381092018-04-11 09:19:59 -07001606}
1607
Andy Hung3ff4b552023-06-26 19:20:57 -07001608void Track::updateTeePatches() {
Jiabin Huangfb476842022-12-06 03:18:10 +00001609 if (mTeePatchesToUpdate.has_value()) {
1610 forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
1611 mTeePatches = mTeePatchesToUpdate.value();
1612 if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
1613 mState == TrackBase::STOPPING_1) {
1614 forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
1615 }
1616 mTeePatchesToUpdate.reset();
jiabinf042b9b2021-05-07 23:46:28 +00001617 }
Kevin Rocard153f92d2018-12-18 18:33:28 -08001618}
1619
Andy Hung3ff4b552023-06-26 19:20:57 -07001620void Track::setTeePatchesToUpdate(AudioFlinger::TeePatches teePatchesToUpdate) {
Jiabin Huangfb476842022-12-06 03:18:10 +00001621 ALOGW_IF(mTeePatchesToUpdate.has_value(),
1622 "%s, existing tee patches to update will be ignored", __func__);
1623 mTeePatchesToUpdate = std::move(teePatchesToUpdate);
1624}
1625
Vlad Popae8d99472022-06-30 16:02:48 +02001626// must be called with player thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001627void Track::processMuteEvent_l(const sp<
Vlad Popae8d99472022-06-30 16:02:48 +02001628 IAudioManager>& audioManager, mute_state_t muteState)
1629{
1630 if (mMuteState == muteState) {
1631 // mute state did not change, do nothing
1632 return;
1633 }
1634
1635 status_t result = UNKNOWN_ERROR;
1636 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
1637 if (mMuteEventExtras == nullptr) {
1638 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
1639 }
1640 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
1641 static_cast<int>(muteState));
1642
1643 result = audioManager->portEvent(mPortId,
1644 PLAYER_UPDATE_MUTED,
1645 mMuteEventExtras);
1646 }
1647
1648 if (result == OK) {
1649 mMuteState = muteState;
1650 } else {
1651 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
1652 __func__,
1653 id(),
1654 mPortId,
1655 result);
Andy Hung818e7a32016-02-16 18:08:07 -08001656 }
Glenn Kastenfe346c72013-08-30 13:28:22 -07001657}
Glenn Kasten573d80a2013-08-26 09:36:23 -07001658
Andy Hung3ff4b552023-06-26 19:20:57 -07001659status_t Track::getTimestamp(AudioTimestamp& timestamp)
Eric Laurent81784c32012-11-19 14:55:58 -08001660{
1661 if (!isOffloaded() && !isDirect()) {
Glenn Kasten573d80a2013-08-26 09:36:23 -07001662 return INVALID_OPERATION; // normal tracks handled through SSQ
1663 }
Andy Hung44f27182023-07-06 20:56:16 -07001664 const sp<IAfThreadBase> thread = mThread.promote();
Glenn Kasten573d80a2013-08-26 09:36:23 -07001665 if (thread == 0) {
Glenn Kastenfe346c72013-08-30 13:28:22 -07001666 return INVALID_OPERATION;
Glenn Kasten573d80a2013-08-26 09:36:23 -07001667 }
Phil Burk6140c792015-03-19 14:30:21 -07001668
Andy Hung44f27182023-07-06 20:56:16 -07001669 Mutex::Autolock _l(thread->mutex());
1670 auto* const playbackThread = thread->asIAfPlaybackThread().get();
Andy Hung818e7a32016-02-16 18:08:07 -08001671 return playbackThread->getTimestamp_l(timestamp);
Glenn Kasten573d80a2013-08-26 09:36:23 -07001672}
1673
Andy Hung3ff4b552023-06-26 19:20:57 -07001674status_t Track::attachAuxEffect(int EffectId)
Eric Laurent81784c32012-11-19 14:55:58 -08001675{
Andy Hung44f27182023-07-06 20:56:16 -07001676 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent6c796322019-04-09 14:13:17 -07001677 if (thread == nullptr) {
1678 return DEAD_OBJECT;
1679 }
Eric Laurent81784c32012-11-19 14:55:58 -08001680
Andy Hung44f27182023-07-06 20:56:16 -07001681 auto dstThread = thread->asIAfPlaybackThread();
Andy Hung3ff4b552023-06-26 19:20:57 -07001682 // srcThread is initialized by call to moveAuxEffectToIo()
Andy Hung44f27182023-07-06 20:56:16 -07001683 sp<IAfPlaybackThread> srcThread;
Eric Laurent6c796322019-04-09 14:13:17 -07001684 sp<AudioFlinger> af = mClient->audioFlinger();
1685 status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001686
Eric Laurent6c796322019-04-09 14:13:17 -07001687 if (EffectId != 0 && status == NO_ERROR) {
1688 status = dstThread->attachAuxEffect(this, EffectId);
1689 if (status == NO_ERROR) {
1690 AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
Eric Laurent81784c32012-11-19 14:55:58 -08001691 }
Eric Laurent6c796322019-04-09 14:13:17 -07001692 }
1693
1694 if (status != NO_ERROR && srcThread != nullptr) {
1695 af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
Eric Laurent81784c32012-11-19 14:55:58 -08001696 }
1697 return status;
1698}
1699
Andy Hung3ff4b552023-06-26 19:20:57 -07001700void Track::setAuxBuffer(int EffectId, int32_t *buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08001701{
1702 mAuxEffectId = EffectId;
1703 mAuxBuffer = buffer;
1704}
1705
Andy Hung59de4262021-06-14 10:53:54 -07001706// presentationComplete verified by frames, used by Mixed tracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001707bool Track::presentationComplete(
Andy Hung818e7a32016-02-16 18:08:07 -08001708 int64_t framesWritten, size_t audioHalFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08001709{
Andy Hung818e7a32016-02-16 18:08:07 -08001710 // TODO: improve this based on FrameMap if it exists, to ensure full drain.
1711 // This assists in proper timestamp computation as well as wakelock management.
1712
Eric Laurent81784c32012-11-19 14:55:58 -08001713 // a track is considered presented when the total number of frames written to audio HAL
1714 // corresponds to the number of frames written when presentationComplete() is called for the
1715 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -08001716 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1717 // to detect when all frames have been played. In this case framesWritten isn't
1718 // useful because it doesn't always reflect whether there is data in the h/w
1719 // buffers, particularly if a track has been paused and resumed during draining
Andy Hung9d84af52018-09-12 18:03:44 -07001720 ALOGV("%s(%d): presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
1721 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001722 (long long)mPresentationCompleteFrames, (long long)framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -08001723 if (mPresentationCompleteFrames == 0) {
1724 mPresentationCompleteFrames = framesWritten + audioHalFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001725 ALOGV("%s(%d): set:"
Andy Hung9d84af52018-09-12 18:03:44 -07001726 " mPresentationCompleteFrames %lld audioHalFrames %zu",
1727 __func__, mId,
Andy Hung818e7a32016-02-16 18:08:07 -08001728 (long long)mPresentationCompleteFrames, audioHalFrames);
Eric Laurent81784c32012-11-19 14:55:58 -08001729 }
Eric Laurentbfb1b832013-01-07 09:53:42 -08001730
Andy Hungc54b1ff2016-02-23 14:07:07 -08001731 bool complete;
Andy Hung59de4262021-06-14 10:53:54 -07001732 if (isFastTrack()) { // does not go through linear map
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001733 complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
Andy Hung59de4262021-06-14 10:53:54 -07001734 ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
1735 __func__, mId, (complete ? "complete" : "waiting"),
1736 (long long) framesWritten, (long long) mPresentationCompleteFrames);
Andy Hungc54b1ff2016-02-23 14:07:07 -08001737 } else { // Normal tracks, OutputTracks, and PatchTracks
Glenn Kastenc42e9b42016-03-21 11:35:03 -07001738 complete = framesWritten >= (int64_t) mPresentationCompleteFrames
Andy Hungc54b1ff2016-02-23 14:07:07 -08001739 && mAudioTrackServerProxy->isDrained();
1740 }
1741
1742 if (complete) {
Andy Hung59de4262021-06-14 10:53:54 -07001743 notifyPresentationComplete();
Eric Laurent81784c32012-11-19 14:55:58 -08001744 return true;
1745 }
1746 return false;
1747}
1748
Andy Hung59de4262021-06-14 10:53:54 -07001749// presentationComplete checked by time, used by DirectTracks.
Andy Hung3ff4b552023-06-26 19:20:57 -07001750bool Track::presentationComplete(uint32_t latencyMs)
Andy Hung59de4262021-06-14 10:53:54 -07001751{
1752 // For Offloaded or Direct tracks.
1753
1754 // For a direct track, we incorporated time based testing for presentationComplete.
1755
1756 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
1757 // to detect when all frames have been played. In this case latencyMs isn't
1758 // useful because it doesn't always reflect whether there is data in the h/w
1759 // buffers, particularly if a track has been paused and resumed during draining
1760
1761 constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
1762 if (mPresentationCompleteTimeNs == 0) {
1763 mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
1764 ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
1765 __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
1766 }
1767
1768 bool complete;
1769 if (isOffloaded()) {
1770 complete = true;
1771 } else { // Direct
1772 complete = systemTime() >= mPresentationCompleteTimeNs;
1773 ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
1774 }
1775 if (complete) {
1776 notifyPresentationComplete();
1777 return true;
1778 }
1779 return false;
1780}
1781
Andy Hung3ff4b552023-06-26 19:20:57 -07001782void Track::notifyPresentationComplete()
Andy Hung59de4262021-06-14 10:53:54 -07001783{
1784 // This only triggers once. TODO: should we enforce this?
1785 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
1786 mAudioTrackServerProxy->setStreamEndDone();
1787}
1788
Andy Hung3ff4b552023-06-26 19:20:57 -07001789void Track::triggerEvents(AudioSystem::sync_event_t type)
Eric Laurent81784c32012-11-19 14:55:58 -08001790{
Andy Hung068e08e2023-05-15 19:02:55 -07001791 for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
1792 if ((*it)->type() == type) {
Andy Hung93bb5732023-05-04 21:16:34 -07001793 ALOGV("%s: triggering SyncEvent type %d", __func__, type);
Andy Hung068e08e2023-05-15 19:02:55 -07001794 (*it)->trigger();
1795 it = mSyncEvents.erase(it);
Ivan Lozano5ec161b2017-12-06 10:00:28 -08001796 } else {
Andy Hung068e08e2023-05-15 19:02:55 -07001797 ++it;
Eric Laurent81784c32012-11-19 14:55:58 -08001798 }
1799 }
1800}
1801
1802// implement VolumeBufferProvider interface
1803
Andy Hung3ff4b552023-06-26 19:20:57 -07001804gain_minifloat_packed_t Track::getVolumeLR() const
Eric Laurent81784c32012-11-19 14:55:58 -08001805{
1806 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
1807 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kastenc56f3422014-03-21 17:53:17 -07001808 gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
1809 float vl = float_from_gain(gain_minifloat_unpack_left(vlr));
1810 float vr = float_from_gain(gain_minifloat_unpack_right(vlr));
Eric Laurent81784c32012-11-19 14:55:58 -08001811 // track volumes come from shared memory, so can't be trusted and must be clamped
Glenn Kastenc56f3422014-03-21 17:53:17 -07001812 if (vl > GAIN_FLOAT_UNITY) {
1813 vl = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001814 }
Glenn Kastenc56f3422014-03-21 17:53:17 -07001815 if (vr > GAIN_FLOAT_UNITY) {
1816 vr = GAIN_FLOAT_UNITY;
Eric Laurent81784c32012-11-19 14:55:58 -08001817 }
1818 // now apply the cached master volume and stream type volume;
1819 // this is trusted but lacks any synchronization or barrier so may be stale
1820 float v = mCachedVolume;
1821 vl *= v;
1822 vr *= v;
Glenn Kastenc56f3422014-03-21 17:53:17 -07001823 // re-combine into packed minifloat
1824 vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr));
Eric Laurent81784c32012-11-19 14:55:58 -08001825 // FIXME look at mute, pause, and stop flags
1826 return vlr;
1827}
1828
Andy Hung3ff4b552023-06-26 19:20:57 -07001829status_t Track::setSyncEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07001830 const sp<audioflinger::SyncEvent>& event)
Eric Laurent81784c32012-11-19 14:55:58 -08001831{
Eric Laurentbfb1b832013-01-07 09:53:42 -08001832 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -08001833 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
1834 (mState == STOPPED)))) {
Andy Hung9d84af52018-09-12 18:03:44 -07001835 ALOGW("%s(%d): in invalid state %d on session %d %s mode, framesReady %zu",
1836 __func__, mId,
Andy Hung959b5b82021-09-24 10:46:20 -07001837 (int)mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
Eric Laurent81784c32012-11-19 14:55:58 -08001838 event->cancel();
1839 return INVALID_OPERATION;
1840 }
1841 (void) TrackBase::setSyncEvent(event);
1842 return NO_ERROR;
1843}
1844
Andy Hung3ff4b552023-06-26 19:20:57 -07001845void Track::invalidate()
Glenn Kasten5736c352012-12-04 12:12:34 -08001846{
Eric Laurent6acd1d42017-01-04 14:23:29 -08001847 TrackBase::invalidate();
Eric Laurent4d231dc2016-03-11 18:38:23 -08001848 signalClientFlag(CBLK_INVALID);
Eric Laurent4d231dc2016-03-11 18:38:23 -08001849}
1850
Andy Hung3ff4b552023-06-26 19:20:57 -07001851void Track::disable()
Eric Laurent4d231dc2016-03-11 18:38:23 -08001852{
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01001853 // TODO(b/142394888): the filling status should also be reset to filling
Eric Laurent4d231dc2016-03-11 18:38:23 -08001854 signalClientFlag(CBLK_DISABLED);
1855}
1856
Andy Hung3ff4b552023-06-26 19:20:57 -07001857void Track::signalClientFlag(int32_t flag)
Eric Laurent4d231dc2016-03-11 18:38:23 -08001858{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001859 // FIXME should use proxy, and needs work
1860 audio_track_cblk_t* cblk = mCblk;
Eric Laurent4d231dc2016-03-11 18:38:23 -08001861 android_atomic_or(flag, &cblk->mFlags);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001862 android_atomic_release_store(0x40000000, &cblk->mFutex);
1863 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07001864 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -08001865}
1866
Andy Hung3ff4b552023-06-26 19:20:57 -07001867void Track::signal()
Eric Laurent59fe0102013-09-27 18:48:26 -07001868{
Andy Hung44f27182023-07-06 20:56:16 -07001869 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent59fe0102013-09-27 18:48:26 -07001870 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07001871 auto* const t = thread->asIAfPlaybackThread().get();
1872 Mutex::Autolock _l(t->mutex());
Eric Laurent59fe0102013-09-27 18:48:26 -07001873 t->broadcast_l();
1874 }
1875}
1876
Andy Hung3ff4b552023-06-26 19:20:57 -07001877status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001878{
1879 status_t status = INVALID_OPERATION;
1880 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001881 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001882 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001883 auto* const t = thread->asIAfPlaybackThread().get();
1884 Mutex::Autolock _l(t->mutex());
1885 status = t->getOutput_l()->stream->getDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001886 ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
1887 "%s: mode %d inconsistent", __func__, mDualMonoMode);
1888 }
1889 }
1890 return status;
1891}
1892
Andy Hung3ff4b552023-06-26 19:20:57 -07001893status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001894{
1895 status_t status = INVALID_OPERATION;
1896 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001897 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001898 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001899 auto* const t = thread->asIAfPlaybackThread().get();
1900 Mutex::Autolock lock(t->mutex());
1901 status = t->getOutput_l()->stream->setDualMonoMode(mode);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001902 if (status == NO_ERROR) {
1903 mDualMonoMode = mode;
1904 }
1905 }
1906 }
1907 return status;
1908}
1909
Andy Hung3ff4b552023-06-26 19:20:57 -07001910status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001911{
1912 status_t status = INVALID_OPERATION;
1913 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001914 sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001915 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001916 auto* const t = thread->asIAfPlaybackThread().get();
1917 Mutex::Autolock lock(t->mutex());
1918 status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001919 ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
1920 "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
1921 }
1922 }
1923 return status;
1924}
1925
Andy Hung3ff4b552023-06-26 19:20:57 -07001926status_t Track::setAudioDescriptionMixLevel(float leveldB)
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001927{
1928 status_t status = INVALID_OPERATION;
1929 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001930 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001931 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001932 auto* const t = thread->asIAfPlaybackThread().get();
1933 Mutex::Autolock lock(t->mutex());
1934 status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001935 if (status == NO_ERROR) {
1936 mAudioDescriptionMixLevel = leveldB;
1937 }
1938 }
1939 }
1940 return status;
1941}
1942
Andy Hung3ff4b552023-06-26 19:20:57 -07001943status_t Track::getPlaybackRateParameters(
Andy Hung02a6c4e2023-06-23 19:27:19 -07001944 audio_playback_rate_t* playbackRate) const
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001945{
1946 status_t status = INVALID_OPERATION;
1947 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001948 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001949 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001950 auto* const t = thread->asIAfPlaybackThread().get();
1951 Mutex::Autolock lock(t->mutex());
1952 status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001953 ALOGD_IF((status == NO_ERROR) &&
1954 !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
1955 "%s: playbackRate inconsistent", __func__);
1956 }
1957 }
1958 return status;
1959}
1960
Andy Hung3ff4b552023-06-26 19:20:57 -07001961status_t Track::setPlaybackRateParameters(
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001962 const audio_playback_rate_t& playbackRate)
1963{
1964 status_t status = INVALID_OPERATION;
1965 if (isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07001966 const sp<IAfThreadBase> thread = mThread.promote();
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001967 if (thread != nullptr) {
Andy Hung44f27182023-07-06 20:56:16 -07001968 auto* const t = thread->asIAfPlaybackThread().get();
1969 Mutex::Autolock lock(t->mutex());
1970 status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
Kuowei Lid4adbdb2020-08-13 14:44:25 +08001971 if (status == NO_ERROR) {
1972 mPlaybackRateParameters = playbackRate;
1973 }
1974 }
1975 }
1976 return status;
1977}
1978
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001979//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001980bool Track::isResumePending() const {
Andy Hung71ba4b32022-10-06 12:09:49 -07001981 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001982 return true;
Andy Hung71ba4b32022-10-06 12:09:49 -07001983 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001984 /* Resume is pending if track was stopping before pause was called */
1985 if (mState == STOPPING_1 &&
Andy Hung71ba4b32022-10-06 12:09:49 -07001986 mResumeToStopping) {
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
1990 return false;
1991}
1992
1993//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07001994void Track::resumeAck() {
Andy Hung71ba4b32022-10-06 12:09:49 -07001995 if (mState == RESUMING) {
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001996 mState = ACTIVE;
Andy Hung71ba4b32022-10-06 12:09:49 -07001997 }
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08001998
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08001999 // Other possibility of pending resume is stopping_1 state
2000 // Do not update the state from stopping as this prevents
Haynes Mathew George2d3ca682014-03-07 13:43:49 -08002001 // drain being called.
2002 if (mState == STOPPING_1) {
2003 mResumeToStopping = false;
2004 }
Krishnankutty Kolathappilly8d6c2922014-02-04 16:23:42 -08002005}
Andy Hunge10393e2015-06-12 13:59:33 -07002006
2007//To be called with thread lock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002008void Track::updateTrackFrameInfo(
Andy Hung818e7a32016-02-16 18:08:07 -08002009 int64_t trackFramesReleased, int64_t sinkFramesWritten,
Andy Hungcef2daa2018-06-01 15:31:49 -07002010 uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
Andy Hung30282562018-08-08 18:27:03 -07002011 // Make the kernel frametime available.
2012 const FrameTime ft{
2013 timeStamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2014 timeStamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2015 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2016 mKernelFrameTime.store(ft);
2017 if (!audio_is_linear_pcm(mFormat)) {
2018 return;
2019 }
2020
Andy Hung818e7a32016-02-16 18:08:07 -08002021 //update frame map
Andy Hunge10393e2015-06-12 13:59:33 -07002022 mFrameMap.push(trackFramesReleased, sinkFramesWritten);
Andy Hung818e7a32016-02-16 18:08:07 -08002023
2024 // adjust server times and set drained state.
2025 //
2026 // Our timestamps are only updated when the track is on the Thread active list.
2027 // We need to ensure that tracks are not removed before full drain.
2028 ExtendedTimestamp local = timeStamp;
Andy Hungcef2daa2018-06-01 15:31:49 -07002029 bool drained = true; // default assume drained, if no server info found
Andy Hung818e7a32016-02-16 18:08:07 -08002030 bool checked = false;
2031 for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
2032 i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
2033 // Lookup the track frame corresponding to the sink frame position.
2034 if (local.mTimeNs[i] > 0) {
2035 local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
2036 // check drain state from the latest stage in the pipeline.
Andy Hung6d7b1192016-05-07 22:59:48 -07002037 if (!checked && i <= ExtendedTimestamp::LOCATION_KERNEL) {
Andy Hungcef2daa2018-06-01 15:31:49 -07002038 drained = local.mPosition[i] >= mAudioTrackServerProxy->framesReleased();
Andy Hung818e7a32016-02-16 18:08:07 -08002039 checked = true;
2040 }
2041 }
Andy Hunge10393e2015-06-12 13:59:33 -07002042 }
Andy Hungcef2daa2018-06-01 15:31:49 -07002043
Andy Hung93bb5732023-05-04 21:16:34 -07002044 ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
2045 __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
Andy Hungcef2daa2018-06-01 15:31:49 -07002046 mAudioTrackServerProxy->setDrained(drained);
Andy Hungea2b9c02016-02-12 17:06:53 -08002047 // Set correction for flushed frames that are not accounted for in released.
Andy Hungea2b9c02016-02-12 17:06:53 -08002048 local.mFlushed = mAudioTrackServerProxy->framesFlushed();
Andy Hung818e7a32016-02-16 18:08:07 -08002049 mServerProxy->setTimestamp(local);
Andy Hungcef2daa2018-06-01 15:31:49 -07002050
2051 // Compute latency info.
2052 const bool useTrackTimestamp = !drained;
2053 const double latencyMs = useTrackTimestamp
2054 ? local.getOutputServerLatencyMs(sampleRate())
2055 : timeStamp.getOutputServerLatencyMs(halSampleRate);
2056
2057 mServerLatencyFromTrack.store(useTrackTimestamp);
2058 mServerLatencyMs.store(latencyMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002059
Andy Hung62921122020-05-18 10:47:31 -07002060 if (mLogStartCountdown > 0
2061 && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
2062 && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
2063 {
2064 if (mLogStartCountdown > 1) {
2065 --mLogStartCountdown;
2066 } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
2067 mLogStartCountdown = 0;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002068 // startup is the difference in times for the current timestamp and our start
2069 double startUpMs =
Andy Hung62921122020-05-18 10:47:31 -07002070 (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002071 // adjust for frames played.
Andy Hung62921122020-05-18 10:47:31 -07002072 startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
2073 * 1e3 / mSampleRate;
2074 ALOGV("%s: latencyMs:%lf startUpMs:%lf"
2075 " localTime:%lld startTime:%lld"
2076 " localPosition:%lld startPosition:%lld",
2077 __func__, latencyMs, startUpMs,
2078 (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002079 (long long)mLogStartTimeNs,
Andy Hung62921122020-05-18 10:47:31 -07002080 (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
Andy Hungb68f5eb2019-12-03 16:49:17 -08002081 (long long)mLogStartFrames);
Andy Hungc2b11cb2020-04-22 09:04:01 -07002082 mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
Andy Hungb68f5eb2019-12-03 16:49:17 -08002083 }
Andy Hung62921122020-05-18 10:47:31 -07002084 mLogLatencyMs = latencyMs;
Andy Hungb68f5eb2019-12-03 16:49:17 -08002085 }
Andy Hunge10393e2015-06-12 13:59:33 -07002086}
2087
Andy Hung3ff4b552023-06-26 19:20:57 -07002088bool Track::AudioVibrationController::setMute(bool muted) {
Andy Hung44f27182023-07-06 20:56:16 -07002089 const sp<IAfThreadBase> thread = mTrack->mThread.promote();
jiabin57303cc2018-12-18 15:45:57 -08002090 if (thread != 0) {
2091 // Lock for updating mHapticPlaybackEnabled.
Andy Hung44f27182023-07-06 20:56:16 -07002092 Mutex::Autolock _l(thread->mutex());
2093 auto* const playbackThread = thread->asIAfPlaybackThread().get();
jiabin57303cc2018-12-18 15:45:57 -08002094 if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
Andy Hung44f27182023-07-06 20:56:16 -07002095 && playbackThread->hapticChannelCount() > 0) {
SPeak Shenc19aa9e2022-11-11 00:28:50 +08002096 ALOGD("%s, haptic playback was %s for track %d",
2097 __func__, muted ? "muted" : "unmuted", mTrack->id());
SPeak Shen0db56b32022-11-11 00:28:50 +08002098 mTrack->setHapticPlaybackEnabled(!muted);
2099 return true;
jiabin57303cc2018-12-18 15:45:57 -08002100 }
2101 }
SPeak Shen0db56b32022-11-11 00:28:50 +08002102 return false;
2103}
2104
Andy Hung3ff4b552023-06-26 19:20:57 -07002105binder::Status Track::AudioVibrationController::mute(
SPeak Shen0db56b32022-11-11 00:28:50 +08002106 /*out*/ bool *ret) {
2107 *ret = setMute(true);
jiabin57303cc2018-12-18 15:45:57 -08002108 return binder::Status::ok();
2109}
2110
Andy Hung3ff4b552023-06-26 19:20:57 -07002111binder::Status Track::AudioVibrationController::unmute(
jiabin57303cc2018-12-18 15:45:57 -08002112 /*out*/ bool *ret) {
SPeak Shen0db56b32022-11-11 00:28:50 +08002113 *ret = setMute(false);
jiabin57303cc2018-12-18 15:45:57 -08002114 return binder::Status::ok();
2115}
2116
Eric Laurent81784c32012-11-19 14:55:58 -08002117// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002118#undef LOG_TAG
2119#define LOG_TAG "AF::OutputTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002120
Andy Hung3ff4b552023-06-26 19:20:57 -07002121/* static */
Andy Hung44f27182023-07-06 20:56:16 -07002122sp<IAfOutputTrack> IAfOutputTrack::create(
2123 IAfPlaybackThread* playbackThread,
2124 IAfDuplicatingThread* sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002125 uint32_t sampleRate,
2126 audio_format_t format,
2127 audio_channel_mask_t channelMask,
2128 size_t frameCount,
2129 const AttributionSourceState& attributionSource) {
2130 return sp<OutputTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002131 playbackThread,
2132 sourceThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002133 sampleRate,
2134 format,
2135 channelMask,
2136 frameCount,
2137 attributionSource);
2138}
2139
2140OutputTrack::OutputTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002141 IAfPlaybackThread* playbackThread,
2142 IAfDuplicatingThread* sourceThread,
Eric Laurent81784c32012-11-19 14:55:58 -08002143 uint32_t sampleRate,
2144 audio_format_t format,
2145 audio_channel_mask_t channelMask,
Marco Nelissen462fd2f2013-01-14 14:12:05 -08002146 size_t frameCount,
Svet Ganov33761132021-05-13 22:51:08 +00002147 const AttributionSourceState& attributionSource)
Eric Laurent223fd5c2014-11-11 13:43:36 -08002148 : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002149 audio_attributes_t{} /* currently unused for output track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002150 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002151 nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002152 AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
Glenn Kastend848eb42016-03-08 13:42:11 -08002153 TYPE_OUTPUT),
Eric Laurent5bba2f62016-03-18 11:14:14 -07002154 mActive(false), mSourceThread(sourceThread)
Eric Laurent81784c32012-11-19 14:55:58 -08002155{
2156
2157 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08002158 mOutBuffer.frameCount = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002159 playbackThread->addOutputTrack_l(this);
Andy Hung9d84af52018-09-12 18:03:44 -07002160 ALOGV("%s(): mCblk %p, mBuffer %p, "
Glenn Kastenc42e9b42016-03-21 11:35:03 -07002161 "frameCount %zu, mChannelMask 0x%08x",
Andy Hung9d84af52018-09-12 18:03:44 -07002162 __func__, mCblk, mBuffer,
Glenn Kasten74935e42013-12-19 08:56:45 -08002163 frameCount, mChannelMask);
Glenn Kastene3aa6592012-12-04 12:22:46 -08002164 // since client and server are in the same process,
2165 // the buffer has the same virtual address on both sides
Glenn Kasten529c61b2014-07-18 15:31:02 -07002166 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
2167 true /*clientInServer*/);
Glenn Kastenc56f3422014-03-21 17:53:17 -07002168 mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
Eric Laurent8d2d4932013-04-25 12:56:18 -07002169 mClientProxy->setSendLevel(0.0);
2170 mClientProxy->setSampleRate(sampleRate);
Eric Laurent81784c32012-11-19 14:55:58 -08002171 } else {
Andy Hung9d84af52018-09-12 18:03:44 -07002172 ALOGW("%s(%d): Error creating output track on thread %d",
2173 __func__, mId, (int)mThreadIoHandle);
Eric Laurent81784c32012-11-19 14:55:58 -08002174 }
2175}
2176
Andy Hung3ff4b552023-06-26 19:20:57 -07002177OutputTrack::~OutputTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002178{
2179 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08002180 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08002181}
2182
Andy Hung3ff4b552023-06-26 19:20:57 -07002183status_t OutputTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002184 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002185{
2186 status_t status = Track::start(event, triggerSession);
2187 if (status != NO_ERROR) {
2188 return status;
2189 }
2190
2191 mActive = true;
2192 mRetryCount = 127;
2193 return status;
2194}
2195
Andy Hung3ff4b552023-06-26 19:20:57 -07002196void OutputTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002197{
2198 Track::stop();
2199 clearBufferQueue();
2200 mOutBuffer.frameCount = 0;
2201 mActive = false;
2202}
2203
Andy Hung3ff4b552023-06-26 19:20:57 -07002204ssize_t OutputTrack::write(void* data, uint32_t frames)
Eric Laurent81784c32012-11-19 14:55:58 -08002205{
Eric Laurent19952e12023-04-20 10:08:29 +02002206 if (!mActive && frames != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002207 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002208 if (thread != nullptr && thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002209 // preload one silent buffer to trigger mixer on start()
2210 ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
2211 status_t status = mClientProxy->obtainBuffer(&buf);
2212 if (status != NO_ERROR && status != NOT_ENOUGH_DATA && status != WOULD_BLOCK) {
2213 ALOGE("%s(%d): could not obtain buffer on start", __func__, mId);
2214 return 0;
2215 }
2216 memset(buf.mRaw, 0, buf.mFrameCount * mFrameSize);
2217 mClientProxy->releaseBuffer(&buf);
2218
2219 (void) start();
2220
2221 // wait for HAL stream to start before sending actual audio. Doing this on each
2222 // OutputTrack makes that playback start on all output streams is synchronized.
2223 // If another OutputTrack has already started it can underrun but this is OK
2224 // as only silence has been played so far and the retry count is very high on
2225 // OutputTrack.
Andy Hung44f27182023-07-06 20:56:16 -07002226 auto* const pt = thread->asIAfPlaybackThread().get();
Eric Laurent19952e12023-04-20 10:08:29 +02002227 if (!pt->waitForHalStart()) {
2228 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
2229 stop();
2230 return 0;
2231 }
2232
2233 // enqueue the first buffer and exit so that other OutputTracks will also start before
2234 // write() is called again and this buffer actually consumed.
2235 Buffer firstBuffer;
2236 firstBuffer.frameCount = frames;
2237 firstBuffer.raw = data;
2238 queueBuffer(firstBuffer);
2239 return frames;
2240 } else {
2241 (void) start();
2242 }
2243 }
2244
Eric Laurent81784c32012-11-19 14:55:58 -08002245 Buffer *pInBuffer;
2246 Buffer inBuffer;
Eric Laurent81784c32012-11-19 14:55:58 -08002247 inBuffer.frameCount = frames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002248 inBuffer.raw = data;
Eric Laurent81784c32012-11-19 14:55:58 -08002249 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
Eric Laurent81784c32012-11-19 14:55:58 -08002250 while (waitTimeLeftMs) {
2251 // First write pending buffers, then new data
2252 if (mBufferQueue.size()) {
2253 pInBuffer = mBufferQueue.itemAt(0);
2254 } else {
2255 pInBuffer = &inBuffer;
2256 }
2257
2258 if (pInBuffer->frameCount == 0) {
2259 break;
2260 }
2261
2262 if (mOutBuffer.frameCount == 0) {
2263 mOutBuffer.frameCount = pInBuffer->frameCount;
2264 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002265 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002266 if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
Andy Hung9d84af52018-09-12 18:03:44 -07002267 ALOGV("%s(%d): thread %d no more output buffers; status %d",
2268 __func__, mId,
2269 (int)mThreadIoHandle, status);
Eric Laurent81784c32012-11-19 14:55:58 -08002270 break;
2271 }
2272 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
2273 if (waitTimeLeftMs >= waitTimeMs) {
2274 waitTimeLeftMs -= waitTimeMs;
2275 } else {
2276 waitTimeLeftMs = 0;
2277 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002278 if (status == NOT_ENOUGH_DATA) {
2279 restartIfDisabled();
2280 continue;
2281 }
Eric Laurent81784c32012-11-19 14:55:58 -08002282 }
2283
2284 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
2285 pInBuffer->frameCount;
Andy Hungc25b84a2015-01-14 19:04:10 -08002286 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002287 Proxy::Buffer buf;
2288 buf.mFrameCount = outFrames;
2289 buf.mRaw = NULL;
2290 mClientProxy->releaseBuffer(&buf);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002291 restartIfDisabled();
Eric Laurent81784c32012-11-19 14:55:58 -08002292 pInBuffer->frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002293 pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002294 mOutBuffer.frameCount -= outFrames;
Andy Hungc25b84a2015-01-14 19:04:10 -08002295 mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -08002296
2297 if (pInBuffer->frameCount == 0) {
2298 if (mBufferQueue.size()) {
2299 mBufferQueue.removeAt(0);
Andy Hungc25b84a2015-01-14 19:04:10 -08002300 free(pInBuffer->mBuffer);
Yunlian Jiang8adc8082017-06-06 15:59:44 -07002301 if (pInBuffer != &inBuffer) {
2302 delete pInBuffer;
2303 }
Andy Hung9d84af52018-09-12 18:03:44 -07002304 ALOGV("%s(%d): thread %d released overflow buffer %zu",
2305 __func__, mId,
2306 (int)mThreadIoHandle, mBufferQueue.size());
Eric Laurent81784c32012-11-19 14:55:58 -08002307 } else {
2308 break;
2309 }
2310 }
2311 }
2312
2313 // If we could not write all frames, allocate a buffer and queue it for next time.
2314 if (inBuffer.frameCount) {
Andy Hung44f27182023-07-06 20:56:16 -07002315 const sp<IAfThreadBase> thread = mThread.promote();
Andy Hung4989d312023-06-29 21:19:25 -07002316 if (thread != nullptr && !thread->inStandby()) {
Eric Laurent19952e12023-04-20 10:08:29 +02002317 queueBuffer(inBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002318 }
2319 }
2320
Andy Hungc25b84a2015-01-14 19:04:10 -08002321 // Calling write() with a 0 length buffer means that no more data will be written:
2322 // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
2323 if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
2324 stop();
Eric Laurent81784c32012-11-19 14:55:58 -08002325 }
2326
Andy Hung1c86ebe2018-05-29 20:29:08 -07002327 return frames - inBuffer.frameCount; // number of frames consumed.
Eric Laurent81784c32012-11-19 14:55:58 -08002328}
2329
Andy Hung3ff4b552023-06-26 19:20:57 -07002330void OutputTrack::queueBuffer(Buffer& inBuffer) {
Eric Laurent19952e12023-04-20 10:08:29 +02002331
2332 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
2333 Buffer *pInBuffer = new Buffer;
2334 const size_t bufferSize = inBuffer.frameCount * mFrameSize;
2335 pInBuffer->mBuffer = malloc(bufferSize);
2336 LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
2337 "%s: Unable to malloc size %zu", __func__, bufferSize);
2338 pInBuffer->frameCount = inBuffer.frameCount;
2339 pInBuffer->raw = pInBuffer->mBuffer;
2340 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
2341 mBufferQueue.add(pInBuffer);
2342 ALOGV("%s(%d): thread %d adding overflow buffer %zu", __func__, mId,
2343 (int)mThreadIoHandle, mBufferQueue.size());
2344 // audio data is consumed (stored locally); set frameCount to 0.
2345 inBuffer.frameCount = 0;
2346 } else {
2347 ALOGW("%s(%d): thread %d no more overflow buffers",
2348 __func__, mId, (int)mThreadIoHandle);
2349 // TODO: return error for this.
2350 }
2351}
2352
Andy Hung3ff4b552023-06-26 19:20:57 -07002353void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
Kevin Rocard12381092018-04-11 09:19:59 -07002354{
2355 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2356 backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
2357}
2358
Andy Hung3ff4b552023-06-26 19:20:57 -07002359void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
Kevin Rocard12381092018-04-11 09:19:59 -07002360 {
2361 std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
2362 mTrackMetadatas = metadatas;
2363 }
2364 // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
2365 setMetadataHasChanged();
2366}
2367
Andy Hung3ff4b552023-06-26 19:20:57 -07002368status_t OutputTrack::obtainBuffer(
Eric Laurent81784c32012-11-19 14:55:58 -08002369 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
2370{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002371 ClientProxy::Buffer buf;
2372 buf.mFrameCount = buffer->frameCount;
2373 struct timespec timeout;
2374 timeout.tv_sec = waitTimeMs / 1000;
2375 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
2376 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
2377 buffer->frameCount = buf.mFrameCount;
2378 buffer->raw = buf.mRaw;
2379 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002380}
2381
Andy Hung3ff4b552023-06-26 19:20:57 -07002382void OutputTrack::clearBufferQueue()
Eric Laurent81784c32012-11-19 14:55:58 -08002383{
2384 size_t size = mBufferQueue.size();
2385
2386 for (size_t i = 0; i < size; i++) {
2387 Buffer *pBuffer = mBufferQueue.itemAt(i);
Andy Hungc25b84a2015-01-14 19:04:10 -08002388 free(pBuffer->mBuffer);
Eric Laurent81784c32012-11-19 14:55:58 -08002389 delete pBuffer;
2390 }
2391 mBufferQueue.clear();
2392}
2393
Andy Hung3ff4b552023-06-26 19:20:57 -07002394void OutputTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002395{
2396 int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2397 if (mActive && (flags & CBLK_DISABLED)) {
2398 start();
2399 }
2400}
Eric Laurent81784c32012-11-19 14:55:58 -08002401
Andy Hung9d84af52018-09-12 18:03:44 -07002402// ----------------------------------------------------------------------------
2403#undef LOG_TAG
2404#define LOG_TAG "AF::PatchTrack"
2405
Andy Hung3ff4b552023-06-26 19:20:57 -07002406/* static */
2407sp<IAfPatchTrack> IAfPatchTrack::create(
Andy Hung44f27182023-07-06 20:56:16 -07002408 IAfPlaybackThread* playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002409 audio_stream_type_t streamType,
2410 uint32_t sampleRate,
2411 audio_channel_mask_t channelMask,
2412 audio_format_t format,
2413 size_t frameCount,
2414 void* buffer,
2415 size_t bufferSize,
2416 audio_output_flags_t flags,
2417 const Timeout& timeout,
2418 size_t frameCountToBeReady /** Default behaviour is to start
2419 * as soon as possible to have
2420 * the lowest possible latency
2421 * even if it might glitch. */)
2422{
2423 return sp<PatchTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002424 playbackThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002425 streamType,
2426 sampleRate,
2427 channelMask,
2428 format,
2429 frameCount,
2430 buffer,
2431 bufferSize,
2432 flags,
2433 timeout,
2434 frameCountToBeReady);
2435}
2436
Andy Hung44f27182023-07-06 20:56:16 -07002437PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
Eric Laurent3bcf8592015-04-03 12:13:24 -07002438 audio_stream_type_t streamType,
Eric Laurent83b88082014-06-20 18:31:16 -07002439 uint32_t sampleRate,
2440 audio_channel_mask_t channelMask,
2441 audio_format_t format,
2442 size_t frameCount,
2443 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002444 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08002445 audio_output_flags_t flags,
Kevin Rocard01c7d9e2019-09-18 11:24:52 +01002446 const Timeout& timeout,
2447 size_t frameCountToBeReady)
Eric Laurent3bcf8592015-04-03 12:13:24 -07002448 : Track(playbackThread, NULL, streamType,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002449 audio_attributes_t{} /* currently unused for patch track */,
Eric Laurent223fd5c2014-11-11 13:43:36 -08002450 sampleRate, format, channelMask, frameCount,
Andy Hung8fe68032017-06-05 16:17:51 -07002451 buffer, bufferSize, nullptr /* sharedBuffer */,
Svet Ganov33761132021-05-13 22:51:08 +00002452 AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002453 TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
gaoxiupei8e3a5682023-07-07 20:30:23 +08002454 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
2455 : nullptr,
Kevin Rocard45986c72018-12-18 18:22:59 -08002456 *playbackThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07002457{
Andy Hung9d84af52018-09-12 18:03:44 -07002458 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
2459 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07002460 (int)mPeerTimeout.tv_sec,
2461 (int)(mPeerTimeout.tv_nsec / 1000000));
2462}
2463
Andy Hung3ff4b552023-06-26 19:20:57 -07002464PatchTrack::~PatchTrack()
Eric Laurent83b88082014-06-20 18:31:16 -07002465{
Andy Hungabfab202019-03-07 19:45:54 -08002466 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002467}
2468
Andy Hung3ff4b552023-06-26 19:20:57 -07002469size_t PatchTrack::framesReady() const
Mikhail Naganovcaf59942019-09-25 14:05:29 -07002470{
2471 if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
2472 return std::numeric_limits<size_t>::max();
2473 } else {
2474 return Track::framesReady();
2475 }
2476}
2477
Andy Hung3ff4b552023-06-26 19:20:57 -07002478status_t PatchTrack::start(AudioSystem::sync_event_t event,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002479 audio_session_t triggerSession)
Eric Laurent4d231dc2016-03-11 18:38:23 -08002480{
2481 status_t status = Track::start(event, triggerSession);
2482 if (status != NO_ERROR) {
2483 return status;
2484 }
2485 android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
2486 return status;
2487}
2488
Eric Laurent83b88082014-06-20 18:31:16 -07002489// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002490status_t PatchTrack::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08002491 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002492{
Andy Hung9d84af52018-09-12 18:03:44 -07002493 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002494 Proxy::Buffer buf;
2495 buf.mFrameCount = buffer->frameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002496 if (ATRACE_ENABLED()) {
2497 std::string traceName("PTnReq");
2498 traceName += std::to_string(id());
2499 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2500 }
Eric Laurent83b88082014-06-20 18:31:16 -07002501 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
Andy Hung9d84af52018-09-12 18:03:44 -07002502 ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07002503 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07002504 if (ATRACE_ENABLED()) {
2505 std::string traceName("PTnObt");
2506 traceName += std::to_string(id());
2507 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
2508 }
Eric Laurent83b88082014-06-20 18:31:16 -07002509 if (buf.mFrameCount == 0) {
2510 return WOULD_BLOCK;
2511 }
Glenn Kastend79072e2016-01-06 08:41:20 -08002512 status = Track::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07002513 return status;
2514}
2515
Andy Hung3ff4b552023-06-26 19:20:57 -07002516void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002517{
Andy Hung9d84af52018-09-12 18:03:44 -07002518 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002519 Proxy::Buffer buf;
2520 buf.mFrameCount = buffer->frameCount;
2521 buf.mRaw = buffer->raw;
2522 mPeerProxy->releaseBuffer(&buf);
Andy Hung71ba4b32022-10-06 12:09:49 -07002523 TrackBase::releaseBuffer(buffer); // Note: this is the base class.
Eric Laurent83b88082014-06-20 18:31:16 -07002524}
2525
Andy Hung3ff4b552023-06-26 19:20:57 -07002526status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07002527 const struct timespec *timeOut)
2528{
Eric Laurent4d231dc2016-03-11 18:38:23 -08002529 status_t status = NO_ERROR;
2530 static const int32_t kMaxTries = 5;
2531 int32_t tryCounter = kMaxTries;
Andy Hungf62e1a22018-05-08 18:32:11 -07002532 const size_t originalFrameCount = buffer->mFrameCount;
Eric Laurent4d231dc2016-03-11 18:38:23 -08002533 do {
2534 if (status == NOT_ENOUGH_DATA) {
2535 restartIfDisabled();
Andy Hungf62e1a22018-05-08 18:32:11 -07002536 buffer->mFrameCount = originalFrameCount; // cleared on error, must be restored.
Eric Laurent4d231dc2016-03-11 18:38:23 -08002537 }
2538 status = mProxy->obtainBuffer(buffer, timeOut);
2539 } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
2540 return status;
Eric Laurent83b88082014-06-20 18:31:16 -07002541}
2542
Andy Hung3ff4b552023-06-26 19:20:57 -07002543void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07002544{
2545 mProxy->releaseBuffer(buffer);
Eric Laurent4d231dc2016-03-11 18:38:23 -08002546 restartIfDisabled();
naoki miyazuf37f9982019-11-28 11:18:18 +09002547
2548 // Check if the PatchTrack has enough data to write once in releaseBuffer().
2549 // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
2550 // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
2551 // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
Andy Hung3ff4b552023-06-26 19:20:57 -07002552 if (mFillingStatus == FS_ACTIVE
naoki miyazuf37f9982019-11-28 11:18:18 +09002553 && audio_is_linear_pcm(mFormat)
2554 && !isOffloadedOrDirect()) {
Andy Hung44f27182023-07-06 20:56:16 -07002555 if (const sp<IAfThreadBase> thread = mThread.promote();
naoki miyazuf37f9982019-11-28 11:18:18 +09002556 thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002557 auto* const playbackThread = thread->asIAfPlaybackThread().get();
naoki miyazuf37f9982019-11-28 11:18:18 +09002558 const size_t frameCount = playbackThread->frameCount() * sampleRate()
2559 / playbackThread->sampleRate();
2560 if (framesReady() < frameCount) {
2561 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
Andy Hung3ff4b552023-06-26 19:20:57 -07002562 mFillingStatus = FS_FILLING;
naoki miyazuf37f9982019-11-28 11:18:18 +09002563 }
2564 }
2565 }
Eric Laurent4d231dc2016-03-11 18:38:23 -08002566}
2567
Andy Hung3ff4b552023-06-26 19:20:57 -07002568void PatchTrack::restartIfDisabled()
Eric Laurent4d231dc2016-03-11 18:38:23 -08002569{
Eric Laurent83b88082014-06-20 18:31:16 -07002570 if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
Andy Hung9d84af52018-09-12 18:03:44 -07002571 ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07002572 start();
2573 }
Eric Laurent83b88082014-06-20 18:31:16 -07002574}
2575
Eric Laurent81784c32012-11-19 14:55:58 -08002576// ----------------------------------------------------------------------------
2577// Record
2578// ----------------------------------------------------------------------------
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002579
2580
Andy Hung9d84af52018-09-12 18:03:44 -07002581#undef LOG_TAG
2582#define LOG_TAG "AF::RecordHandle"
Eric Laurent81784c32012-11-19 14:55:58 -08002583
Andy Hungaaa18282023-06-23 19:27:19 -07002584class RecordHandle : public android::media::BnAudioRecord {
2585public:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002586 explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
Andy Hungaaa18282023-06-23 19:27:19 -07002587 ~RecordHandle() override;
2588 binder::Status start(int /*AudioSystem::sync_event_t*/ event,
2589 int /*audio_session_t*/ triggerSession) final;
2590 binder::Status stop() final;
2591 binder::Status getActiveMicrophones(
2592 std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
2593 binder::Status setPreferredMicrophoneDirection(
2594 int /*audio_microphone_direction_t*/ direction) final;
2595 binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
2596 binder::Status shareAudioHistory(
2597 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
2598
2599private:
Andy Hung02a6c4e2023-06-23 19:27:19 -07002600 const sp<IAfRecordTrack> mRecordTrack;
Andy Hungaaa18282023-06-23 19:27:19 -07002601
2602 // for use from destructor
2603 void stop_nonvirtual();
2604};
2605
2606/* static */
Andy Hung02a6c4e2023-06-23 19:27:19 -07002607sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
2608 const sp<IAfRecordTrack>& recordTrack) {
Andy Hungaaa18282023-06-23 19:27:19 -07002609 return sp<RecordHandle>::make(recordTrack);
2610}
2611
2612RecordHandle::RecordHandle(
Andy Hung02a6c4e2023-06-23 19:27:19 -07002613 const sp<IAfRecordTrack>& recordTrack)
Eric Laurent81784c32012-11-19 14:55:58 -08002614 : BnAudioRecord(),
2615 mRecordTrack(recordTrack)
2616{
Andy Hungaaa18282023-06-23 19:27:19 -07002617 // TODO(b/288339104) binder thread priority change not needed.
Andy Hung225aef62022-12-06 16:33:20 -08002618 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent81784c32012-11-19 14:55:58 -08002619}
2620
Andy Hungaaa18282023-06-23 19:27:19 -07002621RecordHandle::~RecordHandle() {
Eric Laurent81784c32012-11-19 14:55:58 -08002622 stop_nonvirtual();
2623 mRecordTrack->destroy();
2624}
2625
Andy Hungaaa18282023-06-23 19:27:19 -07002626binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002627 int /*audio_session_t*/ triggerSession) {
Andy Hung9d84af52018-09-12 18:03:44 -07002628 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002629 return binderStatusFromStatusT(
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002630 mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
Eric Laurent81784c32012-11-19 14:55:58 -08002631}
2632
Andy Hungaaa18282023-06-23 19:27:19 -07002633binder::Status RecordHandle::stop() {
Eric Laurent81784c32012-11-19 14:55:58 -08002634 stop_nonvirtual();
Ivan Lozanoff6900d2017-08-01 15:47:38 -07002635 return binder::Status::ok();
Eric Laurent81784c32012-11-19 14:55:58 -08002636}
2637
Andy Hungaaa18282023-06-23 19:27:19 -07002638void RecordHandle::stop_nonvirtual() {
Andy Hung9d84af52018-09-12 18:03:44 -07002639 ALOGV("%s()", __func__);
Eric Laurent81784c32012-11-19 14:55:58 -08002640 mRecordTrack->stop();
2641}
2642
Andy Hungaaa18282023-06-23 19:27:19 -07002643binder::Status RecordHandle::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002644 std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
Andy Hung9d84af52018-09-12 18:03:44 -07002645 ALOGV("%s()", __func__);
Mikhail Naganov2a6a3012023-02-13 11:45:03 -08002646 return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
jiabin653cc0a2018-01-17 17:54:10 -08002647}
2648
Andy Hungaaa18282023-06-23 19:27:19 -07002649binder::Status RecordHandle::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002650 int /*audio_microphone_direction_t*/ direction) {
2651 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002652 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07002653 static_cast<audio_microphone_direction_t>(direction)));
2654}
2655
Andy Hungaaa18282023-06-23 19:27:19 -07002656binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07002657 ALOGV("%s()", __func__);
Andy Hung1131b6e2020-12-08 20:47:45 -08002658 return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
Paul McLean03a6e6a2018-12-04 10:54:13 -07002659}
2660
Andy Hungaaa18282023-06-23 19:27:19 -07002661binder::Status RecordHandle::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02002662 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
2663 return binderStatusFromStatusT(
2664 mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
2665}
2666
Eric Laurent81784c32012-11-19 14:55:58 -08002667// ----------------------------------------------------------------------------
Andy Hung9d84af52018-09-12 18:03:44 -07002668#undef LOG_TAG
2669#define LOG_TAG "AF::RecordTrack"
Eric Laurent81784c32012-11-19 14:55:58 -08002670
Andy Hung3ff4b552023-06-26 19:20:57 -07002671
2672/* static */ // TODO(b/288339104)
Andy Hung44f27182023-07-06 20:56:16 -07002673sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002674 const sp<Client>& client,
2675 const audio_attributes_t& attr,
2676 uint32_t sampleRate,
2677 audio_format_t format,
2678 audio_channel_mask_t channelMask,
2679 size_t frameCount,
2680 void* buffer,
2681 size_t bufferSize,
2682 audio_session_t sessionId,
2683 pid_t creatorPid,
2684 const AttributionSourceState& attributionSource,
2685 audio_input_flags_t flags,
2686 track_type type,
2687 audio_port_handle_t portId,
2688 int32_t startFrames)
2689{
2690 return sp<RecordTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07002691 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07002692 client,
2693 attr,
2694 sampleRate,
2695 format,
2696 channelMask,
2697 frameCount,
2698 buffer,
2699 bufferSize,
2700 sessionId,
2701 creatorPid,
2702 attributionSource,
2703 flags,
2704 type,
2705 portId,
2706 startFrames);
2707}
2708
Glenn Kasten05997e22014-03-13 15:08:33 -07002709// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
Andy Hung3ff4b552023-06-26 19:20:57 -07002710RecordTrack::RecordTrack(
Andy Hung44f27182023-07-06 20:56:16 -07002711 IAfRecordThread* thread,
Eric Laurent81784c32012-11-19 14:55:58 -08002712 const sp<Client>& client,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002713 const audio_attributes_t& attr,
Eric Laurent81784c32012-11-19 14:55:58 -08002714 uint32_t sampleRate,
2715 audio_format_t format,
2716 audio_channel_mask_t channelMask,
2717 size_t frameCount,
Eric Laurent83b88082014-06-20 18:31:16 -07002718 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07002719 size_t bufferSize,
Glenn Kastend848eb42016-03-08 13:42:11 -08002720 audio_session_t sessionId,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002721 pid_t creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002722 const AttributionSourceState& attributionSource,
Eric Laurent05067782016-06-01 18:27:28 -07002723 audio_input_flags_t flags,
Eric Laurent20b9ef02016-12-05 11:03:16 -08002724 track_type type,
Eric Laurentec376dc2021-04-08 20:41:22 +02002725 audio_port_handle_t portId,
Eric Laurent2407ce32021-04-26 14:56:03 +02002726 int32_t startFrames)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07002727 : TrackBase(thread, client, attr, sampleRate, format,
Eric Laurent09f1ed22019-04-24 17:45:17 -07002728 channelMask, frameCount, buffer, bufferSize, sessionId,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002729 creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00002730 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07002731 false /*isOut*/,
Eric Laurent83b88082014-06-20 18:31:16 -07002732 (type == TYPE_DEFAULT) ?
Eric Laurent05067782016-06-01 18:27:28 -07002733 ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
Eric Laurent83b88082014-06-20 18:31:16 -07002734 ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
Andy Hungb68f5eb2019-12-03 16:49:17 -08002735 type, portId,
2736 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
Andy Hung97a893e2015-03-29 01:03:07 -07002737 mOverflow(false),
Andy Hung4c6afaf2015-06-12 18:23:35 -07002738 mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
Eric Laurent05067782016-06-01 18:27:28 -07002739 mRecordBufferConverter(NULL),
jiabin9378eb92018-05-02 15:26:35 -07002740 mFlags(flags),
Jean-Michel Trividdf87ef2019-08-20 15:42:04 -07002741 mSilenced(false),
Eric Laurent2407ce32021-04-26 14:56:03 +02002742 mStartFrames(startFrames)
Eric Laurent81784c32012-11-19 14:55:58 -08002743{
Glenn Kasten3ef14ef2014-03-13 15:08:51 -07002744 if (mCblk == NULL) {
2745 return;
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002746 }
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002747
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002748 if (!isDirect()) {
2749 mRecordBufferConverter = new RecordBufferConverter(
Andy Hung44f27182023-07-06 20:56:16 -07002750 thread->channelMask(), thread->format(), thread->sampleRate(),
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002751 channelMask, format, sampleRate);
2752 // Check if the RecordBufferConverter construction was successful.
2753 // If not, don't continue with construction.
2754 //
2755 // NOTE: It would be extremely rare that the record track cannot be created
2756 // for the current device, but a pending or future device change would make
2757 // the record track configuration valid.
2758 if (mRecordBufferConverter->initCheck() != NO_ERROR) {
Andy Hung9d84af52018-09-12 18:03:44 -07002759 ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
Mikhail Naganov7c6ae982018-06-14 12:33:38 -07002760 return;
2761 }
Andy Hung97a893e2015-03-29 01:03:07 -07002762 }
2763
Andy Hung6ae58432016-02-16 18:32:24 -08002764 mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
Andy Hung3f0c9022016-01-15 17:49:46 -08002765 mFrameSize, !isExternalTrack());
Andy Hung3f0c9022016-01-15 17:49:46 -08002766
Andy Hung97a893e2015-03-29 01:03:07 -07002767 mResamplerBufferProvider = new ResamplerBufferProvider(this);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002768
Eric Laurent05067782016-06-01 18:27:28 -07002769 if (flags & AUDIO_INPUT_FLAG_FAST) {
Andy Hung44f27182023-07-06 20:56:16 -07002770 ALOG_ASSERT(thread->fastTrackAvailable());
2771 thread->setFastTrackAvailable(false);
Andy Hung000adb52018-06-01 15:43:26 -07002772 } else {
2773 // TODO: only Normal Record has timestamps (Fast Record does not).
Andy Hung5d3d9562018-10-04 19:27:26 -07002774 mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
Glenn Kastenc263ca02014-06-04 20:31:46 -07002775 }
Andy Hung8946a282018-04-19 20:04:56 -07002776#ifdef TEE_SINK
2777 mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
2778 + "_" + std::to_string(mId)
2779 + "_R");
2780#endif
Andy Hungb68f5eb2019-12-03 16:49:17 -08002781
2782 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07002783 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent81784c32012-11-19 14:55:58 -08002784}
2785
Andy Hung3ff4b552023-06-26 19:20:57 -07002786RecordTrack::~RecordTrack()
Eric Laurent81784c32012-11-19 14:55:58 -08002787{
Andy Hung9d84af52018-09-12 18:03:44 -07002788 ALOGV("%s()", __func__);
Andy Hung97a893e2015-03-29 01:03:07 -07002789 delete mRecordBufferConverter;
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002790 delete mResamplerBufferProvider;
Eric Laurent81784c32012-11-19 14:55:58 -08002791}
2792
Andy Hung3ff4b552023-06-26 19:20:57 -07002793status_t RecordTrack::initCheck() const
Andy Hung97a893e2015-03-29 01:03:07 -07002794{
2795 status_t status = TrackBase::initCheck();
2796 if (status == NO_ERROR && mServerProxy == 0) {
2797 status = BAD_VALUE;
2798 }
2799 return status;
2800}
2801
Eric Laurent81784c32012-11-19 14:55:58 -08002802// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07002803status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent81784c32012-11-19 14:55:58 -08002804{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002805 ServerProxy::Buffer buf;
2806 buf.mFrameCount = buffer->frameCount;
2807 status_t status = mServerProxy->obtainBuffer(&buf);
2808 buffer->frameCount = buf.mFrameCount;
2809 buffer->raw = buf.mRaw;
2810 if (buf.mFrameCount == 0) {
2811 // FIXME also wake futex so that overrun is noticed more quickly
Glenn Kasten96f60d82013-07-12 10:21:18 -07002812 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->mFlags);
Eric Laurent81784c32012-11-19 14:55:58 -08002813 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08002814 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08002815}
2816
Andy Hung3ff4b552023-06-26 19:20:57 -07002817status_t RecordTrack::start(AudioSystem::sync_event_t event,
Glenn Kastend848eb42016-03-08 13:42:11 -08002818 audio_session_t triggerSession)
Eric Laurent81784c32012-11-19 14:55:58 -08002819{
Andy Hung44f27182023-07-06 20:56:16 -07002820 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002821 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002822 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent81784c32012-11-19 14:55:58 -08002823 return recordThread->start(this, event, triggerSession);
2824 } else {
Eric Laurentd52a28c2020-08-21 17:10:39 -07002825 ALOGW("%s track %d: thread was destroyed", __func__, portId());
2826 return DEAD_OBJECT;
Eric Laurent81784c32012-11-19 14:55:58 -08002827 }
2828}
2829
Andy Hung3ff4b552023-06-26 19:20:57 -07002830void RecordTrack::stop()
Eric Laurent81784c32012-11-19 14:55:58 -08002831{
Andy Hung44f27182023-07-06 20:56:16 -07002832 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002833 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002834 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurent83b88082014-06-20 18:31:16 -07002835 if (recordThread->stop(this) && isExternalTrack()) {
Eric Laurentfee19762018-01-29 18:44:13 -08002836 AudioSystem::stopInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002837 }
2838 }
2839}
2840
Andy Hung3ff4b552023-06-26 19:20:57 -07002841void RecordTrack::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002842{
Andy Hung3ff4b552023-06-26 19:20:57 -07002843 // see comments at Track::destroy()
Eric Laurent81784c32012-11-19 14:55:58 -08002844 sp<RecordTrack> keep(this);
2845 {
Andy Hungce685402018-10-05 17:23:27 -07002846 track_state priorState = mState;
Andy Hung44f27182023-07-06 20:56:16 -07002847 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurent81784c32012-11-19 14:55:58 -08002848 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07002849 Mutex::Autolock _l(thread->mutex());
2850 auto* const recordThread = thread->asIAfRecordThread().get();
Andy Hungce685402018-10-05 17:23:27 -07002851 priorState = mState;
Eric Laurentec376dc2021-04-08 20:41:22 +02002852 if (!mSharedAudioPackageName.empty()) {
Eric Laurent92d0a322021-07-16 15:32:33 +02002853 recordThread->resetAudioHistory_l();
Eric Laurentec376dc2021-04-08 20:41:22 +02002854 }
Andy Hungce685402018-10-05 17:23:27 -07002855 recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
2856 }
2857 // APM portid/client management done outside of lock.
2858 // NOTE: if thread doesn't exist, the input descriptor probably doesn't either.
2859 if (isExternalTrack()) {
2860 switch (priorState) {
2861 case ACTIVE: // invalidated while still active
2862 case STARTING_2: // invalidated/start-aborted after startInput successfully called
2863 case PAUSING: // invalidated while in the middle of stop() pausing (still active)
2864 AudioSystem::stopInput(mPortId);
2865 break;
2866
2867 case STARTING_1: // invalidated/start-aborted and startInput not successful
2868 case PAUSED: // OK, not active
2869 case IDLE: // OK, not active
2870 break;
2871
2872 case STOPPED: // unexpected (destroyed)
2873 default:
2874 LOG_ALWAYS_FATAL("%s(%d): invalid prior state: %d", __func__, mId, priorState);
2875 }
2876 AudioSystem::releaseInput(mPortId);
Eric Laurent81784c32012-11-19 14:55:58 -08002877 }
2878 }
2879}
2880
Andy Hung3ff4b552023-06-26 19:20:57 -07002881void RecordTrack::invalidate()
Eric Laurent9a54bc22013-09-09 09:08:44 -07002882{
Eric Laurent6acd1d42017-01-04 14:23:29 -08002883 TrackBase::invalidate();
Eric Laurent9a54bc22013-09-09 09:08:44 -07002884 // FIXME should use proxy, and needs work
2885 audio_track_cblk_t* cblk = mCblk;
2886 android_atomic_or(CBLK_INVALID, &cblk->mFlags);
2887 android_atomic_release_store(0x40000000, &cblk->mFutex);
2888 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
Elliott Hughesee499292014-05-21 17:55:51 -07002889 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
Eric Laurent9a54bc22013-09-09 09:08:44 -07002890}
2891
Eric Laurent81784c32012-11-19 14:55:58 -08002892
Andy Hung3ff4b552023-06-26 19:20:57 -07002893void RecordTrack::appendDumpHeader(String8& result) const
Eric Laurent81784c32012-11-19 14:55:58 -08002894{
Eric Laurent973db022018-11-20 14:54:31 -08002895 result.appendFormat("Active Id Client Session Port Id S Flags "
Andy Hung9d84af52018-09-12 18:03:44 -07002896 " Format Chn mask SRate Source "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002897 " Server FrmCnt FrmRdy Sil%s\n",
2898 isServerLatencySupported() ? " Latency" : "");
Eric Laurent81784c32012-11-19 14:55:58 -08002899}
2900
Andy Hung3ff4b552023-06-26 19:20:57 -07002901void RecordTrack::appendDump(String8& result, bool active) const
Eric Laurent81784c32012-11-19 14:55:58 -08002902{
Eric Laurent973db022018-11-20 14:54:31 -08002903 result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002904 "%08X %08X %6u %6X "
Andy Hung000adb52018-06-01 15:43:26 -07002905 "%08X %6zu %6zu %3c",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002906 isFastTrack() ? 'F' : ' ',
Marco Nelissenb2208842014-02-07 14:00:50 -08002907 active ? "yes" : "no",
Andy Hung9d84af52018-09-12 18:03:44 -07002908 mId,
Andy Hung4ef19fa2018-05-15 19:35:29 -07002909 (mClient == 0) ? getpid() : mClient->pid(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002910 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08002911 mPortId,
Andy Hunge2e830f2019-12-03 12:54:46 -08002912 getTrackStateAsCodedString(),
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002913 mCblk->mFlags,
2914
Eric Laurent81784c32012-11-19 14:55:58 -08002915 mFormat,
2916 mChannelMask,
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002917 mSampleRate,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07002918 mAttr.source,
Glenn Kasten6dd62fb2013-12-05 16:35:58 -08002919
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002920 mCblk->mServer,
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002921 mFrameCount,
Andy Hung000adb52018-06-01 15:43:26 -07002922 mServerProxy->framesReadySafe(),
Jean-Michel Trivi7d665ab2018-04-11 17:26:51 -07002923 isSilenced() ? 's' : 'n'
Andy Hung2c6c3bb2017-06-16 14:01:45 -07002924 );
Andy Hung000adb52018-06-01 15:43:26 -07002925 if (isServerLatencySupported()) {
2926 double latencyMs;
2927 bool fromTrack;
2928 if (getTrackLatencyMs(&latencyMs, &fromTrack) == OK) {
2929 // Show latency in msec, followed by 't' if from track timestamp (the most accurate)
2930 // or 'k' if estimated from kernel (usually for debugging).
2931 result.appendFormat(" %7.2lf %c", latencyMs, fromTrack ? 't' : 'k');
2932 } else {
2933 result.appendFormat("%10s", mCblk->mServer != 0 ? "unavail" : "new");
2934 }
2935 }
2936 result.append("\n");
Eric Laurent81784c32012-11-19 14:55:58 -08002937}
2938
Andy Hung93bb5732023-05-04 21:16:34 -07002939// This is invoked by SyncEvent callback.
Andy Hung3ff4b552023-06-26 19:20:57 -07002940void RecordTrack::handleSyncStartEvent(
Andy Hung068e08e2023-05-15 19:02:55 -07002941 const sp<audioflinger::SyncEvent>& event)
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002942{
Andy Hung93bb5732023-05-04 21:16:34 -07002943 size_t framesToDrop = 0;
Andy Hung44f27182023-07-06 20:56:16 -07002944 const sp<IAfThreadBase> threadBase = mThread.promote();
Andy Hung93bb5732023-05-04 21:16:34 -07002945 if (threadBase != 0) {
2946 // TODO: use actual buffer filling status instead of 2 buffers when info is available
2947 // from audio HAL
Andy Hung44f27182023-07-06 20:56:16 -07002948 framesToDrop = threadBase->frameCount() * 2;
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002949 }
Andy Hung93bb5732023-05-04 21:16:34 -07002950
2951 mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002952}
2953
Andy Hung3ff4b552023-06-26 19:20:57 -07002954void RecordTrack::clearSyncStartEvent()
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002955{
Andy Hung93bb5732023-05-04 21:16:34 -07002956 mSynchronizedRecordState.clear();
Glenn Kasten25f4aa82014-02-07 10:50:43 -08002957}
2958
Andy Hung3ff4b552023-06-26 19:20:57 -07002959void RecordTrack::updateTrackFrameInfo(
Andy Hung3f0c9022016-01-15 17:49:46 -08002960 int64_t trackFramesReleased, int64_t sourceFramesRead,
2961 uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
2962{
Andy Hung30282562018-08-08 18:27:03 -07002963 // Make the kernel frametime available.
2964 const FrameTime ft{
2965 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
2966 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]};
2967 // ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
2968 mKernelFrameTime.store(ft);
2969 if (!audio_is_linear_pcm(mFormat)) {
Atneya Nair497fff12022-01-18 16:23:04 -05002970 // Stream is direct, return provided timestamp with no conversion
2971 mServerProxy->setTimestamp(timestamp);
Andy Hung30282562018-08-08 18:27:03 -07002972 return;
2973 }
2974
Andy Hung3f0c9022016-01-15 17:49:46 -08002975 ExtendedTimestamp local = timestamp;
2976
2977 // Convert HAL frames to server-side track frames at track sample rate.
2978 // We use trackFramesReleased and sourceFramesRead as an anchor point.
2979 for (int i = ExtendedTimestamp::LOCATION_SERVER; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
2980 if (local.mTimeNs[i] != 0) {
2981 const int64_t relativeServerFrames = local.mPosition[i] - sourceFramesRead;
2982 const int64_t relativeTrackFrames = relativeServerFrames
2983 * mSampleRate / halSampleRate; // TODO: potential computation overflow
2984 local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
2985 }
2986 }
Andy Hung6ae58432016-02-16 18:32:24 -08002987 mServerProxy->setTimestamp(local);
Andy Hung000adb52018-06-01 15:43:26 -07002988
2989 // Compute latency info.
2990 const bool useTrackTimestamp = true; // use track unless debugging.
2991 const double latencyMs = - (useTrackTimestamp
2992 ? local.getOutputServerLatencyMs(sampleRate())
2993 : timestamp.getOutputServerLatencyMs(halSampleRate));
2994
2995 mServerLatencyFromTrack.store(useTrackTimestamp);
2996 mServerLatencyMs.store(latencyMs);
Andy Hung3f0c9022016-01-15 17:49:46 -08002997}
Eric Laurent83b88082014-06-20 18:31:16 -07002998
Andy Hung3ff4b552023-06-26 19:20:57 -07002999status_t RecordTrack::getActiveMicrophones(
Andy Hung02a6c4e2023-06-23 19:27:19 -07003000 std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
jiabin653cc0a2018-01-17 17:54:10 -08003001{
Andy Hung44f27182023-07-06 20:56:16 -07003002 const sp<IAfThreadBase> thread = mThread.promote();
jiabin653cc0a2018-01-17 17:54:10 -08003003 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003004 auto* const recordThread = thread->asIAfRecordThread().get();
jiabin653cc0a2018-01-17 17:54:10 -08003005 return recordThread->getActiveMicrophones(activeMicrophones);
3006 } else {
3007 return BAD_VALUE;
3008 }
3009}
3010
Andy Hung3ff4b552023-06-26 19:20:57 -07003011status_t RecordTrack::setPreferredMicrophoneDirection(
Paul McLean03a6e6a2018-12-04 10:54:13 -07003012 audio_microphone_direction_t direction) {
Andy Hung44f27182023-07-06 20:56:16 -07003013 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003014 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003015 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003016 return recordThread->setPreferredMicrophoneDirection(direction);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003017 } else {
3018 return BAD_VALUE;
3019 }
3020}
3021
Andy Hung3ff4b552023-06-26 19:20:57 -07003022status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
Andy Hung44f27182023-07-06 20:56:16 -07003023 const sp<IAfThreadBase> thread = mThread.promote();
Paul McLean03a6e6a2018-12-04 10:54:13 -07003024 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003025 auto* const recordThread = thread->asIAfRecordThread().get();
Paul McLean12340082019-03-19 09:35:05 -06003026 return recordThread->setPreferredMicrophoneFieldDimension(zoom);
Paul McLean03a6e6a2018-12-04 10:54:13 -07003027 } else {
3028 return BAD_VALUE;
3029 }
3030}
3031
Andy Hung3ff4b552023-06-26 19:20:57 -07003032status_t RecordTrack::shareAudioHistory(
Eric Laurentec376dc2021-04-08 20:41:22 +02003033 const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
3034
3035 const uid_t callingUid = IPCThreadState::self()->getCallingUid();
3036 const pid_t callingPid = IPCThreadState::self()->getCallingPid();
3037 if (callingUid != mUid || callingPid != mCreatorPid) {
3038 return PERMISSION_DENIED;
3039 }
3040
Svet Ganov33761132021-05-13 22:51:08 +00003041 AttributionSourceState attributionSource{};
3042 attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
3043 attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
3044 attributionSource.token = sp<BBinder>::make();
3045 if (!captureHotwordAllowed(attributionSource)) {
Eric Laurentec376dc2021-04-08 20:41:22 +02003046 return PERMISSION_DENIED;
3047 }
3048
Andy Hung44f27182023-07-06 20:56:16 -07003049 const sp<IAfThreadBase> thread = mThread.promote();
Eric Laurentec376dc2021-04-08 20:41:22 +02003050 if (thread != 0) {
Andy Hung44f27182023-07-06 20:56:16 -07003051 auto* const recordThread = thread->asIAfRecordThread().get();
Eric Laurentec376dc2021-04-08 20:41:22 +02003052 status_t status = recordThread->shareAudioHistory(
3053 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
3054 if (status == NO_ERROR) {
3055 mSharedAudioPackageName = sharedAudioPackageName;
3056 }
3057 return status;
3058 } else {
3059 return BAD_VALUE;
3060 }
3061}
3062
Andy Hung3ff4b552023-06-26 19:20:57 -07003063void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
Eric Laurent78b07302022-10-07 16:20:34 +02003064{
3065
3066 // Do not forward PatchRecord metadata with unspecified audio source
3067 if (mAttr.source == AUDIO_SOURCE_DEFAULT) {
3068 return;
3069 }
3070
3071 // No track is invalid as this is called after prepareTrack_l in the same critical section
3072 record_track_metadata_v7_t metadata;
3073 metadata.base = {
3074 .source = mAttr.source,
3075 .gain = 1, // capture tracks do not have volumes
3076 };
3077 metadata.channel_mask = mChannelMask;
3078 strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
3079
3080 *backInserter++ = metadata;
3081}
Eric Laurentec376dc2021-04-08 20:41:22 +02003082
Andy Hung9d84af52018-09-12 18:03:44 -07003083// ----------------------------------------------------------------------------
3084#undef LOG_TAG
3085#define LOG_TAG "AF::PatchRecord"
3086
Andy Hung3ff4b552023-06-26 19:20:57 -07003087/* static */
3088sp<IAfPatchRecord> IAfPatchRecord::create(
Andy Hung44f27182023-07-06 20:56:16 -07003089 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003090 uint32_t sampleRate,
3091 audio_channel_mask_t channelMask,
3092 audio_format_t format,
3093 size_t frameCount,
3094 void *buffer,
3095 size_t bufferSize,
3096 audio_input_flags_t flags,
3097 const Timeout& timeout,
3098 audio_source_t source)
3099{
3100 return sp<PatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003101 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003102 sampleRate,
3103 channelMask,
3104 format,
3105 frameCount,
3106 buffer,
3107 bufferSize,
3108 flags,
3109 timeout,
3110 source);
3111}
3112
Andy Hung44f27182023-07-06 20:56:16 -07003113PatchRecord::PatchRecord(IAfRecordThread* recordThread,
Eric Laurent83b88082014-06-20 18:31:16 -07003114 uint32_t sampleRate,
3115 audio_channel_mask_t channelMask,
3116 audio_format_t format,
3117 size_t frameCount,
3118 void *buffer,
Andy Hung8fe68032017-06-05 16:17:51 -07003119 size_t bufferSize,
Kevin Rocard45986c72018-12-18 18:22:59 -08003120 audio_input_flags_t flags,
Eric Laurent78b07302022-10-07 16:20:34 +02003121 const Timeout& timeout,
3122 audio_source_t source)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003123 : RecordTrack(recordThread, NULL,
Eric Laurent78b07302022-10-07 16:20:34 +02003124 audio_attributes_t{ .source = source } ,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003125 sampleRate, format, channelMask, frameCount,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003126 buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
Svet Ganov33761132021-05-13 22:51:08 +00003127 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
gaoxiupei8e3a5682023-07-07 20:30:23 +08003128 PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
3129 : nullptr,
Kevin Rocard45986c72018-12-18 18:22:59 -08003130 *recordThread, timeout)
Eric Laurent83b88082014-06-20 18:31:16 -07003131{
Andy Hung9d84af52018-09-12 18:03:44 -07003132 ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
3133 __func__, mId, sampleRate,
Eric Laurent83b88082014-06-20 18:31:16 -07003134 (int)mPeerTimeout.tv_sec,
3135 (int)(mPeerTimeout.tv_nsec / 1000000));
3136}
3137
Andy Hung3ff4b552023-06-26 19:20:57 -07003138PatchRecord::~PatchRecord()
Eric Laurent83b88082014-06-20 18:31:16 -07003139{
Andy Hungabfab202019-03-07 19:45:54 -08003140 ALOGV("%s(%d)", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003141}
3142
Mikhail Naganov8296c252019-09-25 14:59:54 -07003143static size_t writeFramesHelper(
3144 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3145{
3146 AudioBufferProvider::Buffer patchBuffer;
3147 patchBuffer.frameCount = frameCount;
3148 auto status = dest->getNextBuffer(&patchBuffer);
3149 if (status != NO_ERROR) {
3150 ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
3151 __func__, status, strerror(-status));
3152 return 0;
3153 }
3154 ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
3155 memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
3156 size_t framesWritten = patchBuffer.frameCount;
3157 dest->releaseBuffer(&patchBuffer);
3158 return framesWritten;
3159}
3160
3161// static
Andy Hung3ff4b552023-06-26 19:20:57 -07003162size_t PatchRecord::writeFrames(
Mikhail Naganov8296c252019-09-25 14:59:54 -07003163 AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
3164{
3165 size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
3166 // On buffer wrap, the buffer frame count will be less than requested,
3167 // when this happens a second buffer needs to be used to write the leftover audio
3168 const size_t framesLeft = frameCount - framesWritten;
3169 if (framesWritten != 0 && framesLeft != 0) {
3170 framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
3171 framesLeft, frameSize);
3172 }
3173 return framesWritten;
3174}
3175
Eric Laurent83b88082014-06-20 18:31:16 -07003176// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003177status_t PatchRecord::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -08003178 AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003179{
Andy Hung9d84af52018-09-12 18:03:44 -07003180 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003181 Proxy::Buffer buf;
3182 buf.mFrameCount = buffer->frameCount;
3183 status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
3184 ALOGV_IF(status != NO_ERROR,
Andy Hung9d84af52018-09-12 18:03:44 -07003185 "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
Eric Laurentc2730ba2014-07-20 15:47:07 -07003186 buffer->frameCount = buf.mFrameCount;
Mikhail Naganov938be412019-09-04 11:38:47 -07003187 if (ATRACE_ENABLED()) {
3188 std::string traceName("PRnObt");
3189 traceName += std::to_string(id());
3190 ATRACE_INT(traceName.c_str(), buf.mFrameCount);
3191 }
Eric Laurent83b88082014-06-20 18:31:16 -07003192 if (buf.mFrameCount == 0) {
3193 return WOULD_BLOCK;
3194 }
Glenn Kastend79072e2016-01-06 08:41:20 -08003195 status = RecordTrack::getNextBuffer(buffer);
Eric Laurent83b88082014-06-20 18:31:16 -07003196 return status;
3197}
3198
Andy Hung3ff4b552023-06-26 19:20:57 -07003199void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003200{
Andy Hung9d84af52018-09-12 18:03:44 -07003201 ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Eric Laurent83b88082014-06-20 18:31:16 -07003202 Proxy::Buffer buf;
3203 buf.mFrameCount = buffer->frameCount;
3204 buf.mRaw = buffer->raw;
3205 mPeerProxy->releaseBuffer(&buf);
3206 TrackBase::releaseBuffer(buffer);
3207}
3208
Andy Hung3ff4b552023-06-26 19:20:57 -07003209status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
Eric Laurent83b88082014-06-20 18:31:16 -07003210 const struct timespec *timeOut)
3211{
3212 return mProxy->obtainBuffer(buffer, timeOut);
3213}
3214
Andy Hung3ff4b552023-06-26 19:20:57 -07003215void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Eric Laurent83b88082014-06-20 18:31:16 -07003216{
3217 mProxy->releaseBuffer(buffer);
3218}
3219
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003220#undef LOG_TAG
3221#define LOG_TAG "AF::PthrPatchRecord"
3222
3223static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
3224{
3225 void *ptr = nullptr;
3226 (void)posix_memalign(&ptr, alignment, size);
Andy Hung71ba4b32022-10-06 12:09:49 -07003227 return {ptr, free};
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003228}
3229
Andy Hung3ff4b552023-06-26 19:20:57 -07003230/* static */
3231sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
Andy Hung44f27182023-07-06 20:56:16 -07003232 IAfRecordThread* recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003233 uint32_t sampleRate,
3234 audio_channel_mask_t channelMask,
3235 audio_format_t format,
3236 size_t frameCount,
3237 audio_input_flags_t flags,
3238 audio_source_t source)
3239{
3240 return sp<PassthruPatchRecord>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003241 recordThread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003242 sampleRate,
3243 channelMask,
3244 format,
3245 frameCount,
3246 flags,
3247 source);
3248}
3249
3250PassthruPatchRecord::PassthruPatchRecord(
Andy Hung44f27182023-07-06 20:56:16 -07003251 IAfRecordThread* recordThread,
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003252 uint32_t sampleRate,
3253 audio_channel_mask_t channelMask,
3254 audio_format_t format,
3255 size_t frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003256 audio_input_flags_t flags,
3257 audio_source_t source)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003258 : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
Eric Laurent78b07302022-10-07 16:20:34 +02003259 nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source),
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003260 mPatchRecordAudioBufferProvider(*this),
3261 mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
3262 mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
3263{
3264 memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
3265}
3266
Andy Hung3ff4b552023-06-26 19:20:57 -07003267sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
Andy Hung44f27182023-07-06 20:56:16 -07003268 sp<IAfThreadBase>* thread)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003269{
3270 *thread = mThread.promote();
3271 if (!*thread) return nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003272 auto* const recordThread = (*thread)->asIAfRecordThread().get();
3273 Mutex::Autolock _l(recordThread->mutex());
3274 return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003275}
3276
3277// PatchProxyBufferProvider methods are called on DirectOutputThread
Andy Hung3ff4b552023-06-26 19:20:57 -07003278status_t PassthruPatchRecord::obtainBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003279 Proxy::Buffer* buffer, const struct timespec* timeOut)
3280{
3281 if (mUnconsumedFrames) {
3282 buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
3283 // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
3284 return PatchRecord::obtainBuffer(buffer, timeOut);
3285 }
3286
3287 // Otherwise, execute a read from HAL and write into the buffer.
3288 nsecs_t startTimeNs = 0;
3289 if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
3290 // Will need to correct timeOut by elapsed time.
3291 startTimeNs = systemTime();
3292 }
3293 const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
3294 buffer->mFrameCount = 0;
3295 buffer->mRaw = nullptr;
Andy Hung44f27182023-07-06 20:56:16 -07003296 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003297 sp<StreamInHalInterface> stream = obtainStream(&thread);
3298 if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
3299
3300 status_t result = NO_ERROR;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003301 size_t bytesRead = 0;
3302 {
3303 ATRACE_NAME("read");
3304 result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
3305 if (result != NO_ERROR) goto stream_error;
3306 if (bytesRead == 0) return NO_ERROR;
3307 }
3308
3309 {
3310 std::lock_guard<std::mutex> lock(mReadLock);
3311 mReadBytes += bytesRead;
3312 mReadError = NO_ERROR;
3313 }
3314 mReadCV.notify_one();
3315 // writeFrames handles wraparound and should write all the provided frames.
3316 // If it couldn't, there is something wrong with the client/server buffer of the software patch.
3317 buffer->mFrameCount = writeFrames(
3318 &mPatchRecordAudioBufferProvider,
3319 mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
3320 ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
3321 "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
3322 mUnconsumedFrames = buffer->mFrameCount;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003323 struct timespec newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003324 if (startTimeNs) {
Mikhail Naganov4de49972019-10-07 09:53:58 -07003325 // Correct the timeout by elapsed time.
3326 nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003327 if (newTimeOutNs < 0) newTimeOutNs = 0;
3328 newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
3329 newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
Mikhail Naganov4de49972019-10-07 09:53:58 -07003330 timeOut = &newTimeOut;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003331 }
Mikhail Naganov4de49972019-10-07 09:53:58 -07003332 return PatchRecord::obtainBuffer(buffer, timeOut);
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003333
3334stream_error:
3335 stream->standby();
3336 {
3337 std::lock_guard<std::mutex> lock(mReadLock);
3338 mReadError = result;
3339 }
3340 mReadCV.notify_one();
3341 return result;
3342}
3343
Andy Hung3ff4b552023-06-26 19:20:57 -07003344void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003345{
3346 if (buffer->mFrameCount <= mUnconsumedFrames) {
3347 mUnconsumedFrames -= buffer->mFrameCount;
3348 } else {
3349 ALOGW("Write side has consumed more frames than we had: %zu > %zu",
3350 buffer->mFrameCount, mUnconsumedFrames);
3351 mUnconsumedFrames = 0;
3352 }
3353 PatchRecord::releaseBuffer(buffer);
3354}
3355
3356// AudioBufferProvider and Source methods are called on RecordThread
3357// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
3358// and 'releaseBuffer' are stubbed out and ignore their input.
3359// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
3360// until we copy it.
Andy Hung3ff4b552023-06-26 19:20:57 -07003361status_t PassthruPatchRecord::read(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003362 void* buffer, size_t bytes, size_t* read)
3363{
3364 bytes = std::min(bytes, mFrameCount * mFrameSize);
3365 {
3366 std::unique_lock<std::mutex> lock(mReadLock);
3367 mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
3368 if (mReadError != NO_ERROR) {
3369 mLastReadFrames = 0;
3370 return mReadError;
3371 }
3372 *read = std::min(bytes, mReadBytes);
3373 mReadBytes -= *read;
3374 }
3375 mLastReadFrames = *read / mFrameSize;
3376 memset(buffer, 0, *read);
3377 return 0;
3378}
3379
Andy Hung3ff4b552023-06-26 19:20:57 -07003380status_t PassthruPatchRecord::getCapturePosition(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003381 int64_t* frames, int64_t* time)
3382{
Andy Hung44f27182023-07-06 20:56:16 -07003383 sp<IAfThreadBase> thread;
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003384 sp<StreamInHalInterface> stream = obtainStream(&thread);
3385 return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
3386}
3387
Andy Hung3ff4b552023-06-26 19:20:57 -07003388status_t PassthruPatchRecord::standby()
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003389{
3390 // RecordThread issues 'standby' command in two major cases:
3391 // 1. Error on read--this case is handled in 'obtainBuffer'.
3392 // 2. Track is stopping--as PassthruPatchRecord assumes continuous
3393 // output, this can only happen when the software patch
3394 // is being torn down. In this case, the RecordThread
3395 // will terminate and close the HAL stream.
3396 return 0;
3397}
3398
3399// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
Andy Hung3ff4b552023-06-26 19:20:57 -07003400status_t PassthruPatchRecord::getNextBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003401 AudioBufferProvider::Buffer* buffer)
3402{
3403 buffer->frameCount = mLastReadFrames;
3404 buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
3405 return NO_ERROR;
3406}
3407
Andy Hung3ff4b552023-06-26 19:20:57 -07003408void PassthruPatchRecord::releaseBuffer(
Mikhail Naganovcaf59942019-09-25 14:05:29 -07003409 AudioBufferProvider::Buffer* buffer)
3410{
3411 buffer->frameCount = 0;
3412 buffer->raw = nullptr;
3413}
3414
Andy Hung9d84af52018-09-12 18:03:44 -07003415// ----------------------------------------------------------------------------
3416#undef LOG_TAG
3417#define LOG_TAG "AF::MmapTrack"
Eric Laurent6acd1d42017-01-04 14:23:29 -08003418
Andy Hung3ff4b552023-06-26 19:20:57 -07003419/* static */
Andy Hung44f27182023-07-06 20:56:16 -07003420sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003421 const audio_attributes_t& attr,
3422 uint32_t sampleRate,
3423 audio_format_t format,
3424 audio_channel_mask_t channelMask,
3425 audio_session_t sessionId,
3426 bool isOut,
3427 const android::content::AttributionSourceState& attributionSource,
3428 pid_t creatorPid,
3429 audio_port_handle_t portId)
3430{
3431 return sp<MmapTrack>::make(
Andy Hung44f27182023-07-06 20:56:16 -07003432 thread,
Andy Hung3ff4b552023-06-26 19:20:57 -07003433 attr,
3434 sampleRate,
3435 format,
3436 channelMask,
3437 sessionId,
3438 isOut,
3439 attributionSource,
3440 creatorPid,
3441 portId);
3442}
3443
Andy Hung44f27182023-07-06 20:56:16 -07003444MmapTrack::MmapTrack(IAfThreadBase* thread,
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003445 const audio_attributes_t& attr,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003446 uint32_t sampleRate,
3447 audio_format_t format,
3448 audio_channel_mask_t channelMask,
3449 audio_session_t sessionId,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003450 bool isOut,
Svet Ganov33761132021-05-13 22:51:08 +00003451 const AttributionSourceState& attributionSource,
Eric Laurent09f1ed22019-04-24 17:45:17 -07003452 pid_t creatorPid,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003453 audio_port_handle_t portId)
Kevin Rocard1f564ac2018-03-29 13:53:10 -07003454 : TrackBase(thread, NULL, attr, sampleRate, format,
Andy Hung8fe68032017-06-05 16:17:51 -07003455 channelMask, (size_t)0 /* frameCount */,
3456 nullptr /* buffer */, (size_t)0 /* bufferSize */,
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003457 sessionId, creatorPid,
Svet Ganov33761132021-05-13 22:51:08 +00003458 VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003459 isOut,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003460 ALLOC_NONE,
Andy Hungc2b11cb2020-04-22 09:04:01 -07003461 TYPE_DEFAULT, portId,
3462 std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
Svet Ganov33761132021-05-13 22:51:08 +00003463 mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
Philip P. Moltmannbda45752020-07-17 16:41:18 -07003464 mSilenced(false), mSilencedNotified(false)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003465{
Andy Hungc2b11cb2020-04-22 09:04:01 -07003466 // Once this item is logged by the server, the client can add properties.
Andy Hung94235282021-03-24 15:50:14 -07003467 mTrackMetrics.logConstructor(creatorPid, uid(), id());
Eric Laurent6acd1d42017-01-04 14:23:29 -08003468}
3469
Andy Hung3ff4b552023-06-26 19:20:57 -07003470MmapTrack::~MmapTrack()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003471{
3472}
3473
Andy Hung3ff4b552023-06-26 19:20:57 -07003474status_t MmapTrack::initCheck() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003475{
3476 return NO_ERROR;
3477}
3478
Andy Hung3ff4b552023-06-26 19:20:57 -07003479status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003480 audio_session_t triggerSession __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003481{
3482 return NO_ERROR;
3483}
3484
Andy Hung3ff4b552023-06-26 19:20:57 -07003485void MmapTrack::stop()
Eric Laurent6acd1d42017-01-04 14:23:29 -08003486{
3487}
3488
3489// AudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003490status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003491{
3492 buffer->frameCount = 0;
3493 buffer->raw = nullptr;
3494 return INVALID_OPERATION;
3495}
3496
3497// ExtendedAudioBufferProvider interface
Andy Hung3ff4b552023-06-26 19:20:57 -07003498size_t MmapTrack::framesReady() const {
Eric Laurent6acd1d42017-01-04 14:23:29 -08003499 return 0;
3500}
3501
Andy Hung3ff4b552023-06-26 19:20:57 -07003502int64_t MmapTrack::framesReleased() const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003503{
3504 return 0;
3505}
3506
Andy Hung3ff4b552023-06-26 19:20:57 -07003507void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
Eric Laurent6acd1d42017-01-04 14:23:29 -08003508{
3509}
3510
Andy Hung3ff4b552023-06-26 19:20:57 -07003511void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
Vlad Popaec1788e2022-08-04 11:23:30 +02003512{
3513 if (mMuteState == muteState) {
3514 // mute state did not change, do nothing
3515 return;
3516 }
3517
3518 status_t result = UNKNOWN_ERROR;
3519 if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
3520 if (mMuteEventExtras == nullptr) {
3521 mMuteEventExtras = std::make_unique<os::PersistableBundle>();
3522 }
3523 mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
3524 static_cast<int>(muteState));
3525
3526 result = audioManager->portEvent(mPortId,
3527 PLAYER_UPDATE_MUTED,
3528 mMuteEventExtras);
3529 }
3530
3531 if (result == OK) {
3532 mMuteState = muteState;
3533 } else {
3534 ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
3535 __func__,
3536 id(),
3537 mPortId,
3538 result);
3539 }
3540}
3541
Andy Hung3ff4b552023-06-26 19:20:57 -07003542void MmapTrack::appendDumpHeader(String8& result) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003543{
Eric Laurent973db022018-11-20 14:54:31 -08003544 result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003545 isOut() ? "Usg CT": "Source");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003546}
3547
Andy Hung3ff4b552023-06-26 19:20:57 -07003548void MmapTrack::appendDump(String8& result, bool active __unused) const
Eric Laurent6acd1d42017-01-04 14:23:29 -08003549{
Eric Laurent973db022018-11-20 14:54:31 -08003550 result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
Andy Hung2c6c3bb2017-06-16 14:01:45 -07003551 mPid,
3552 mSessionId,
Eric Laurent973db022018-11-20 14:54:31 -08003553 mPortId,
Eric Laurent6acd1d42017-01-04 14:23:29 -08003554 mFormat,
3555 mChannelMask,
Kevin Rocard5f2136e2018-05-11 22:03:00 -07003556 mSampleRate,
3557 mAttr.flags);
3558 if (isOut()) {
3559 result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
3560 } else {
3561 result.appendFormat("%6x", mAttr.source);
3562 }
3563 result.append("\n");
Eric Laurent6acd1d42017-01-04 14:23:29 -08003564}
3565
Glenn Kasten63238ef2015-03-02 15:50:29 -08003566} // namespace android