Merge "MediaPlayer: fix channel mask handling"
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index 0bd0d88..d62dd91 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -8,6 +8,7 @@
task_profiles ProcessCapacityHigh HighPerformance
onrestart restart vendor.audio-hal
onrestart restart vendor.audio-hal-aidl
+ onrestart restart vendor.audio-effect-hal-aidl
onrestart restart vendor.audio-hal-4-0-msd
onrestart restart audio_proxy_service
@@ -19,6 +20,7 @@
on property:init.svc.audioserver=stopped
stop vendor.audio-hal
stop vendor.audio-hal-aidl
+ stop vendor.audio-effect-hal-aidl
stop vendor.audio-hal-4-0-msd
stop audio_proxy_service
# See b/155364397. Need to have HAL service running for VTS.
@@ -26,12 +28,14 @@
# audioserver bringing it back into running state.
start vendor.audio-hal
start vendor.audio-hal-aidl
+ start vendor.audio-effect-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
on property:init.svc.audioserver=running
start vendor.audio-hal
start vendor.audio-hal-aidl
+ start vendor.audio-effect-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
@@ -40,10 +44,12 @@
# Keep the original service names for backward compatibility
stop vendor.audio-hal
stop vendor.audio-hal-aidl
+ stop vendor.audio-effect-hal-aidl
stop vendor.audio-hal-4-0-msd
stop audio_proxy_service
start vendor.audio-hal
start vendor.audio-hal-aidl
+ start vendor.audio-effect-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
# reset the property
diff --git a/media/janitors/media_solutions_OWNERS b/media/janitors/media_solutions_OWNERS
index 8dc1c7b..69e3a5e 100644
--- a/media/janitors/media_solutions_OWNERS
+++ b/media/janitors/media_solutions_OWNERS
@@ -2,9 +2,9 @@
# go/android-fwk-media-solutions for info on areas of ownership.
# Main owners:
+adadukin@google.com
aquilescanta@google.com
-krocard@google.com
+ivanbuper@google.com
# In case of emergency:
andrewlewis@google.com #{LAST_RESORT_SUGGESTION}
-olly@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index c51ec0e..db9649c 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -302,12 +302,26 @@
double_loadable: true,
vendor_available: true,
srcs: [
+ "aidl/android/media/EffectConfig.aidl",
"aidl/android/media/IEffect.aidl",
"aidl/android/media/IEffectClient.aidl",
],
imports: [
+ "android.media.audio.common.types-V1",
"shared-file-region-aidl",
],
+ backend: {
+ cpp: {
+ min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ ],
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
}
aidl_interface {
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index d447f0c..641c4d9 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -527,6 +527,36 @@
return status;
}
+status_t AudioEffect::getConfigs(
+ audio_config_base_t *inputCfg, audio_config_base_t *outputCfg)
+{
+ if (mProbe) {
+ return INVALID_OPERATION;
+ }
+ if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+ return mStatus;
+ }
+ if (inputCfg == NULL || outputCfg == NULL) {
+ return BAD_VALUE;
+ }
+ status_t status;
+ media::EffectConfig cfg;
+ Status bs = mIEffect->getConfig(&cfg, &status);
+ if (!bs.isOk()) {
+ status = statusTFromBinderStatus(bs);
+ ALOGW("%s received status %d from binder transaction", __func__, status);
+ return status;
+ }
+ if (status == NO_ERROR) {
+ *inputCfg = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioConfigBase_audio_config_base_t(
+ cfg.inputCfg, cfg.isOnInputStream));
+ *outputCfg = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioConfigBase_audio_config_base_t(
+ cfg.outputCfg, cfg.isOnInputStream));
+ } else {
+ ALOGW("%s received status %d from the effect", __func__, status);
+ }
+ return status;
+}
// -------------------------------------------------------------------------
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 1280577..7e4d514 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2272,6 +2272,9 @@
const AudioDeviceTypeAddrVector &devices,
bool *canBeSpatialized) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (canBeSpatialized == nullptr) {
+ return BAD_VALUE;
+ }
if (aps == 0) {
return PERMISSION_DENIED;
}
diff --git a/media/libaudioclient/aidl/android/media/EffectConfig.aidl b/media/libaudioclient/aidl/android/media/EffectConfig.aidl
new file mode 100644
index 0000000..5f62b73
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/EffectConfig.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.audio.common.AudioConfigBase;
+
+/**
+ * Describes configuration of an audio effect. Input and output
+ * audio configurations are described separately because the effect
+ * can perform transformations on channel layouts, for example.
+ *
+ * {@hide}
+ */
+parcelable EffectConfig {
+ /** Configuration of the audio input of the effect. */
+ AudioConfigBase inputCfg;
+ /** Configuration of the audio output of the effect. */
+ AudioConfigBase outputCfg;
+ /**
+ * Specifies whether the effect is instantiated on an input stream,
+ * e.g. on the input from a microphone.
+ */
+ boolean isOnInputStream;
+}
diff --git a/media/libaudioclient/aidl/android/media/IEffect.aidl b/media/libaudioclient/aidl/android/media/IEffect.aidl
index 6ec0405..b7f70a6 100644
--- a/media/libaudioclient/aidl/android/media/IEffect.aidl
+++ b/media/libaudioclient/aidl/android/media/IEffect.aidl
@@ -16,6 +16,7 @@
package android.media;
+import android.media.EffectConfig;
import android.media.SharedFileRegion;
/**
@@ -63,6 +64,14 @@
*/
SharedFileRegion getCblk();
+ /**
+ * Provides audio configurations for effect's input and output,
+ * see EffectConfig parcelable for more details.
+ *
+ * @return a status_t code.
+ */
+ int getConfig(out EffectConfig config);
+
// When adding a new method, please review and update
// Effects.cpp AudioFlinger::EffectHandle::onTransact()
// Effects.cpp IEFFECT_BINDER_METHOD_MACRO_LIST
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index ca35543..72c050b 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -578,6 +578,25 @@
uint32_t *replySize,
void *replyData);
+ /* Retrieves the configuration of the effect.
+ *
+ * Parameters:
+ * inputCfg: pointer to audio_config_base_t structure receiving input
+ * configuration of the effect
+ * outputCfg: pointer to audio_config_base_t structure receiving output
+ * configuration of the effect
+ *
+ * Channel masks of the returned configs are "input" or "output" depending
+ * on the direction of the stream that the effect is attached to.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the AudioEffect was not successfully initialized.
+ * - BAD_VALUE: null config pointers
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ virtual status_t getConfigs(audio_config_base_t *inputCfg,
+ audio_config_base_t *outputCfg);
/*
* Utility functions.
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index e6d7cf7..72c378d 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -569,7 +569,8 @@
mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
mDisableWaitCnt(0), // set by process() and updateState()
mOffloaded(false),
- mAddedToHal(false)
+ mAddedToHal(false),
+ mIsOutput(false)
#ifdef FLOAT_EFFECT_CHAIN
, mSupportsFloat(false)
#endif
@@ -962,6 +963,7 @@
mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
mConfig.inputCfg.buffer.frameCount = callback->frameCount();
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
+ mIsOutput = callback->isOutput();
ALOGV("configure() %p chain %p buffer %p framecount %zu",
this, callback->chain().promote().get(),
@@ -980,7 +982,7 @@
#ifdef MULTICHANNEL_EFFECT_CHAIN
if (status != NO_ERROR &&
- callback->isOutput() &&
+ mIsOutput &&
(mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
|| mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
// Older effects may require exact STEREO position mask.
@@ -1643,6 +1645,22 @@
return status;
}
+status_t AudioFlinger::EffectModule::getConfigs(
+ audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
+ Mutex::Autolock _l(mLock);
+ if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
+ return NO_INIT;
+ }
+ inputCfg->sample_rate = mConfig.inputCfg.samplingRate;
+ inputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.inputCfg.channels);
+ inputCfg->format = static_cast<audio_format_t>(mConfig.inputCfg.format);
+ outputCfg->sample_rate = mConfig.outputCfg.samplingRate;
+ outputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.outputCfg.channels);
+ outputCfg->format = static_cast<audio_format_t>(mConfig.outputCfg.format);
+ *isOutput = mIsOutput;
+ return NO_ERROR;
+}
+
static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
std::stringstream ss;
@@ -1760,6 +1778,7 @@
BINDER_METHOD_ENTRY(command) \
BINDER_METHOD_ENTRY(disconnect) \
BINDER_METHOD_ENTRY(getCblk) \
+BINDER_METHOD_ENTRY(getConfig) \
// singleton for Binder Method Statistics for IEffect
mediautils::MethodStatistics<int>& getIEffectStatistics() {
@@ -1803,6 +1822,13 @@
*_aidl_return = (code); \
return Status::ok();
+#define VALUE_OR_RETURN_STATUS_AS_OUT(exp) \
+ ({ \
+ auto _tmp = (exp); \
+ if (!_tmp.ok()) { RETURN(_tmp.error()); } \
+ std::move(_tmp.value()); \
+ })
+
Status AudioFlinger::EffectHandle::enable(int32_t* _aidl_return)
{
AutoMutex _l(mLock);
@@ -1914,6 +1940,32 @@
return Status::ok();
}
+Status AudioFlinger::EffectHandle::getConfig(
+ media::EffectConfig* _config, int32_t* _aidl_return) {
+ AutoMutex _l(mLock);
+ sp<EffectBase> effect = mEffect.promote();
+ if (effect == nullptr || mDisconnected) {
+ RETURN(DEAD_OBJECT);
+ }
+ sp<EffectModule> effectModule = effect->asEffectModule();
+ if (effectModule == nullptr) {
+ RETURN(INVALID_OPERATION);
+ }
+ audio_config_base_t inputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
+ audio_config_base_t outputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
+ bool isOutput;
+ status_t status = effectModule->getConfigs(&inputCfg, &outputCfg, &isOutput);
+ if (status == NO_ERROR) {
+ constexpr bool isInput = false; // effects always use 'OUT' channel masks.
+ _config->inputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(inputCfg, isInput));
+ _config->outputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(outputCfg, isInput));
+ _config->isOnInputStream = !isOutput;
+ }
+ RETURN(status);
+}
+
Status AudioFlinger::EffectHandle::command(int32_t cmdCode,
const std::vector<uint8_t>& cmdData,
int32_t maxResponseSize,
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 42614cc..a89a814 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -283,6 +283,10 @@
status_t setHapticIntensity(int id, int intensity);
status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo);
+ status_t getConfigs(audio_config_base_t* inputCfg,
+ audio_config_base_t* outputCfg,
+ bool* isOutput) const;
+
void dump(int fd, const Vector<String16>& args);
private:
@@ -314,6 +318,7 @@
uint32_t mDisableWaitCnt; // current process() calls count during disable period.
bool mOffloaded; // effect is currently offloaded to the audio DSP
bool mAddedToHal; // effect has been added to the audio HAL
+ bool mIsOutput; // direction of the AF thread
#ifdef FLOAT_EFFECT_CHAIN
bool mSupportsFloat; // effect supports float processing
@@ -370,6 +375,8 @@
int32_t* _aidl_return) override;
android::binder::Status disconnect() override;
android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
+ android::binder::Status getConfig(media::EffectConfig* _config,
+ int32_t* _aidl_return) override;
sp<Client> client() const { return mClient; }