blob: 73389525af62e360b776f976c78d7123a040d97a [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
34StreamHalAidl::StreamHalAidl(
35 std::string_view className, bool isInput, const StreamDescriptor& descriptor,
36 const std::shared_ptr<IStreamCommon>& stream)
37 : ConversionHelperAidl(className),
38 mIsInput(isInput),
39 mFrameSizeBytes(descriptor.frameSizeBytes),
40 mBufferSizeFrames(descriptor.bufferSizeFrames),
41 mCommandMQ(new CommandMQ(descriptor.command)),
42 mReplyMQ(new ReplyMQ(descriptor.reply)),
43 mDataMQ(maybeCreateDataMQ(descriptor)),
44 mStream(stream) {
45 // Instrument audio signal power logging.
46 // Note: This assumes channel mask, format, and sample rate do not change after creation.
47 if (audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
48 /* mStreamPowerLog.isUserDebugOrEngBuild() && */
49 StreamHalAidl::getAudioProperties(&config) == NO_ERROR) {
50 mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
51 }
52}
53
54StreamHalAidl::~StreamHalAidl() {
55 if (mStream != nullptr) {
56 ndk::ScopedAStatus status = mStream->close();
57 ALOGE_IF(!status.isOk(), "%s: status %s", __func__, status.getDescription().c_str());
58 }
59}
60
61status_t StreamHalAidl::getBufferSize(size_t *size) {
62 if (size == nullptr) {
63 return BAD_VALUE;
64 }
65 if (mFrameSizeBytes == 0 || mBufferSizeFrames == 0) {
66 return NO_INIT;
67 }
68 *size = mFrameSizeBytes * mBufferSizeFrames;
69 return OK;
70}
71
72status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
73 if (configBase == nullptr) {
74 return BAD_VALUE;
75 }
76 TIME_CHECK();
77 *configBase = AUDIO_CONFIG_BASE_INITIALIZER;
78 configBase->sample_rate = 48000;
79 configBase->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
80 configBase->channel_mask = mIsInput ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_OUT_STEREO;
81 // if (!mStream) return NO_INIT;
82 ALOGE("%s not implemented yet", __func__);
83 return OK;
84}
85
86status_t StreamHalAidl::setParameters(const String8& kvPairs __unused) {
87 TIME_CHECK();
88 if (!mStream) return NO_INIT;
89 ALOGE("%s not implemented yet", __func__);
90 return OK;
91}
92
93status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
94 TIME_CHECK();
95 values->clear();
96 if (!mStream) return NO_INIT;
97 ALOGE("%s not implemented yet", __func__);
98 return OK;
99}
100
101status_t StreamHalAidl::getFrameSize(size_t *size) {
102 if (size == nullptr) {
103 return BAD_VALUE;
104 }
105 if (mFrameSizeBytes == 0) {
106 return NO_INIT;
107 }
108 *size = mFrameSizeBytes;
109 return OK;
110}
111
112status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
113 TIME_CHECK();
114 if (!mStream) return NO_INIT;
115 ALOGE("%s not implemented yet", __func__);
116 return OK;
117}
118
119status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
120 TIME_CHECK();
121 if (!mStream) return NO_INIT;
122 ALOGE("%s not implemented yet", __func__);
123 return OK;
124}
125
126status_t StreamHalAidl::standby() {
127 TIME_CHECK();
128 if (!mStream) return NO_INIT;
129 ALOGE("%s not implemented yet", __func__);
130 return OK;
131}
132
133status_t StreamHalAidl::dump(int fd __unused, const Vector<String16>& args __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::start() {
141 TIME_CHECK();
142 if (!mStream) return NO_INIT;
143 ALOGE("%s not implemented yet", __func__);
144 return OK;
145}
146
147status_t StreamHalAidl::stop() {
148 TIME_CHECK();
149 if (!mStream) return NO_INIT;
150 ALOGE("%s not implemented yet", __func__);
151 return OK;
152}
153
154status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
155 struct audio_mmap_buffer_info *info __unused) {
156 TIME_CHECK();
157 if (!mStream) return NO_INIT;
158 ALOGE("%s not implemented yet", __func__);
159 return OK;
160}
161
162status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
163 TIME_CHECK();
164 if (!mStream) return NO_INIT;
165 ALOGE("%s not implemented yet", __func__);
166 return OK;
167}
168
169status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
170 mHalThreadPriority = priority;
171 return OK;
172}
173
174status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
175 TIME_CHECK();
176 if (!mStream) return NO_INIT;
177 ALOGE("%s not implemented yet", __func__);
178 return OK;
179}
180
181bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
182 if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
183 return true;
184 }
185 if (!mStream) return NO_INIT;
186 ALOGE("%s not implemented yet", __func__);
187 return OK;
188}
189
190status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
191 std::optional<audio_source_t> source __unused,
192 audio_devices_t type __unused) {
193 TIME_CHECK();
194 LOG_ALWAYS_FATAL_IF(port.type != AUDIO_PORT_TYPE_DEVICE, "port type must be device");
195 if (!mStream) return NO_INIT;
196 ALOGE("%s not implemented yet", __func__);
197 return OK;
198}
199
200status_t StreamHalAidl::legacyReleaseAudioPatch() {
201 TIME_CHECK();
202 if (!mStream) return NO_INIT;
203 ALOGE("%s not implemented yet", __func__);
204 return OK;
205}
206
207namespace {
208
209/* Notes on callback ownership.
210
211This is how Binder ownership model looks like. The server implementation
212is owned by Binder framework (via sp<>). Proxies are owned by clients.
213When the last proxy disappears, Binder framework releases the server impl.
214
215Thus, it is not needed to keep any references to StreamCallback (this is
216the server impl) -- it will live as long as HAL server holds a strong ref to
217IStreamCallback proxy.
218
219The callback only keeps a weak reference to the stream. The stream is owned
220by AudioFlinger.
221
222*/
223
224class StreamCallback : public ::aidl::android::hardware::audio::core::BnStreamCallback {
225 ndk::ScopedAStatus onTransferReady() override {
226 return ndk::ScopedAStatus::ok();
227 }
228 ndk::ScopedAStatus onError() override {
229 return ndk::ScopedAStatus::ok();
230 }
231 ndk::ScopedAStatus onDrainReady() override {
232 return ndk::ScopedAStatus::ok();
233 }
234};
235
236} // namespace
237
238StreamOutHalAidl::StreamOutHalAidl(
239 const StreamDescriptor& descriptor, const std::shared_ptr<IStreamOut>& stream)
240 : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, descriptor,
241 nullptr /* FIXME: Retrieve IStreamCommon */),
242 mStream(stream) {}
243
244status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
245 TIME_CHECK();
246 *latency = 0;
247 if (!mStream) return NO_INIT;
248 ALOGE("%s not implemented yet", __func__);
249 return OK;
250}
251
252status_t StreamOutHalAidl::setVolume(float left __unused, float right __unused) {
253 TIME_CHECK();
254 if (!mStream) return NO_INIT;
255 ALOGE("%s not implemented yet", __func__);
256 return OK;
257}
258
259status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __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::write(
267 const void *buffer __unused, size_t bytes __unused, size_t *written __unused) {
268 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
269 if (!mStream) return NO_INIT;
270 *written = 0;
271 ALOGE("%s not implemented yet", __func__);
272 return OK;
273}
274
275status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames __unused) {
276 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
277 if (!mStream) return NO_INIT;
278 ALOGE("%s not implemented yet", __func__);
279 return OK;
280}
281
282status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
283 TIME_CHECK();
284 if (!mStream) return NO_INIT;
285 ALOGE("%s not implemented yet", __func__);
286 return OK;
287}
288
289status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback __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::supportsPauseAndResume(
297 bool *supportsPause __unused, bool *supportsResume __unused) {
298 TIME_CHECK();
299 if (!mStream) return NO_INIT;
300 ALOGE("%s not implemented yet", __func__);
301 return OK;
302}
303
304status_t StreamOutHalAidl::pause() {
305 TIME_CHECK();
306 if (!mStream) return NO_INIT;
307 ALOGE("%s not implemented yet", __func__);
308 return OK;
309}
310
311status_t StreamOutHalAidl::resume() {
312 TIME_CHECK();
313 if (!mStream) return NO_INIT;
314 ALOGE("%s not implemented yet", __func__);
315 return OK;
316}
317
318status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain __unused) {
319 TIME_CHECK();
320 if (!mStream) return NO_INIT;
321 ALOGE("%s not implemented yet", __func__);
322 return OK;
323}
324
325status_t StreamOutHalAidl::drain(bool earlyNotify __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::flush() {
333 TIME_CHECK();
334 if (!mStream) return NO_INIT;
335 ALOGE("%s not implemented yet", __func__);
336 return OK;
337}
338
339status_t StreamOutHalAidl::getPresentationPosition(
340 uint64_t *frames __unused, struct timespec *timestamp __unused) {
341 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
342 if (!mStream) return NO_INIT;
343 ALOGE("%s not implemented yet", __func__);
344 return OK;
345}
346
347status_t StreamOutHalAidl::updateSourceMetadata(
348 const StreamOutHalInterface::SourceMetadata& sourceMetadata __unused) {
349 TIME_CHECK();
350 if (!mStream) return NO_INIT;
351 ALOGE("%s not implemented yet", __func__);
352 return OK;
353}
354
355status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
356 return INVALID_OPERATION;
357}
358
359status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
360 return INVALID_OPERATION;
361}
362
363status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
364 return INVALID_OPERATION;
365}
366
367status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
368 return INVALID_OPERATION;
369}
370
371status_t StreamOutHalAidl::getPlaybackRateParameters(
372 audio_playback_rate_t* playbackRate __unused) {
373 return INVALID_OPERATION;
374}
375
376status_t StreamOutHalAidl::setPlaybackRateParameters(
377 const audio_playback_rate_t& playbackRate __unused) {
378 return INVALID_OPERATION;
379}
380
381status_t StreamOutHalAidl::setEventCallback(
382 const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
383 return INVALID_OPERATION;
384}
385
386namespace {
387
388struct StreamOutEventCallback {
389 StreamOutEventCallback(const wp<StreamOutHalAidl>& stream) : mStream(stream) {}
390 private:
391 wp<StreamOutHalAidl> mStream;
392};
393
394} // namespace
395
396status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
397 return INVALID_OPERATION;
398};
399
400status_t StreamOutHalAidl::getRecommendedLatencyModes(
401 std::vector<audio_latency_mode_t> *modes __unused) {
402 return INVALID_OPERATION;
403};
404
405status_t StreamOutHalAidl::setLatencyModeCallback(
406 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
407 return INVALID_OPERATION;
408};
409
410void StreamOutHalAidl::onWriteReady() {
411 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
412 if (callback == 0) return;
413 ALOGV("asyncCallback onWriteReady");
414 callback->onWriteReady();
415}
416
417void StreamOutHalAidl::onDrainReady() {
418 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
419 if (callback == 0) return;
420 ALOGV("asyncCallback onDrainReady");
421 callback->onDrainReady();
422}
423
424void StreamOutHalAidl::onError() {
425 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
426 if (callback == 0) return;
427 ALOGV("asyncCallback onError");
428 callback->onError();
429}
430
431void StreamOutHalAidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs __unused) {
432 sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
433 if (callback == nullptr) return;
434 ALOGV("asyncCodecFormatCallback %s", __func__);
435 callback->onCodecFormatChanged(metadataBs);
436}
437
438void StreamOutHalAidl::onRecommendedLatencyModeChanged(
439 const std::vector<audio_latency_mode_t>& modes __unused) {
440 sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
441 if (callback == nullptr) return;
442 callback->onRecommendedLatencyModeChanged(modes);
443}
444
445status_t StreamOutHalAidl::exit() {
446 // FIXME this is using hard-coded strings but in the future, this functionality will be
447 // converted to use audio HAL extensions required to support tunneling
448 if (!mStream) return NO_INIT;
449 ALOGE("%s not implemented yet", __func__);
450 return OK;
451}
452
453StreamInHalAidl::StreamInHalAidl(
454 const StreamDescriptor& descriptor, const std::shared_ptr<IStreamIn>& stream)
455 : StreamHalAidl("StreamInHalAidl", true /*isInput*/, descriptor,
456 nullptr /* FIXME: Retrieve IStreamCommon */),
457 mStream(stream) {}
458
459status_t StreamInHalAidl::setGain(float gain __unused) {
460 TIME_CHECK();
461 if (!mStream) return NO_INIT;
462 ALOGE("%s not implemented yet", __func__);
463 return OK;
464}
465
466status_t StreamInHalAidl::read(
467 void *buffer __unused, size_t bytes __unused, size_t *read __unused) {
468 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
469 if (!mStream) return NO_INIT;
470 ALOGE("%s not implemented yet", __func__);
471 // FIXME: Don't forget to update mPowerLog
472 return OK;
473}
474
475status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost __unused) {
476 TIME_CHECK();
477 if (!mStream) return NO_INIT;
478 ALOGE("%s not implemented yet", __func__);
479 return OK;
480}
481
482status_t StreamInHalAidl::getCapturePosition(int64_t *frames __unused, int64_t *time __unused) {
483 // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
484 if (!mStream) return NO_INIT;
485 ALOGE("%s not implemented yet", __func__);
486 return OK;
487}
488
489status_t StreamInHalAidl::getActiveMicrophones(
490 std::vector<media::MicrophoneInfo> *microphones __unused) {
491 if (mStream == 0) return NO_INIT;
492 return INVALID_OPERATION;
493}
494
495status_t StreamInHalAidl::updateSinkMetadata(
496 const StreamInHalInterface::SinkMetadata& sinkMetadata __unused) {
497 return INVALID_OPERATION;
498}
499
500status_t StreamInHalAidl::setPreferredMicrophoneDirection(
501 audio_microphone_direction_t direction __unused) {
502 if (mStream == 0) return NO_INIT;
503 return INVALID_OPERATION;
504}
505
506status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
507 if (mStream == 0) return NO_INIT;
508 return INVALID_OPERATION;
509}
510
511} // namespace android