blob: 1c6a01449d02e76766e1ea5fc2fa85c31771a30e [file] [log] [blame]
Mikhail Naganov31d46652023-01-10 18:29:25 +00001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "StreamHalAidl"
18//#define LOG_NDEBUG 0
19
20#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
21#include <mediautils/TimeCheck.h>
22#include <utils/Log.h>
23
24#include "DeviceHalAidl.h"
25#include "StreamHalAidl.h"
26
27using ::aidl::android::hardware::audio::core::IStreamCommon;
28using ::aidl::android::hardware::audio::core::IStreamIn;
29using ::aidl::android::hardware::audio::core::IStreamOut;
30using ::aidl::android::hardware::audio::core::StreamDescriptor;
31
32namespace android {
33
Mikhail Naganovfab697c2023-01-11 19:33:13 +000034// static
35template<class T>
36std::shared_ptr<IStreamCommon> StreamHalAidl::getStreamCommon(const std::shared_ptr<T>& stream) {
37 std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> streamCommon;
38 if (stream != nullptr) {
39 if (ndk::ScopedAStatus status = stream->getStreamCommon(&streamCommon);
40 !status.isOk()) {
41 ALOGE("%s: failed to retrieve IStreamCommon instance: %s", __func__,
42 status.getDescription().c_str());
43 }
44 }
45 return streamCommon;
46}
47
Mikhail Naganov31d46652023-01-10 18:29:25 +000048StreamHalAidl::StreamHalAidl(
49 std::string_view className, bool isInput, const StreamDescriptor& descriptor,
50 const std::shared_ptr<IStreamCommon>& stream)
51 : ConversionHelperAidl(className),
52 mIsInput(isInput),
53 mFrameSizeBytes(descriptor.frameSizeBytes),
54 mBufferSizeFrames(descriptor.bufferSizeFrames),
55 mCommandMQ(new CommandMQ(descriptor.command)),
56 mReplyMQ(new ReplyMQ(descriptor.reply)),
57 mDataMQ(maybeCreateDataMQ(descriptor)),
58 mStream(stream) {
59 // Instrument audio signal power logging.
60 // Note: This assumes channel mask, format, and sample rate do not change after creation.
61 if (audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
62 /* mStreamPowerLog.isUserDebugOrEngBuild() && */
63 StreamHalAidl::getAudioProperties(&config) == NO_ERROR) {
64 mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
65 }
66}
67
68StreamHalAidl::~StreamHalAidl() {
69 if (mStream != nullptr) {
70 ndk::ScopedAStatus status = mStream->close();
71 ALOGE_IF(!status.isOk(), "%s: status %s", __func__, status.getDescription().c_str());
72 }
73}
74
75status_t StreamHalAidl::getBufferSize(size_t *size) {
76 if (size == nullptr) {
77 return BAD_VALUE;
78 }
79 if (mFrameSizeBytes == 0 || mBufferSizeFrames == 0) {
80 return NO_INIT;
81 }
82 *size = mFrameSizeBytes * mBufferSizeFrames;
83 return OK;
84}
85
86status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
87 if (configBase == nullptr) {
88 return BAD_VALUE;
89 }
90 TIME_CHECK();
91 *configBase = AUDIO_CONFIG_BASE_INITIALIZER;
92 configBase->sample_rate = 48000;
93 configBase->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
94 configBase->channel_mask = mIsInput ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_OUT_STEREO;
95 // if (!mStream) return NO_INIT;
96 ALOGE("%s not implemented yet", __func__);
97 return OK;
98}
99
100status_t StreamHalAidl::setParameters(const String8& kvPairs __unused) {
101 TIME_CHECK();
102 if (!mStream) return NO_INIT;
103 ALOGE("%s not implemented yet", __func__);
104 return OK;
105}
106
107status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
108 TIME_CHECK();
109 values->clear();
110 if (!mStream) return NO_INIT;
111 ALOGE("%s not implemented yet", __func__);
112 return OK;
113}
114
115status_t StreamHalAidl::getFrameSize(size_t *size) {
116 if (size == nullptr) {
117 return BAD_VALUE;
118 }
119 if (mFrameSizeBytes == 0) {
120 return NO_INIT;
121 }
122 *size = mFrameSizeBytes;
123 return OK;
124}
125
126status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
127 TIME_CHECK();
128 if (!mStream) return NO_INIT;
129 ALOGE("%s not implemented yet", __func__);
130 return OK;
131}
132
133status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
134 TIME_CHECK();
135 if (!mStream) return NO_INIT;
136 ALOGE("%s not implemented yet", __func__);
137 return OK;
138}
139
140status_t StreamHalAidl::standby() {
141 TIME_CHECK();
142 if (!mStream) return NO_INIT;
143 ALOGE("%s not implemented yet", __func__);
144 return OK;
145}
146
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000147status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000148 TIME_CHECK();
149 if (!mStream) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000150 return mStream->dump(fd, Args(args).args(), args.size());
Mikhail Naganov31d46652023-01-10 18:29:25 +0000151}
152
153status_t StreamHalAidl::start() {
154 TIME_CHECK();
155 if (!mStream) return NO_INIT;
156 ALOGE("%s not implemented yet", __func__);
157 return OK;
158}
159
160status_t StreamHalAidl::stop() {
161 TIME_CHECK();
162 if (!mStream) return NO_INIT;
163 ALOGE("%s not implemented yet", __func__);
164 return OK;
165}
166
167status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
168 struct audio_mmap_buffer_info *info __unused) {
169 TIME_CHECK();
170 if (!mStream) return NO_INIT;
171 ALOGE("%s not implemented yet", __func__);
172 return OK;
173}
174
175status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
176 TIME_CHECK();
177 if (!mStream) return NO_INIT;
178 ALOGE("%s not implemented yet", __func__);
179 return OK;
180}
181
182status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
183 mHalThreadPriority = priority;
184 return OK;
185}
186
187status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
188 TIME_CHECK();
189 if (!mStream) return NO_INIT;
190 ALOGE("%s not implemented yet", __func__);
191 return OK;
192}
193
194bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
195 if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
196 return true;
197 }
198 if (!mStream) return NO_INIT;
199 ALOGE("%s not implemented yet", __func__);
200 return OK;
201}
202
203status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
204 std::optional<audio_source_t> source __unused,
205 audio_devices_t type __unused) {
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000206 // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
207 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000208}
209
210status_t StreamHalAidl::legacyReleaseAudioPatch() {
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000211 // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
212 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000213}
214
215namespace {
216
217/* Notes on callback ownership.
218
219This is how Binder ownership model looks like. The server implementation
220is owned by Binder framework (via sp<>). Proxies are owned by clients.
221When the last proxy disappears, Binder framework releases the server impl.
222
223Thus, it is not needed to keep any references to StreamCallback (this is
224the server impl) -- it will live as long as HAL server holds a strong ref to
225IStreamCallback proxy.
226
227The callback only keeps a weak reference to the stream. The stream is owned
228by AudioFlinger.
229
230*/
231
232class StreamCallback : public ::aidl::android::hardware::audio::core::BnStreamCallback {
233 ndk::ScopedAStatus onTransferReady() override {
234 return ndk::ScopedAStatus::ok();
235 }
236 ndk::ScopedAStatus onError() override {
237 return ndk::ScopedAStatus::ok();
238 }
239 ndk::ScopedAStatus onDrainReady() override {
240 return ndk::ScopedAStatus::ok();
241 }
242};
243
244} // namespace
245
246StreamOutHalAidl::StreamOutHalAidl(
247 const StreamDescriptor& descriptor, const std::shared_ptr<IStreamOut>& stream)
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000248 : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, descriptor, getStreamCommon(stream)),
Mikhail Naganov31d46652023-01-10 18:29:25 +0000249 mStream(stream) {}
250
251status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
252 TIME_CHECK();
253 *latency = 0;
254 if (!mStream) return NO_INIT;
255 ALOGE("%s not implemented yet", __func__);
256 return OK;
257}
258
259status_t StreamOutHalAidl::setVolume(float left __unused, float right __unused) {
260 TIME_CHECK();
261 if (!mStream) return NO_INIT;
262 ALOGE("%s not implemented yet", __func__);
263 return OK;
264}
265
266status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
267 TIME_CHECK();
268 if (!mStream) return NO_INIT;
269 ALOGE("%s not implemented yet", __func__);
270 return OK;
271}
272
273status_t StreamOutHalAidl::write(
274 const void *buffer __unused, size_t bytes __unused, size_t *written __unused) {
275 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
276 if (!mStream) return NO_INIT;
277 *written = 0;
278 ALOGE("%s not implemented yet", __func__);
279 return OK;
280}
281
282status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames __unused) {
283 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
284 if (!mStream) return NO_INIT;
285 ALOGE("%s not implemented yet", __func__);
286 return OK;
287}
288
289status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
290 TIME_CHECK();
291 if (!mStream) return NO_INIT;
292 ALOGE("%s not implemented yet", __func__);
293 return OK;
294}
295
296status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback __unused) {
297 TIME_CHECK();
298 if (!mStream) return NO_INIT;
299 ALOGE("%s not implemented yet", __func__);
300 return OK;
301}
302
303status_t StreamOutHalAidl::supportsPauseAndResume(
304 bool *supportsPause __unused, bool *supportsResume __unused) {
305 TIME_CHECK();
306 if (!mStream) return NO_INIT;
307 ALOGE("%s not implemented yet", __func__);
308 return OK;
309}
310
311status_t StreamOutHalAidl::pause() {
312 TIME_CHECK();
313 if (!mStream) return NO_INIT;
314 ALOGE("%s not implemented yet", __func__);
315 return OK;
316}
317
318status_t StreamOutHalAidl::resume() {
319 TIME_CHECK();
320 if (!mStream) return NO_INIT;
321 ALOGE("%s not implemented yet", __func__);
322 return OK;
323}
324
325status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain __unused) {
326 TIME_CHECK();
327 if (!mStream) return NO_INIT;
328 ALOGE("%s not implemented yet", __func__);
329 return OK;
330}
331
332status_t StreamOutHalAidl::drain(bool earlyNotify __unused) {
333 TIME_CHECK();
334 if (!mStream) return NO_INIT;
335 ALOGE("%s not implemented yet", __func__);
336 return OK;
337}
338
339status_t StreamOutHalAidl::flush() {
340 TIME_CHECK();
341 if (!mStream) return NO_INIT;
342 ALOGE("%s not implemented yet", __func__);
343 return OK;
344}
345
346status_t StreamOutHalAidl::getPresentationPosition(
347 uint64_t *frames __unused, struct timespec *timestamp __unused) {
348 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
349 if (!mStream) return NO_INIT;
350 ALOGE("%s not implemented yet", __func__);
351 return OK;
352}
353
354status_t StreamOutHalAidl::updateSourceMetadata(
355 const StreamOutHalInterface::SourceMetadata& sourceMetadata __unused) {
356 TIME_CHECK();
357 if (!mStream) return NO_INIT;
358 ALOGE("%s not implemented yet", __func__);
359 return OK;
360}
361
362status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
363 return INVALID_OPERATION;
364}
365
366status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
367 return INVALID_OPERATION;
368}
369
370status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
371 return INVALID_OPERATION;
372}
373
374status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
375 return INVALID_OPERATION;
376}
377
378status_t StreamOutHalAidl::getPlaybackRateParameters(
379 audio_playback_rate_t* playbackRate __unused) {
380 return INVALID_OPERATION;
381}
382
383status_t StreamOutHalAidl::setPlaybackRateParameters(
384 const audio_playback_rate_t& playbackRate __unused) {
385 return INVALID_OPERATION;
386}
387
388status_t StreamOutHalAidl::setEventCallback(
389 const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
390 return INVALID_OPERATION;
391}
392
393namespace {
394
395struct StreamOutEventCallback {
396 StreamOutEventCallback(const wp<StreamOutHalAidl>& stream) : mStream(stream) {}
397 private:
398 wp<StreamOutHalAidl> mStream;
399};
400
401} // namespace
402
403status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
404 return INVALID_OPERATION;
405};
406
407status_t StreamOutHalAidl::getRecommendedLatencyModes(
408 std::vector<audio_latency_mode_t> *modes __unused) {
409 return INVALID_OPERATION;
410};
411
412status_t StreamOutHalAidl::setLatencyModeCallback(
413 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
414 return INVALID_OPERATION;
415};
416
417void StreamOutHalAidl::onWriteReady() {
418 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
419 if (callback == 0) return;
420 ALOGV("asyncCallback onWriteReady");
421 callback->onWriteReady();
422}
423
424void StreamOutHalAidl::onDrainReady() {
425 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
426 if (callback == 0) return;
427 ALOGV("asyncCallback onDrainReady");
428 callback->onDrainReady();
429}
430
431void StreamOutHalAidl::onError() {
432 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
433 if (callback == 0) return;
434 ALOGV("asyncCallback onError");
435 callback->onError();
436}
437
438void StreamOutHalAidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs __unused) {
439 sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
440 if (callback == nullptr) return;
441 ALOGV("asyncCodecFormatCallback %s", __func__);
442 callback->onCodecFormatChanged(metadataBs);
443}
444
445void StreamOutHalAidl::onRecommendedLatencyModeChanged(
446 const std::vector<audio_latency_mode_t>& modes __unused) {
447 sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
448 if (callback == nullptr) return;
449 callback->onRecommendedLatencyModeChanged(modes);
450}
451
452status_t StreamOutHalAidl::exit() {
453 // FIXME this is using hard-coded strings but in the future, this functionality will be
454 // converted to use audio HAL extensions required to support tunneling
455 if (!mStream) return NO_INIT;
456 ALOGE("%s not implemented yet", __func__);
457 return OK;
458}
459
460StreamInHalAidl::StreamInHalAidl(
461 const StreamDescriptor& descriptor, const std::shared_ptr<IStreamIn>& stream)
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000462 : StreamHalAidl("StreamInHalAidl", true /*isInput*/, descriptor, getStreamCommon(stream)),
Mikhail Naganov31d46652023-01-10 18:29:25 +0000463 mStream(stream) {}
464
465status_t StreamInHalAidl::setGain(float gain __unused) {
466 TIME_CHECK();
467 if (!mStream) return NO_INIT;
468 ALOGE("%s not implemented yet", __func__);
469 return OK;
470}
471
472status_t StreamInHalAidl::read(
473 void *buffer __unused, size_t bytes __unused, size_t *read __unused) {
474 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
475 if (!mStream) return NO_INIT;
476 ALOGE("%s not implemented yet", __func__);
477 // FIXME: Don't forget to update mPowerLog
478 return OK;
479}
480
481status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost __unused) {
482 TIME_CHECK();
483 if (!mStream) return NO_INIT;
484 ALOGE("%s not implemented yet", __func__);
485 return OK;
486}
487
488status_t StreamInHalAidl::getCapturePosition(int64_t *frames __unused, int64_t *time __unused) {
489 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
490 if (!mStream) return NO_INIT;
491 ALOGE("%s not implemented yet", __func__);
492 return OK;
493}
494
495status_t StreamInHalAidl::getActiveMicrophones(
496 std::vector<media::MicrophoneInfo> *microphones __unused) {
497 if (mStream == 0) return NO_INIT;
498 return INVALID_OPERATION;
499}
500
501status_t StreamInHalAidl::updateSinkMetadata(
502 const StreamInHalInterface::SinkMetadata& sinkMetadata __unused) {
503 return INVALID_OPERATION;
504}
505
506status_t StreamInHalAidl::setPreferredMicrophoneDirection(
507 audio_microphone_direction_t direction __unused) {
508 if (mStream == 0) return NO_INIT;
509 return INVALID_OPERATION;
510}
511
512status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
513 if (mStream == 0) return NO_INIT;
514 return INVALID_OPERATION;
515}
516
517} // namespace android