Merge "Use another Vector as a swap to reduce computing complexity"
diff --git a/Android.bp b/Android.bp
index 5aa2029..37f6457 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,7 @@
srcs: [
"aidl/android/media/InterpolatorConfig.aidl",
"aidl/android/media/InterpolatorType.aidl",
- "aidl/android/media/MicrophoneInfoData.aidl",
+ "aidl/android/media/MicrophoneInfoFw.aidl",
"aidl/android/media/VolumeShaperConfiguration.aidl",
"aidl/android/media/VolumeShaperConfigurationOptionFlag.aidl",
"aidl/android/media/VolumeShaperConfigurationType.aidl",
@@ -52,6 +52,9 @@
"aidl/android/media/VolumeShaperOperationFlag.aidl",
"aidl/android/media/VolumeShaperState.aidl",
],
+ imports: [
+ "android.media.audio.common.types-V2",
+ ],
backend: {
cpp: {
min_sdk_version: "29",
@@ -62,6 +65,9 @@
"com.android.media.swcodec",
],
},
+ java: {
+ sdk_version: "module_current",
+ },
},
}
diff --git a/aidl/android/media/MicrophoneInfoData.aidl b/aidl/android/media/MicrophoneInfoFw.aidl
similarity index 62%
rename from aidl/android/media/MicrophoneInfoData.aidl
rename to aidl/android/media/MicrophoneInfoFw.aidl
index 747bfa5..bad0e0a 100644
--- a/aidl/android/media/MicrophoneInfoData.aidl
+++ b/aidl/android/media/MicrophoneInfoFw.aidl
@@ -16,24 +16,14 @@
package android.media;
+import android.media.audio.common.MicrophoneDynamicInfo;
+import android.media.audio.common.MicrophoneInfo;
+
/**
* {@hide}
*/
-parcelable MicrophoneInfoData {
- @utf8InCpp String deviceId;
+parcelable MicrophoneInfoFw {
+ MicrophoneInfo info;
+ MicrophoneDynamicInfo dynamic;
int portId;
- int type;
- @utf8InCpp String address;
- int deviceLocation;
- int deviceGroup;
- int indexInTheGroup;
- float[] geometricLocation;
- float[] orientation;
- float[] frequencies;
- float[] frequencyResponses;
- int[] channelMapping;
- float sensitivity;
- float maxSpl;
- float minSpl;
- int directionality;
}
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index df3a6a2..ab25c65 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -63,3 +63,39 @@
init_rc: ["drmserver.rc"],
}
+
+cc_fuzz {
+ name: "drmserver_fuzzer",
+
+ defaults: [
+ "service_fuzzer_defaults",
+ ],
+
+ srcs: [
+ "fuzzer/DrmFuzzer.cpp",
+ "DrmManagerService.cpp",
+ "DrmManager.cpp",
+ ],
+
+ static_libs: [
+ "libmediautils",
+ "liblog",
+ "libdl",
+ "libdrmframeworkcommon",
+ "libselinux",
+ "libstagefright_foundation",
+ ],
+
+ shared_libs: [
+ "libmediametrics",
+ ],
+
+ fuzz_config: {
+ libfuzzer_options: [
+ "max_len=50000",
+ ],
+ cc: [
+ "android-drm-team@google.com",
+ ],
+ },
+}
\ No newline at end of file
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index f9b8bef..56201d9 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -141,6 +141,8 @@
virtual status_t dump(int fd, const Vector<String16>& args);
+ friend class DrmManagerServiceFuzzer;
+
private:
sp<DrmManager> mDrmManager;
};
diff --git a/drm/drmserver/fuzzer/DrmFuzzer.cpp b/drm/drmserver/fuzzer/DrmFuzzer.cpp
new file mode 100644
index 0000000..4b23679
--- /dev/null
+++ b/drm/drmserver/fuzzer/DrmFuzzer.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <fuzzbinder/libbinder_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "DrmManagerService.h"
+
+namespace android {
+class DrmManagerServiceFuzzer {
+public:
+ DrmManagerServiceFuzzer() {}
+
+ void fuzz(const uint8_t* data, size_t size) {
+ auto drmService = new DrmManagerService();
+ fuzzService(drmService, FuzzedDataProvider(data, size));
+ }
+};
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ android::DrmManagerServiceFuzzer serviceFuzzer;
+ serviceFuzzer.fuzz(data, size);
+ return 0;
+}
\ No newline at end of file
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
index c369529..1844acb 100644
--- a/drm/libmediadrm/DrmHalAidl.cpp
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -393,7 +393,8 @@
// DrmHalAidl methods
DrmHalAidl::DrmHalAidl()
- : mListener(::ndk::SharedRefBase::make<DrmHalListener>(&mMetrics)),
+ : mMetrics(std::make_shared<MediaDrmMetrics>()),
+ mListener(::ndk::SharedRefBase::make<DrmHalListener>(mMetrics)),
mFactories(DrmUtils::makeDrmFactoriesAidl()),
mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
@@ -462,8 +463,8 @@
Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
std::string appPackageNameAidl = toStdString(appPackageName);
std::shared_ptr<IDrmPluginAidl> pluginAidl;
- mMetrics.SetAppPackageName(appPackageName);
- mMetrics.SetAppUid(AIBinder_getCallingUid());
+ mMetrics->SetAppPackageName(appPackageName);
+ mMetrics->SetAppUid(AIBinder_getCallingUid());
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
::ndk::ScopedAStatus status =
mFactories[i]->createDrmPlugin(uuidAidl, appPackageNameAidl, &pluginAidl);
@@ -539,10 +540,10 @@
AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
sessionId);
mOpenSessions.push_back(client);
- mMetrics.SetSessionStart(sessionId);
+ mMetrics->SetSessionStart(sessionId);
}
- mMetrics.mOpenSessionCounter.Increment(err);
+ mMetrics->mOpenSessionCounter.Increment(err);
return err;
}
@@ -562,10 +563,10 @@
}
}
- mMetrics.SetSessionEnd(sessionId);
+ mMetrics->SetSessionEnd(sessionId);
}
- mMetrics.mCloseSessionCounter.Increment(response);
+ mMetrics->mCloseSessionCounter.Increment(response);
return response;
}
@@ -577,7 +578,7 @@
DrmPlugin::KeyRequestType* keyRequestType) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+ EventTimer<status_t> keyRequestTimer(&mMetrics->mGetKeyRequestTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
@@ -618,7 +619,7 @@
Vector<uint8_t>& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+ EventTimer<status_t> keyResponseTimer(&mMetrics->mProvideKeyResponseTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
@@ -687,7 +688,7 @@
defaultUrl = toString8(requestAidl.defaultUrl);
err = statusAidlToDrmStatus(status);
- mMetrics.mGetProvisionRequestCounter.Increment(err);
+ mMetrics->mGetProvisionRequestCounter.Increment(err);
return err;
}
@@ -704,7 +705,7 @@
certificate = toVector(result.certificate);
wrappedKey = toVector(result.wrappedKey);
err = statusAidlToDrmStatus(status);
- mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ mMetrics->mProvideProvisionResponseCounter.Increment(err);
return err;
}
@@ -914,7 +915,7 @@
value = toVector(result);
err = statusAidlToDrmStatus(status);
if (name == kPropertyDeviceUniqueId) {
- mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ mMetrics->mGetDeviceUniqueIdCounter.Increment(err);
}
return err;
}
@@ -940,7 +941,7 @@
if (consumer == nullptr) {
return DrmStatus(UNEXPECTED_NULL);
}
- consumer->consumeFrameworkMetrics(mMetrics);
+ consumer->consumeFrameworkMetrics(*mMetrics.get());
// Append vendor metrics if they are supported.
@@ -1146,7 +1147,7 @@
getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
- mMetrics.GetAppUid());
+ mMetrics->GetAppUid());
if (res != OK) {
ALOGE("Metrics were retrieved but could not be reported: %d", res);
}
@@ -1156,7 +1157,7 @@
std::string DrmHalAidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
mediametrics_handle_t item(mediametrics_create("mediadrm"));
- mediametrics_setUid(item, mMetrics.GetAppUid());
+ mediametrics_setUid(item, mMetrics->GetAppUid());
String8 vendor;
String8 description;
status_t result = getPropertyStringInternal(String8("vendor"), vendor);
@@ -1173,7 +1174,7 @@
}
std::string serializedMetrics;
- result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+ result = mMetrics->GetSerializedMetrics(&serializedMetrics);
if (result != OK) {
ALOGE("Failed to serialize framework metrics: %d", result);
}
diff --git a/drm/libmediadrm/DrmHalListener.cpp b/drm/libmediadrm/DrmHalListener.cpp
index cfcf475..4e868ac 100644
--- a/drm/libmediadrm/DrmHalListener.cpp
+++ b/drm/libmediadrm/DrmHalListener.cpp
@@ -37,12 +37,12 @@
return vec;
}
-DrmHalListener::DrmHalListener(MediaDrmMetrics* metrics)
+DrmHalListener::DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& metrics)
: mMetrics(metrics) {}
DrmHalListener::~DrmHalListener() {}
-void DrmHalListener::setListener(sp<IDrmClient> listener) {
+void DrmHalListener::setListener(const sp<IDrmClient>& listener) {
Mutex::Autolock lock(mEventLock);
mListener = listener;
}
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index f7653ff..89b1dcc 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -33,6 +33,7 @@
std::vector<uint8_t> vec(sessionKey, sessionKey + sessionId.size());
return vec;
}
+
} // namespace
DrmMetricsLogger::DrmMetricsLogger(IDrmFrontend frontend)
@@ -48,7 +49,8 @@
return status;
}
-DrmStatus DrmMetricsLogger::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+DrmStatus DrmMetricsLogger::isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& mimeType,
DrmPlugin::SecurityLevel securityLevel,
bool* result) {
DrmStatus status = mImpl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
@@ -58,8 +60,9 @@
return status;
}
-DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
- std::memcpy(mUuid.data(), uuid, mUuid.size());
+DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& appPackageName) {
+ std::memcpy(mUuid.data(), uuid, IDRM_UUID_SIZE);
if (kUuidSchemeMap.count(mUuid)) {
mScheme = kUuidSchemeMap.at(mUuid);
} else {
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
index e0b8341..a81b312 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
@@ -123,7 +123,7 @@
::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
private:
static Mutex mLock;
- mutable MediaDrmMetrics mMetrics;
+ std::shared_ptr<MediaDrmMetrics> mMetrics;
std::shared_ptr<DrmHalListener> mListener;
const std::vector<std::shared_ptr<IDrmFactoryAidl>> mFactories;
std::shared_ptr<IDrmPluginAidl> mPlugin;
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalListener.h b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
index 22361ad..0eed929 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalListener.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
@@ -27,7 +27,7 @@
namespace android {
struct DrmHalListener : public BnDrmPluginListener {
- explicit DrmHalListener(MediaDrmMetrics* mMetrics);
+ explicit DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& in_metrics);
~DrmHalListener();
::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
const std::vector<uint8_t>& in_sessionId,
@@ -38,9 +38,9 @@
const std::vector<KeyStatusAidl>& in_keyStatusList,
bool in_hasNewUsableKey);
::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
- void setListener(sp<IDrmClient> listener);
+ void setListener(const sp<IDrmClient>& listener);
private:
- mutable MediaDrmMetrics* mMetrics;
+ std::shared_ptr<MediaDrmMetrics> mMetrics;
sp<IDrmClient> mListener;
mutable Mutex mEventLock;
mutable Mutex mNotifyLock;
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
index d2e9a56..f4e3c3e 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -39,10 +39,13 @@
virtual DrmStatus initCheck() const;
- virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel securityLevel, bool* result);
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* result);
- virtual DrmStatus createPlugin(const uint8_t uuid[16], const String8& appPackageName);
+ virtual DrmStatus createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
+ const String8& appPackageName);
virtual DrmStatus destroyPlugin();
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index f37d1d1..ff5f63b 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -24,6 +24,8 @@
#define ANDROID_IDRM_H_
+#define IDRM_UUID_SIZE (16)
+
namespace android {
namespace hardware {
namespace drm {
diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h
deleted file mode 100644
index 6d6c594..0000000
--- a/include/media/MicrophoneInfo.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_MICROPHONE_INFO_H
-#define ANDROID_MICROPHONE_INFO_H
-
-#include <android/media/MicrophoneInfoData.h>
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <media/AidlConversionUtil.h>
-#include <system/audio.h>
-
-namespace android {
-namespace media {
-
-class MicrophoneInfo : public Parcelable {
-public:
- MicrophoneInfo() = default;
- MicrophoneInfo(const MicrophoneInfo& microphoneInfo) = default;
- MicrophoneInfo(audio_microphone_characteristic_t& characteristic) {
- mDeviceId = std::string(&characteristic.device_id[0]);
- mPortId = characteristic.id;
- mType = characteristic.device;
- mAddress = std::string(&characteristic.address[0]);
- mDeviceLocation = characteristic.location;
- mDeviceGroup = characteristic.group;
- mIndexInTheGroup = characteristic.index_in_the_group;
- mGeometricLocation.push_back(characteristic.geometric_location.x);
- mGeometricLocation.push_back(characteristic.geometric_location.y);
- mGeometricLocation.push_back(characteristic.geometric_location.z);
- mOrientation.push_back(characteristic.orientation.x);
- mOrientation.push_back(characteristic.orientation.y);
- mOrientation.push_back(characteristic.orientation.z);
- std::vector<float> frequencies;
- std::vector<float> responses;
- for (size_t i = 0; i < characteristic.num_frequency_responses; i++) {
- frequencies.push_back(characteristic.frequency_responses[0][i]);
- responses.push_back(characteristic.frequency_responses[1][i]);
- }
- mFrequencyResponses.push_back(frequencies);
- mFrequencyResponses.push_back(responses);
- for (size_t i = 0; i < AUDIO_CHANNEL_COUNT_MAX; i++) {
- mChannelMapping.push_back(characteristic.channel_mapping[i]);
- }
- mSensitivity = characteristic.sensitivity;
- mMaxSpl = characteristic.max_spl;
- mMinSpl = characteristic.min_spl;
- mDirectionality = characteristic.directionality;
- }
-
- virtual ~MicrophoneInfo() = default;
-
- virtual status_t writeToParcel(Parcel* parcel) const {
- MicrophoneInfoData parcelable;
- return writeToParcelable(&parcelable)
- ?: parcelable.writeToParcel(parcel);
- }
-
- virtual status_t writeToParcelable(MicrophoneInfoData* parcelable) const {
-#if defined(BACKEND_NDK)
- using ::aidl::android::convertReinterpret;
-#endif
- parcelable->deviceId = mDeviceId;
- parcelable->portId = mPortId;
- parcelable->type = VALUE_OR_RETURN_STATUS(convertReinterpret<int32_t>(mType));
- parcelable->address = mAddress;
- parcelable->deviceGroup = mDeviceGroup;
- parcelable->indexInTheGroup = mIndexInTheGroup;
- parcelable->geometricLocation = mGeometricLocation;
- parcelable->orientation = mOrientation;
- if (mFrequencyResponses.size() != 2) {
- return BAD_VALUE;
- }
- parcelable->frequencies = mFrequencyResponses[0];
- parcelable->frequencyResponses = mFrequencyResponses[1];
- parcelable->channelMapping = mChannelMapping;
- parcelable->sensitivity = mSensitivity;
- parcelable->maxSpl = mMaxSpl;
- parcelable->minSpl = mMinSpl;
- parcelable->directionality = mDirectionality;
- return OK;
- }
-
- virtual status_t readFromParcel(const Parcel* parcel) {
- MicrophoneInfoData data;
- return data.readFromParcel(parcel)
- ?: readFromParcelable(data);
- }
-
- virtual status_t readFromParcelable(const MicrophoneInfoData& parcelable) {
-#if defined(BACKEND_NDK)
- using ::aidl::android::convertReinterpret;
-#endif
- mDeviceId = parcelable.deviceId;
- mPortId = parcelable.portId;
- mType = VALUE_OR_RETURN_STATUS(convertReinterpret<uint32_t>(parcelable.type));
- mAddress = parcelable.address;
- mDeviceLocation = parcelable.deviceLocation;
- mDeviceGroup = parcelable.deviceGroup;
- mIndexInTheGroup = parcelable.indexInTheGroup;
- if (parcelable.geometricLocation.size() != 3) {
- return BAD_VALUE;
- }
- mGeometricLocation = parcelable.geometricLocation;
- if (parcelable.orientation.size() != 3) {
- return BAD_VALUE;
- }
- mOrientation = parcelable.orientation;
- if (parcelable.frequencies.size() != parcelable.frequencyResponses.size()) {
- return BAD_VALUE;
- }
-
- mFrequencyResponses.push_back(parcelable.frequencies);
- mFrequencyResponses.push_back(parcelable.frequencyResponses);
- if (parcelable.channelMapping.size() != AUDIO_CHANNEL_COUNT_MAX) {
- return BAD_VALUE;
- }
- mChannelMapping = parcelable.channelMapping;
- mSensitivity = parcelable.sensitivity;
- mMaxSpl = parcelable.maxSpl;
- mMinSpl = parcelable.minSpl;
- mDirectionality = parcelable.directionality;
- return OK;
- }
-
- std::string getDeviceId() const {
- return mDeviceId;
- }
-
- int getPortId() const {
- return mPortId;
- }
-
- unsigned int getType() const {
- return mType;
- }
-
- std::string getAddress() const {
- return mAddress;
- }
-
- int getDeviceLocation() const {
- return mDeviceLocation;
- }
-
- int getDeviceGroup() const {
- return mDeviceGroup;
- }
-
- int getIndexInTheGroup() const {
- return mIndexInTheGroup;
- }
-
- const std::vector<float>& getGeometricLocation() const {
- return mGeometricLocation;
- }
-
- const std::vector<float>& getOrientation() const {
- return mOrientation;
- }
-
- const std::vector<std::vector<float>>& getFrequencyResponses() const {
- return mFrequencyResponses;
- }
-
- const std::vector<int>& getChannelMapping() const {
- return mChannelMapping;
- }
-
- float getSensitivity() const {
- return mSensitivity;
- }
-
- float getMaxSpl() const {
- return mMaxSpl;
- }
-
- float getMinSpl() const {
- return mMinSpl;
- }
-
- int getDirectionality() const {
- return mDirectionality;
- }
-
-private:
- std::string mDeviceId;
- int32_t mPortId;
- uint32_t mType;
- std::string mAddress;
- int32_t mDeviceLocation;
- int32_t mDeviceGroup;
- int32_t mIndexInTheGroup;
- std::vector<float> mGeometricLocation;
- std::vector<float> mOrientation;
- std::vector<std::vector<float>> mFrequencyResponses;
- std::vector<int> mChannelMapping;
- float mSensitivity;
- float mMaxSpl;
- float mMinSpl;
- int32_t mDirectionality;
-};
-
-#if defined(BACKEND_NDK)
-using ::aidl::ConversionResult;
-#endif
-
-// Conversion routines, according to AidlConversion.h conventions.
-inline ConversionResult<MicrophoneInfo>
-aidl2legacy_MicrophoneInfo(const media::MicrophoneInfoData& aidl) {
- MicrophoneInfo legacy;
- RETURN_IF_ERROR(legacy.readFromParcelable(aidl));
- return legacy;
-}
-
-inline ConversionResult<media::MicrophoneInfoData>
-legacy2aidl_MicrophoneInfo(const MicrophoneInfo& legacy) {
- media::MicrophoneInfoData aidl;
- RETURN_IF_ERROR(legacy.writeToParcelable(&aidl));
- return aidl;
-}
-
-} // namespace media
-} // namespace android
-
-#endif
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 8704314..b0852f5 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -83,6 +83,8 @@
using media::audio::common::AudioUuid;
using media::audio::common::ExtraAudioDescriptor;
using media::audio::common::Int;
+using media::audio::common::MicrophoneDynamicInfo;
+using media::audio::common::MicrophoneInfo;
using media::audio::common::PcmType;
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2711,6 +2713,280 @@
return unexpected(BAD_VALUE);
}
+ConversionResult<audio_microphone_location_t>
+aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(MicrophoneInfo::Location aidl) {
+ switch (aidl) {
+ case MicrophoneInfo::Location::UNKNOWN:
+ return AUDIO_MICROPHONE_LOCATION_UNKNOWN;
+ case MicrophoneInfo::Location::MAINBODY:
+ return AUDIO_MICROPHONE_LOCATION_MAINBODY;
+ case MicrophoneInfo::Location::MAINBODY_MOVABLE:
+ return AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE;
+ case MicrophoneInfo::Location::PERIPHERAL:
+ return AUDIO_MICROPHONE_LOCATION_PERIPHERAL;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneInfo::Location>
+legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(audio_microphone_location_t legacy) {
+ switch (legacy) {
+ case AUDIO_MICROPHONE_LOCATION_UNKNOWN:
+ return MicrophoneInfo::Location::UNKNOWN;
+ case AUDIO_MICROPHONE_LOCATION_MAINBODY:
+ return MicrophoneInfo::Location::MAINBODY;
+ case AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE:
+ return MicrophoneInfo::Location::MAINBODY_MOVABLE;
+ case AUDIO_MICROPHONE_LOCATION_PERIPHERAL:
+ return MicrophoneInfo::Location::PERIPHERAL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_group_t> aidl2legacy_int32_t_audio_microphone_group_t(
+ int32_t aidl) {
+ return convertReinterpret<audio_microphone_group_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_microphone_group_t_int32_t(
+ audio_microphone_group_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_microphone_directionality_t>
+aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+ MicrophoneInfo::Directionality aidl) {
+ switch (aidl) {
+ case MicrophoneInfo::Directionality::UNKNOWN:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN;
+ case MicrophoneInfo::Directionality::OMNI:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_OMNI;
+ case MicrophoneInfo::Directionality::BI_DIRECTIONAL:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL;
+ case MicrophoneInfo::Directionality::CARDIOID:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID;
+ case MicrophoneInfo::Directionality::HYPER_CARDIOID:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID;
+ case MicrophoneInfo::Directionality::SUPER_CARDIOID:
+ return AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneInfo::Directionality>
+legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+ audio_microphone_directionality_t legacy) {
+ switch (legacy) {
+ case AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN:
+ return MicrophoneInfo::Directionality::UNKNOWN;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_OMNI:
+ return MicrophoneInfo::Directionality::OMNI;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL:
+ return MicrophoneInfo::Directionality::BI_DIRECTIONAL;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID:
+ return MicrophoneInfo::Directionality::CARDIOID;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID:
+ return MicrophoneInfo::Directionality::HYPER_CARDIOID;
+ case AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID:
+ return MicrophoneInfo::Directionality::SUPER_CARDIOID;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_coordinate>
+aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ const MicrophoneInfo::Coordinate& aidl) {
+ audio_microphone_coordinate legacy;
+ legacy.x = aidl.x;
+ legacy.y = aidl.y;
+ legacy.z = aidl.z;
+ return legacy;
+}
+ConversionResult<MicrophoneInfo::Coordinate>
+legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ const audio_microphone_coordinate& legacy) {
+ MicrophoneInfo::Coordinate aidl;
+ aidl.x = legacy.x;
+ aidl.y = legacy.y;
+ aidl.z = legacy.z;
+ return aidl;
+}
+
+ConversionResult<audio_microphone_channel_mapping_t>
+aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+ MicrophoneDynamicInfo::ChannelMapping aidl) {
+ switch (aidl) {
+ case MicrophoneDynamicInfo::ChannelMapping::UNUSED:
+ return AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+ case MicrophoneDynamicInfo::ChannelMapping::DIRECT:
+ return AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT;
+ case MicrophoneDynamicInfo::ChannelMapping::PROCESSED:
+ return AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneDynamicInfo::ChannelMapping>
+legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+ audio_microphone_channel_mapping_t legacy) {
+ switch (legacy) {
+ case AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED:
+ return MicrophoneDynamicInfo::ChannelMapping::UNUSED;
+ case AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT:
+ return MicrophoneDynamicInfo::ChannelMapping::DIRECT;
+ case AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED:
+ return MicrophoneDynamicInfo::ChannelMapping::PROCESSED;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+ const MicrophoneInfo& aidlInfo, const MicrophoneDynamicInfo& aidlDynamic) {
+ static const audio_microphone_coordinate kCoordinateUnknown = {
+ AUDIO_MICROPHONE_COORDINATE_UNKNOWN, AUDIO_MICROPHONE_COORDINATE_UNKNOWN,
+ AUDIO_MICROPHONE_COORDINATE_UNKNOWN };
+ audio_microphone_characteristic_t legacy{};
+ if (aidlInfo.id != aidlDynamic.id) {
+ return unexpected(BAD_VALUE);
+ }
+ // Note: in the legacy structure, 'device_id' is the mic's ID, 'id' is APM port id.
+ RETURN_IF_ERROR(aidl2legacy_string(aidlInfo.id, legacy.device_id, AUDIO_MICROPHONE_ID_MAX_LEN));
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidlInfo.device, &legacy.device, legacy.address));
+ legacy.location = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(aidlInfo.location));
+ legacy.group = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_microphone_group_t(aidlInfo.group));
+ // For some reason, the legacy field is unsigned, however in the SDK layer it is signed,
+ // as it is in AIDL. So, use UINT_MAX for INDEX_IN_THE_GROUP_UNKNOWN which is -1.
+ if (aidlInfo.indexInTheGroup != MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN) {
+ legacy.index_in_the_group = VALUE_OR_RETURN(
+ convertReinterpret<unsigned int>(aidlInfo.indexInTheGroup));
+ } else {
+ legacy.index_in_the_group = UINT_MAX;
+ }
+ if (aidlInfo.sensitivity.has_value()) {
+ legacy.sensitivity = aidlInfo.sensitivity.value().leveldBFS;
+ legacy.max_spl = aidlInfo.sensitivity.value().maxSpldB;
+ legacy.min_spl = aidlInfo.sensitivity.value().minSpldB;
+ } else {
+ legacy.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+ legacy.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ legacy.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ }
+ legacy.directionality = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+ aidlInfo.directionality));
+ if (aidlInfo.frequencyResponse.size() > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ return unexpected(BAD_VALUE);
+ }
+ legacy.num_frequency_responses = 0;
+ for (const auto& p: aidlInfo.frequencyResponse) {
+ legacy.frequency_responses[0][legacy.num_frequency_responses] = p.frequencyHz;
+ legacy.frequency_responses[1][legacy.num_frequency_responses++] = p.leveldB;
+ }
+ if (aidlInfo.position.has_value()) {
+ legacy.geometric_location = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ aidlInfo.position.value()));
+ } else {
+ legacy.geometric_location = kCoordinateUnknown;
+ }
+ if (aidlInfo.orientation.has_value()) {
+ legacy.orientation = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ aidlInfo.orientation.value()));
+ } else {
+ legacy.orientation = kCoordinateUnknown;
+ }
+ if (aidlDynamic.channelMapping.size() > AUDIO_CHANNEL_COUNT_MAX) {
+ return unexpected(BAD_VALUE);
+ }
+ size_t i = 0;
+ for (; i < aidlDynamic.channelMapping.size(); ++i) {
+ legacy.channel_mapping[i] = VALUE_OR_RETURN(
+ aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+ aidlDynamic.channelMapping[i]));
+ }
+ for (; i < AUDIO_CHANNEL_COUNT_MAX; ++i) {
+ legacy.channel_mapping[i] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+ }
+ return legacy;
+}
+
+status_t
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+ const audio_microphone_characteristic_t& legacy,
+ MicrophoneInfo* aidlInfo, MicrophoneDynamicInfo* aidlDynamic) {
+ aidlInfo->id = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_string(legacy.device_id, AUDIO_MICROPHONE_ID_MAX_LEN));
+ aidlDynamic->id = aidlInfo->id;
+ aidlInfo->device = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_device_AudioDevice(
+ legacy.device, legacy.address));
+ aidlInfo->location = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(legacy.location));
+ aidlInfo->group = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_group_t_int32_t(legacy.group));
+ // For some reason, the legacy field is unsigned, however in the SDK layer it is signed,
+ // as it is in AIDL. So, use UINT_MAX for INDEX_IN_THE_GROUP_UNKNOWN which is -1.
+ if (legacy.index_in_the_group != UINT_MAX) {
+ aidlInfo->indexInTheGroup = VALUE_OR_RETURN_STATUS(
+ convertReinterpret<int32_t>(legacy.index_in_the_group));
+ } else {
+ aidlInfo->indexInTheGroup = MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN;
+ }
+ if (legacy.sensitivity != AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN &&
+ legacy.max_spl != AUDIO_MICROPHONE_SPL_UNKNOWN &&
+ legacy.min_spl != AUDIO_MICROPHONE_SPL_UNKNOWN) {
+ MicrophoneInfo::Sensitivity sensitivity;
+ sensitivity.leveldBFS = legacy.sensitivity;
+ sensitivity.maxSpldB = legacy.max_spl;
+ sensitivity.minSpldB = legacy.min_spl;
+ aidlInfo->sensitivity = std::move(sensitivity);
+ } else {
+ aidlInfo->sensitivity = {};
+ }
+ aidlInfo->directionality = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+ legacy.directionality));
+ if (legacy.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ return BAD_VALUE;
+ }
+ aidlInfo->frequencyResponse.resize(legacy.num_frequency_responses);
+ for (size_t i = 0; i < legacy.num_frequency_responses; ++i) {
+ aidlInfo->frequencyResponse[i].frequencyHz = legacy.frequency_responses[0][i];
+ aidlInfo->frequencyResponse[i].leveldB = legacy.frequency_responses[1][i];
+ }
+ if (legacy.geometric_location.x != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.geometric_location.y != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.geometric_location.z != AUDIO_MICROPHONE_COORDINATE_UNKNOWN) {
+ aidlInfo->position = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ legacy.geometric_location));
+ } else {
+ aidlInfo->position = {};
+ }
+ if (legacy.orientation.x != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.orientation.y != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+ legacy.orientation.z != AUDIO_MICROPHONE_COORDINATE_UNKNOWN) {
+ aidlInfo->orientation = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ legacy.orientation));
+ } else {
+ aidlInfo->orientation = {};
+ }
+ size_t channelsUsed = AUDIO_CHANNEL_COUNT_MAX;
+ while (channelsUsed != 0 &&
+ legacy.channel_mapping[--channelsUsed] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {}
+ // Doing an increment is correct even when channel 0 is 'UNUSED',
+ // that's because AIDL requires to have at least 1 element in the mapping.
+ ++channelsUsed;
+ aidlDynamic->channelMapping.resize(channelsUsed);
+ for (size_t i = 0; i < channelsUsed; ++i) {
+ aidlDynamic->channelMapping[i] = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+ legacy.channel_mapping[i]));
+ }
+ return OK;
+}
+
} // namespace android
#if defined(BACKEND_NDK)
diff --git a/media/audioaidlconversion/AidlConversionEffect.cpp b/media/audioaidlconversion/AidlConversionEffect.cpp
index 9660072..ec380e3 100644
--- a/media/audioaidlconversion/AidlConversionEffect.cpp
+++ b/media/audioaidlconversion/AidlConversionEffect.cpp
@@ -14,12 +14,16 @@
* limitations under the License.
*/
+#include <cstdint>
+#include <inttypes.h>
#include <utility>
#define LOG_TAG "AidlConversionEffect"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionEffect.h>
@@ -30,17 +34,23 @@
namespace android {
using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
-using ::aidl::android::hardware::audio::effect::AutomaticGainControl;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV2;
using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::Downmix;
using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
using ::aidl::android::hardware::audio::effect::Flags;
using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::PresetReverb;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::hardware::audio::effect::Visualizer;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::android::BAD_VALUE;
using ::android::base::unexpected;
+using ::android::effect::utils::EffectParamReader;
+using ::android::effect::utils::EffectParamWriter;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Converters
@@ -152,7 +162,7 @@
if (aidl.audioSourceIndication) {
legacy |= EFFECT_FLAG_AUDIO_SOURCE_IND;
}
- if (aidl.noProcessing) {
+ if (aidl.bypass) {
legacy |= EFFECT_FLAG_NO_PROCESS;
}
return legacy;
@@ -169,7 +179,7 @@
aidl.deviceIndication = (legacy & EFFECT_FLAG_DEVICE_IND);
aidl.audioModeIndication = (legacy & EFFECT_FLAG_AUDIO_MODE_IND);
aidl.audioSourceIndication = (legacy & EFFECT_FLAG_AUDIO_SOURCE_IND);
- aidl.noProcessing = (legacy & EFFECT_FLAG_NO_PROCESS);
+ aidl.bypass = (legacy & EFFECT_FLAG_NO_PROCESS);
return aidl;
}
@@ -259,46 +269,47 @@
ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
const Parameter& aidl) {
int gain = VALUE_OR_RETURN(
- GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControl, automaticGainControl,
- AutomaticGainControl::fixedDigitalGainMb, int));
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControlV2, automaticGainControlV2,
+ AutomaticGainControlV2::fixedDigitalGainMb, int));
return VALUE_OR_RETURN(convertReinterpret<uint32_t>(gain));
}
ConversionResult<Parameter> legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy) {
int gain = VALUE_OR_RETURN(convertReinterpret<int>(legacy));
- return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, fixedDigitalGainMb,
- gain);
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+ fixedDigitalGainMb, gain);
}
ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
const Parameter& aidl) {
const auto& le = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
- aidl, AutomaticGainControl, automaticGainControl, AutomaticGainControl::levelEstimator,
- AutomaticGainControl::LevelEstimator));
+ aidl, AutomaticGainControlV2, automaticGainControlV2,
+ AutomaticGainControlV2::levelEstimator, AutomaticGainControlV2::LevelEstimator));
return static_cast<uint32_t>(le);
}
ConversionResult<Parameter> legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy) {
- if (legacy > (uint32_t) AutomaticGainControl::LevelEstimator::PEAK) {
+ if (legacy > (uint32_t)AutomaticGainControlV2::LevelEstimator::PEAK) {
return unexpected(BAD_VALUE);
}
- AutomaticGainControl::LevelEstimator le =
- static_cast<AutomaticGainControl::LevelEstimator>(legacy);
- return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, levelEstimator, le);
+ AutomaticGainControlV2::LevelEstimator le =
+ static_cast<AutomaticGainControlV2::LevelEstimator>(legacy);
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2, levelEstimator,
+ le);
}
ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
const Parameter& aidl) {
int saturationMargin = VALUE_OR_RETURN(
- GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControl, automaticGainControl,
- AutomaticGainControl::saturationMarginMb, int));
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControlV2, automaticGainControlV2,
+ AutomaticGainControlV2::saturationMarginMb, int));
return VALUE_OR_RETURN(convertIntegral<uint32_t>(saturationMargin));
}
ConversionResult<Parameter> legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy) {
int saturationMargin = VALUE_OR_RETURN(convertIntegral<int>(legacy));
- return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, saturationMarginMb,
- saturationMargin);
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+ saturationMarginMb, saturationMargin);
}
ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
@@ -347,6 +358,100 @@
return static_cast<int32_t>(aidl);
}
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+ Visualizer::ScalingMode aidl) {
+ switch (aidl) {
+ case Visualizer::ScalingMode::NORMALIZED: {
+ return 0;
+ }
+ case Visualizer::ScalingMode::AS_PLAYED: {
+ return 1;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::ScalingMode> legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(
+ uint32_t legacy) {
+ if (legacy == 0) {
+ return Visualizer::ScalingMode::NORMALIZED;
+ } else if (legacy == 1) {
+ return Visualizer::ScalingMode::AS_PLAYED;
+ } else {
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+ Visualizer::MeasurementMode aidl) {
+ switch (aidl) {
+ case Visualizer::MeasurementMode::NONE: {
+ return 0;
+ }
+ case Visualizer::MeasurementMode::PEAK_RMS: {
+ return 1;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy) {
+ if (legacy == 0) {
+ return Visualizer::MeasurementMode::NONE;
+ } else if (legacy == 1) {
+ return Visualizer::MeasurementMode::PEAK_RMS;
+ } else {
+ return unexpected(BAD_VALUE);
+ }
+}
+
+/**
+ * Copy the entire effect_param_t to DefaultExtension::bytes.
+ */
+ConversionResult<Parameter> legacy2aidl_EffectParameterReader_ParameterExtension(
+ EffectParamReader& param) {
+ size_t len = param.getTotalSize();
+ DefaultExtension ext;
+ ext.bytes.resize(len);
+ std::memcpy(ext.bytes.data(), ¶m.getEffectParam(), len);
+
+ VendorExtension effectParam;
+ effectParam.extension.setParcelable(ext);
+ return UNION_MAKE(Parameter, specific,
+ UNION_MAKE(Parameter::Specific, vendorEffect, effectParam));
+}
+
+ConversionResult<std::vector<uint8_t>> aidl2legacy_ParameterExtension_vector_uint8(
+ const Parameter& param) {
+ VendorExtension effectParam = VALUE_OR_RETURN(
+ (::aidl::android::getParameterSpecific<Parameter, VendorExtension,
+ Parameter::Specific::vendorEffect>(param)));
+ std::optional<DefaultExtension> ext;
+ if (STATUS_OK != effectParam.extension.getParcelable(&ext) || !ext.has_value()) {
+ return unexpected(BAD_VALUE);
+ }
+ return ext.value().bytes;
+}
+
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+ EffectParamWriter& legacy) {
+ const std::vector<uint8_t>& extBytes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_vector_uint8(aidl));
+ if (legacy.getTotalSize() < extBytes.size()) {
+ legacy.setStatus(BAD_VALUE);
+ return unexpected(BAD_VALUE);
+ }
+
+ // create a reader wrapper and read the content to legacy EffectParamWriter
+ EffectParamReader reader(*(effect_param_t*)extBytes.data());
+ if (STATUS_OK != legacy.writeToValue(reader.getValueAddress(), reader.getValueSize())) {
+ legacy.setStatus(BAD_VALUE);
+ return unexpected(BAD_VALUE);
+ }
+ return STATUS_OK;
+}
} // namespace android
} // aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
index c412238..e1daf31 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -61,6 +61,8 @@
#include PREFIX(android/media/audio/common/AudioUuid.h)
#include PREFIX(android/media/audio/common/ExtraAudioDescriptor.h)
#include PREFIX(android/media/audio/common/Int.h)
+#include PREFIX(android/media/audio/common/MicrophoneDynamicInfo.h)
+#include PREFIX(android/media/audio/common/MicrophoneInfo.h)
#undef PREFIX
#include <media/AidlConversionUtil.h>
@@ -125,6 +127,11 @@
ConversionResult<media::audio::common::AudioChannelLayout>
legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ int aidlLayout, bool isInput);
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+ audio_channel_mask_t legacy, bool isInput);
+
enum class AudioPortDirection {
INPUT, OUTPUT
};
@@ -371,6 +378,48 @@
ConversionResult<media::audio::common::AudioLatencyMode>
legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+ConversionResult<audio_microphone_location_t>
+aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(
+ media::audio::common::MicrophoneInfo::Location aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Location>
+legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(audio_microphone_location_t legacy);
+
+ConversionResult<audio_microphone_group_t> aidl2legacy_int32_t_audio_microphone_group_t(
+ int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_microphone_group_t_int32_t(
+ audio_microphone_group_t legacy);
+
+ConversionResult<audio_microphone_directionality_t>
+aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+ media::audio::common::MicrophoneInfo::Directionality aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Directionality>
+legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+ audio_microphone_directionality_t legacy);
+
+ConversionResult<audio_microphone_coordinate>
+aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+ const media::audio::common::MicrophoneInfo::Coordinate& aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Coordinate>
+legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+ const audio_microphone_coordinate& legacy);
+
+ConversionResult<audio_microphone_channel_mapping_t>
+aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+ media::audio::common::MicrophoneDynamicInfo::ChannelMapping aidl);
+ConversionResult<media::audio::common::MicrophoneDynamicInfo::ChannelMapping>
+legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+ audio_microphone_channel_mapping_t legacy);
+
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+ const media::audio::common::MicrophoneInfo& aidlInfo,
+ const media::audio::common::MicrophoneDynamicInfo& aidlDynamic);
+status_t
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+ const audio_microphone_characteristic_t& legacy,
+ media::audio::common::MicrophoneInfo* aidlInfo,
+ media::audio::common::MicrophoneDynamicInfo* aidlDynamic);
+
} // namespace android
#if defined(BACKEND_NDK)
diff --git a/media/audioaidlconversion/include/media/AidlConversionEffect.h b/media/audioaidlconversion/include/media/AidlConversionEffect.h
index 83aa614..3aa9ac2 100644
--- a/media/audioaidlconversion/include/media/AidlConversionEffect.h
+++ b/media/audioaidlconversion/include/media/AidlConversionEffect.h
@@ -26,6 +26,7 @@
#include <hardware/audio_effect.h>
#include <media/AidlConversionUtil.h>
#include <system/audio_effect.h>
+#include <system/audio_effects/audio_effects_utils.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
@@ -126,5 +127,24 @@
ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference aidl);
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+ ::aidl::android::hardware::audio::effect::Visualizer::ScalingMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::ScalingMode>
+legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+ ::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_EffectParameterReader_ParameterExtension(
+ ::android::effect::utils::EffectParamReader& param);
+ConversionResult<std::vector<uint8_t>> aidl2legacy_ParameterExtension_vector_uint8(
+ const ::aidl::android::hardware::audio::effect::Parameter& legacy);
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+ ::android::effect::utils::EffectParamWriter& legacy);
+
} // namespace android
} // namespace aidl
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 6fff568..4affaed 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -108,7 +108,7 @@
aaudio_result_t outputError = AAUDIO_OK;
GlitchAnalyzer sineAnalyzer;
- PulseLatencyAnalyzer echoAnalyzer;
+ WhiteNoiseLatencyAnalyzer echoAnalyzer;
AudioRecording audioRecording;
LoopbackProcessor *loopbackProcessor;
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index b3c8643..3a5ba78 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -990,4 +990,24 @@
indexToEnum_bitmask<audio_direct_mode_t>,
enumToMask_index<int32_t, media::AudioDirectMode>);
}
+
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(
+ const media::MicrophoneInfoFw& aidl) {
+ audio_microphone_characteristic_t legacy =
+ VALUE_OR_RETURN(aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+ aidl.info, aidl.dynamic));
+ legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
+ return legacy;
+}
+ConversionResult<media::MicrophoneInfoFw>
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+ const audio_microphone_characteristic_t& legacy) {
+ media::MicrophoneInfoFw aidl;
+ RETURN_IF_ERROR(legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+ legacy, &aidl.info, &aidl.dynamic));
+ aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ return aidl;
+}
+
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 1c0535d..30658f7 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -199,6 +199,7 @@
srcs: ["AidlConversion.cpp"],
shared_libs: [
"audioclient-types-aidl-cpp",
+ "av-types-aidl-cpp",
],
static_libs: [
"libaudio_aidl_conversion_common_cpp",
@@ -212,6 +213,7 @@
],
export_shared_lib_headers: [
"audioclient-types-aidl-cpp",
+ "av-types-aidl-cpp",
],
defaults: [
"audio_aidl_conversion_common_default",
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 69d73ad..91b54a8 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -1617,16 +1617,10 @@
// -------------------------------------------------------------------------
-status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
AutoMutex lock(mLock);
- std::vector<media::MicrophoneInfoData> mics;
- status_t status = statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(&mics));
- activeMicrophones->resize(mics.size());
- for (size_t i = 0; status == OK && i < mics.size(); ++i) {
- status = activeMicrophones->at(i).readFromParcelable(mics[i]);
- }
- return status;
+ return statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(activeMicrophones));
}
status_t AudioRecord::setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 31d95e6..6ffbdc4 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1904,7 +1904,7 @@
return result.value_or(NAN);
}
-status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
+status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->getMicrophones(microphones);
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 255fd1e..a005ab4 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -746,14 +746,11 @@
}
status_t
-AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
- std::vector<media::MicrophoneInfoData> aidlRet;
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mDelegate->getMicrophones(&aidlRet)));
+AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
+ std::vector<media::MicrophoneInfoFw> aidlRet;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getMicrophones(&aidlRet)));
if (microphones != nullptr) {
- *microphones = VALUE_OR_RETURN_STATUS(
- convertContainer<std::vector<media::MicrophoneInfo>>(aidlRet,
- media::aidl2legacy_MicrophoneInfo));
+ *microphones = std::move(aidlRet);
}
return OK;
}
@@ -1309,11 +1306,8 @@
}
Status AudioFlingerServerAdapter::getMicrophones(
- std::vector<media::MicrophoneInfoData>* _aidl_return) {
- std::vector<media::MicrophoneInfo> resultLegacy;
- RETURN_BINDER_IF_ERROR(mDelegate->getMicrophones(&resultLegacy));
- *_aidl_return = VALUE_OR_RETURN_BINDER(convertContainer<std::vector<media::MicrophoneInfoData>>(
- resultLegacy, media::legacy2aidl_MicrophoneInfo));
+ std::vector<media::MicrophoneInfoFw>* _aidl_return) {
+ RETURN_BINDER_IF_ERROR(mDelegate->getMicrophones(_aidl_return));
return Status::ok();
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 51bf05a..7c44c74 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -35,7 +35,7 @@
import android.media.IAudioFlingerClient;
import android.media.IAudioRecord;
import android.media.IAudioTrack;
-import android.media.MicrophoneInfoData;
+import android.media.MicrophoneInfoFw;
import android.media.RenderPosition;
import android.media.TrackSecondaryOutputInfo;
import android.media.audio.common.AudioChannelLayout;
@@ -208,7 +208,7 @@
long frameCountHAL(int /* audio_io_handle_t */ ioHandle);
/* List available microphones and their characteristics */
- MicrophoneInfoData[] getMicrophones();
+ MicrophoneInfoFw[] getMicrophones();
void setAudioHalPids(in int[] /* pid_t[] */ pids);
diff --git a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
index 44ef80b..1ea4156 100644
--- a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.MicrophoneInfoData;
+import android.media.MicrophoneInfoFw;
/**
* Native code must specify namespace media (media::IAudioRecord) when referring to this class.
@@ -39,7 +39,7 @@
/* Get a list of current active microphones.
*/
- void getActiveMicrophones(out MicrophoneInfoData[] activeMicrophones);
+ void getActiveMicrophones(out MicrophoneInfoFw[] activeMicrophones);
/* Set the microphone direction (for processing).
*/
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 036e72e..d881447 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -359,7 +359,7 @@
record->getInputFramesLost();
record->getFlags();
- std::vector<media::MicrophoneInfo> activeMicrophones;
+ std::vector<media::MicrophoneInfoFw> activeMicrophones;
record->getActiveMicrophones(&activeMicrophones);
record->releaseBuffer(&audioBuffer);
@@ -541,7 +541,7 @@
AudioSystem::getPrimaryOutputFrameCount();
AudioSystem::setLowRamDevice(mFdp.ConsumeBool(), mFdp.ConsumeIntegral<int64_t>());
- std::vector<media::MicrophoneInfo> microphones;
+ std::vector<media::MicrophoneInfoFw> microphones;
AudioSystem::getMicrophones(µphones);
std::vector<pid_t> pids;
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index f0e58ae..5bd0114 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -33,6 +33,7 @@
#include <android/media/AudioTimestampInternal.h>
#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
+#include <android/media/MicrophoneInfoFw.h>
#include <android/media/TrackSecondaryOutputInfo.h>
#include <android/media/SharedFileRegion.h>
@@ -198,4 +199,11 @@
ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(
+ const media::MicrophoneInfoFw& aidl);
+ConversionResult<media::MicrophoneInfoFw>
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+ const audio_microphone_characteristic_t& legacy);
+
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 5a1ff65..ae70a7f 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -26,7 +26,6 @@
#include <media/AudioTimestamp.h>
#include <media/MediaMetricsItem.h>
#include <media/Modulo.h>
-#include <media/MicrophoneInfo.h>
#include <media/RecordingActivityTracker.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
@@ -575,10 +574,11 @@
/* Get the flags */
audio_input_flags_t getFlags() const { AutoMutex _l(mLock); return mFlags; }
- /* Get active microphones. A empty vector of MicrophoneInfo will be passed as a parameter,
+ /* Get active microphones. A empty vector of MicrophoneInfoFw will be passed as a parameter,
* the data will be filled when querying the hal.
*/
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
/* Set the Microphone direction (for processing purposes).
*/
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 3b7cc39..543ce00 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -28,6 +28,7 @@
#include <android/media/BnAudioPolicyServiceClient.h>
#include <android/media/INativeSpatializerCallback.h>
#include <android/media/ISpatializer.h>
+#include <android/media/MicrophoneInfoFw.h>
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
#include <android/media/audio/common/AudioPort.h>
@@ -38,7 +39,6 @@
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <media/AudioIoDescriptor.h>
-#include <media/MicrophoneInfo.h>
#include <system/audio.h>
#include <system/audio_effect.h>
#include <system/audio_policy.h>
@@ -428,7 +428,7 @@
static float getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device);
- static status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ static status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
static status_t getHwOffloadFormatsSupportedForBluetoothMedia(
audio_devices_t device, std::vector<audio_format_t> *formats);
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 1177e5a..25b5414 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -32,7 +32,6 @@
#include <system/audio_effect.h>
#include <system/audio_policy.h>
#include <utils/String8.h>
-#include <media/MicrophoneInfo.h>
#include <map>
#include <string>
#include <vector>
@@ -339,7 +338,7 @@
virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
/* List available microphones and their characteristics */
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+ virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
@@ -463,7 +462,7 @@
status_t audioPolicyReady() override;
size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
- status_t getMicrophones(std::vector<media::MicrophoneInfo>* microphones) override;
+ status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) override;
status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
status_t updateSecondaryOutputs(
@@ -688,7 +687,7 @@
Status systemReady() override;
Status audioPolicyReady() override;
Status frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) override;
- Status getMicrophones(std::vector<media::MicrophoneInfoData>* _aidl_return) override;
+ Status getMicrophones(std::vector<media::MicrophoneInfoFw>* _aidl_return) override;
Status setAudioHalPids(const std::vector<int32_t>& pids) override;
Status setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
Status updateSecondaryOutputs(
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index dcb6c25..2189521 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -39,6 +39,7 @@
"libaudioclient_aidl_conversion",
"libaudio_aidl_conversion_common_cpp",
"audioclient-types-aidl-cpp",
+ "av-types-aidl-cpp",
"libstagefright_foundation",
],
}
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 5fbd090..e2216a0 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -47,6 +47,8 @@
using media::audio::common::AudioStandard;
using media::audio::common::ExtraAudioDescriptor;
using media::audio::common::Int;
+using media::audio::common::MicrophoneDynamicInfo;
+using media::audio::common::MicrophoneInfo;
using media::audio::common::PcmType;
// Provide value printers for types generated from AIDL
@@ -663,3 +665,73 @@
}
}
INSTANTIATE_TEST_SUITE_P(AudioGain, AudioGainTest, testing::Values(true, false));
+
+TEST(AudioMicrophoneInfoFw, Aidl2Legacy2Aidl) {
+ media::MicrophoneInfoFw initial{};
+ // HALs must return at least 1 element in channelMapping. The zero value is 'UNUSED'.
+ initial.dynamic.channelMapping.resize(1);
+ auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+
+TEST(AudioMicrophoneInfoFw, UnknownValues) {
+ {
+ media::MicrophoneInfoFw initial;
+ initial.dynamic.channelMapping.resize(1);
+ initial.info.indexInTheGroup = MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN;
+ auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack =
+ legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+ }
+ for (const auto f : {&audio_microphone_characteristic_t::sensitivity,
+ &audio_microphone_characteristic_t::max_spl,
+ &audio_microphone_characteristic_t::min_spl}) {
+ audio_microphone_characteristic_t mic{};
+ if (f == &audio_microphone_characteristic_t::sensitivity) {
+ mic.*f = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+ } else {
+ mic.*f = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ }
+ auto aidl = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ ASSERT_TRUE(aidl.ok());
+ EXPECT_FALSE(aidl.value().info.sensitivity.has_value());
+ }
+ for (const auto f : {&audio_microphone_characteristic_t::geometric_location,
+ &audio_microphone_characteristic_t::orientation}) {
+ for (const auto c : {&audio_microphone_coordinate::x, &audio_microphone_coordinate::y,
+ &audio_microphone_coordinate::z}) {
+ audio_microphone_characteristic_t mic{};
+ mic.*f.*c = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ ASSERT_TRUE(conv.ok());
+ const auto& aidl = conv.value();
+ if (f == &audio_microphone_characteristic_t::geometric_location) {
+ EXPECT_FALSE(aidl.info.position.has_value());
+ EXPECT_TRUE(aidl.info.orientation.has_value());
+ } else {
+ EXPECT_TRUE(aidl.info.position.has_value());
+ EXPECT_FALSE(aidl.info.orientation.has_value());
+ }
+ }
+ }
+}
+
+TEST(AudioMicrophoneInfoFw, ChannelMapping) {
+ audio_microphone_characteristic_t mic{};
+ mic.channel_mapping[1] = AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT;
+ mic.channel_mapping[3] = AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED;
+ auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ ASSERT_TRUE(conv.ok());
+ const auto& aidl = conv.value();
+ EXPECT_EQ(4, aidl.dynamic.channelMapping.size());
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::UNUSED, aidl.dynamic.channelMapping[0]);
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::DIRECT, aidl.dynamic.channelMapping[1]);
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::UNUSED, aidl.dynamic.channelMapping[2]);
+ EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::PROCESSED, aidl.dynamic.channelMapping[3]);
+}
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
index 2c5fcd7..19d1abc 100644
--- a/media/libaudioclient/tests/audiorouting_tests.cpp
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -73,7 +73,6 @@
}
}
ap->stop();
- ap->getAudioTrackHandle()->removeAudioDeviceCallback(cb);
}
}
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index aed847c..b7a2d60 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -49,12 +49,12 @@
void TearDown() override {
if (mPlayback) {
mPlayback->stop();
- mPlayback->getAudioTrackHandle()->removeAudioDeviceCallback(mCbPlayback);
+ mCbPlayback.clear();
mPlayback.clear();
}
if (mCapture) {
mCapture->stop();
- mCapture->getAudioRecordHandle()->removeAudioDeviceCallback(mCbRecord);
+ mCbRecord.clear();
mCapture.clear();
}
}
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
index 0a8188f..202a400 100644
--- a/media/libaudiofoundation/AudioContainers.cpp
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -77,6 +77,13 @@
return audioDeviceOutLeAudioUnicastSet;
}
+const DeviceTypeSet& getAudioDeviceOutLeAudioBroadcastSet() {
+ static const DeviceTypeSet audioDeviceOutLeAudioUnicastSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_OUT_BLE_BROADCAST_ARRAY),
+ std::end(AUDIO_DEVICE_OUT_BLE_BROADCAST_ARRAY));
+ return audioDeviceOutLeAudioUnicastSet;
+}
+
std::string deviceTypesToString(const DeviceTypeSet &deviceTypes) {
if (deviceTypes.empty()) {
return "Empty device types";
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 6c01e29..3f79ea2 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -42,6 +42,7 @@
const DeviceTypeSet& getAudioDeviceInAllUsbSet();
const DeviceTypeSet& getAudioDeviceOutAllBleSet();
const DeviceTypeSet& getAudioDeviceOutLeAudioUnicastSet();
+const DeviceTypeSet& getAudioDeviceOutLeAudioBroadcastSet();
template<typename T>
static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
index 84ac64c..f88915d 100644
--- a/media/libaudiohal/FactoryHal.cpp
+++ b/media/libaudiohal/FactoryHal.cpp
@@ -105,12 +105,12 @@
bool hasAidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
const std::string name = interface.first + "." + interface.second + "/default";
- AIBinder* binder = AServiceManager_checkService(name.c_str());
- if (binder == nullptr) {
- ALOGW("%s Service %s doesn't exist", __func__, name.c_str());
+ const bool isDeclared = AServiceManager_isDeclared(name.c_str());
+ if (!isDeclared) {
+ ALOGW("%s %s: false", __func__, name.c_str());
return false;
}
- ALOGI("%s AIDL Service %s exist: %s", __func__, name.c_str(), version.toString().c_str());
+ ALOGI("%s %s: true, version %s", __func__, name.c_str(), version.toString().c_str());
return true;
}
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index e676850..3f19219 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -55,6 +55,7 @@
shared_libs: [
"audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libaudiofoundation",
"libaudioutils",
"libbase",
@@ -71,6 +72,9 @@
"libaudioclient_headers",
"libaudiohal_headers"
],
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_export_shared",
+ ],
export_shared_lib_headers: [
"libfmq",
@@ -241,7 +245,7 @@
"libaudiohal_default",
"latest_android_hardware_audio_common_ndk_shared",
"latest_android_hardware_audio_core_ndk_shared",
- "latest_android_hardware_audio_effect_ndk_static",
+ "latest_android_hardware_audio_effect_ndk_shared",
"latest_android_media_audio_common_types_ndk_shared",
],
srcs: [
@@ -256,6 +260,16 @@
"effectsAidlConversion/AidlConversionBassBoost.cpp",
"effectsAidlConversion/AidlConversionDownmix.cpp",
"effectsAidlConversion/AidlConversionDynamicsProcessing.cpp",
+ "effectsAidlConversion/AidlConversionEnvReverb.cpp",
+ "effectsAidlConversion/AidlConversionEq.cpp",
+ "effectsAidlConversion/AidlConversionHapticGenerator.cpp",
+ "effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp",
+ "effectsAidlConversion/AidlConversionNoiseSuppression.cpp",
+ "effectsAidlConversion/AidlConversionPresetReverb.cpp",
+ "effectsAidlConversion/AidlConversionSpatializer.cpp",
+ "effectsAidlConversion/AidlConversionVendorExtension.cpp",
+ "effectsAidlConversion/AidlConversionVirtualizer.cpp",
+ "effectsAidlConversion/AidlConversionVisualizer.cpp",
"EffectsFactoryHalAidl.cpp",
"EffectsFactoryHalEntry.cpp",
"StreamHalAidl.cpp",
@@ -268,9 +282,9 @@
"libbinder_ndk",
"libaudio_aidl_conversion_common_ndk",
"libaudio_aidl_conversion_effect_ndk",
+ "libaudioaidlcommon",
],
header_libs: [
- "libaudio_aidl_conversion_common_util_ndk",
"libaudio_system_headers",
],
cflags: [
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index a7537c1..697135f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -15,15 +15,19 @@
*/
#define LOG_TAG "DeviceHalAidl"
+// #define LOG_NDEBUG 0
#include <algorithm>
#include <forward_list>
+#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
+#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionUtil.h>
#include <mediautils/TimeCheck.h>
+#include <Utils.h>
#include <utils/Log.h>
#include "DeviceHalAidl.h"
@@ -32,11 +36,16 @@
using aidl::android::aidl_utils::statusTFromBinderStatus;
using aidl::android::media::audio::common::AudioConfig;
using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioLatencyMode;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::Int;
@@ -46,6 +55,9 @@
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::ITelephony;
using aidl::android::hardware::audio::core::StreamDescriptor;
+using android::hardware::audio::common::getFrameSizeInBytes;
+using android::hardware::audio::common::isBitPositionFlagSet;
+using android::hardware::audio::common::makeBitPositionFlagMask;
namespace android {
@@ -86,6 +98,21 @@
__func__, mInstance.c_str());
std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
[](const auto& p) { return std::make_pair(p.id, p); });
+ mDefaultInputPortId = mDefaultOutputPortId = -1;
+ const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+ for (const auto& pair : mPorts) {
+ const auto& p = pair.second;
+ if (p.ext.getTag() == AudioPortExt::Tag::device &&
+ (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
+ if (p.flags.getTag() == AudioIoFlags::Tag::input) {
+ mDefaultInputPortId = p.id;
+ } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
+ mDefaultOutputPortId = p.id;
+ }
+ }
+ }
+ ALOGI("%s: module %s default port ids: input %d, output %d",
+ __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
std::vector<AudioPortConfig> portConfigs;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
@@ -180,14 +207,6 @@
return OK;
}
-status_t DeviceHalAidl::getInputBufferSize(
- const struct audio_config* config __unused, size_t* size __unused) {
- TIME_CHECK();
- if (!mModule) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
-}
-
namespace {
class Cleanup {
@@ -221,10 +240,33 @@
void disarmAll() { for (auto& c : *this) c.disarm(); }
};
+status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (size == nullptr) return BAD_VALUE;
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
+ AudioDevice aidlDevice;
+ aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
+ AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
+ AudioPortConfig mixPortConfig;
+ Cleanups cleanups;
+ audio_config writableConfig = *config;
+ int32_t nominalLatency;
+ RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, &writableConfig,
+ &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ *size = aidlConfig.frameCount *
+ getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
+ // Do not disarm cleanups to release temporary port configs.
+ return OK;
+}
+
status_t DeviceHalAidl::prepareToOpenStream(
int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
struct audio_config* config,
- Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig) {
+ Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
+ int32_t* nominalLatency) {
const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
// Find / create AudioPortConfigs for the device port and the mix port,
// then find / create a patch between them, and open a stream on the mix port.
@@ -251,6 +293,7 @@
if (created) {
cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
}
+ *nominalLatency = patch.latenciesMs[0];
if (aidlConfig->frameCount <= 0) {
aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
}
@@ -259,11 +302,129 @@
return OK;
}
+namespace {
+
+class StreamCallbackBase {
+ protected:
+ explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
+ public:
+ void* getCookie() const { return mCookie; }
+ void setCookie(void* cookie) { mCookie = cookie; }
+ sp<CallbackBroker> getBroker() const {
+ if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
+ return nullptr;
+ }
+ private:
+ const wp<CallbackBroker> mBroker;
+ std::atomic<void*> mCookie;
+};
+
+template<class C>
+class StreamCallbackBaseHelper {
+ protected:
+ explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
+ sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
+ using CbRef = const sp<C>&;
+ ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
+ if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
+ return ndk::ScopedAStatus::ok();
+ }
+ private:
+ const StreamCallbackBase& mBase;
+};
+
+template<>
+sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutCallback(cookie);
+ return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceEventCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
+ return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceLatencyModeCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
+ return nullptr;
+}
+
+/*
+Note on the callback ownership.
+
+In the Binder ownership model, the server implementation is kept alive
+as long as there is any client (proxy object) alive. This is done by
+incrementing the refcount of the server-side object by the Binder framework.
+When it detects that the last client is gone, it decrements the refcount back.
+
+Thus, it is not needed to keep any references to StreamCallback on our
+side (after we have sent an instance to the client), because we are
+the server-side. The callback object will be kept alive as long as the HAL server
+holds a strong ref to IStreamCallback proxy.
+*/
+
+class OutputStreamCallbackAidl : public StreamCallbackBase,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
+ public ::aidl::android::hardware::audio::core::BnStreamCallback {
+ public:
+ explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
+ : StreamCallbackBase(broker),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
+ *static_cast<StreamCallbackBase*>(this)) {}
+ ndk::ScopedAStatus onTransferReady() override {
+ return runCb([](CbRef cb) { cb->onWriteReady(); });
+ }
+ ndk::ScopedAStatus onError() override {
+ return runCb([](CbRef cb) { cb->onError(); });
+ }
+ ndk::ScopedAStatus onDrainReady() override {
+ return runCb([](CbRef cb) { cb->onDrainReady(); });
+ }
+};
+
+class OutputStreamEventCallbackAidl :
+ public StreamCallbackBase,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
+ public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
+ public:
+ explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
+ : StreamCallbackBase(broker),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
+ *static_cast<StreamCallbackBase*>(this)),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
+ *static_cast<StreamCallbackBase*>(this)) {}
+ ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
+ std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
+ return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
+ [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
+ }
+ ndk::ScopedAStatus onRecommendedLatencyModeChanged(
+ const std::vector<AudioLatencyMode>& in_modes) override {
+ auto halModes = VALUE_OR_FATAL(
+ ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
+ in_modes,
+ ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
+ return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
+ [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
+ }
+};
+
+} // namespace
+
status_t DeviceHalAidl::openOutputStream(
audio_io_handle_t handle, audio_devices_t devices,
audio_output_flags_t flags, struct audio_config* config,
const char* address,
sp<StreamOutHalInterface>* outStream) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
if (!outStream || !config) {
return BAD_VALUE;
}
@@ -280,15 +441,41 @@
AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
AudioPortConfig mixPortConfig;
Cleanups cleanups;
+ int32_t nominalLatency;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
- &cleanups, &aidlConfig, &mixPortConfig));
+ &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
args.portConfigId = mixPortConfig.id;
- args.offloadInfo = aidlConfig.offloadInfo;
+ const bool isOffload = isBitPositionFlagSet(
+ aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
+ std::shared_ptr<OutputStreamCallbackAidl> streamCb;
+ if (isOffload) {
+ streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
+ }
+ auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
+ if (isOffload) {
+ args.offloadInfo = aidlConfig.offloadInfo;
+ args.callback = streamCb;
+ }
args.bufferSizeFrames = aidlConfig.frameCount;
+ args.eventCallback = eventCb;
::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
- *outStream = sp<StreamOutHalAidl>::make(*config, std::move(ret.desc), std::move(ret.stream));
+ StreamContextAidl context(ret.desc);
+ if (!context.isValid()) {
+ ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
+ __func__, ret.desc.toString().c_str());
+ return NO_INIT;
+ }
+ *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
+ std::move(ret.stream), this /*callbackBroker*/);
+ void* cbCookie = (*outStream).get();
+ {
+ std::lock_guard l(mLock);
+ mCallbacks.emplace(cbCookie, Callbacks{});
+ }
+ if (streamCb) streamCb->setCookie(cbCookie);
+ eventCb->setCookie(cbCookie);
cleanups.disarmAll();
return OK;
}
@@ -299,6 +486,7 @@
const char* address, audio_source_t source,
audio_devices_t outputDevice, const char* outputDeviceAddress,
sp<StreamInHalInterface>* inStream) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
if (!inStream || !config) {
return BAD_VALUE;
}
@@ -317,8 +505,9 @@
::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
AudioPortConfig mixPortConfig;
Cleanups cleanups;
+ int32_t nominalLatency;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
- &cleanups, &aidlConfig, &mixPortConfig));
+ &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
args.portConfigId = mixPortConfig.id;
RecordTrackMetadata aidlTrackMetadata{
@@ -332,7 +521,14 @@
args.bufferSizeFrames = aidlConfig.frameCount;
::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
- *inStream = sp<StreamInHalAidl>::make(*config, std::move(ret.desc), std::move(ret.stream));
+ StreamContextAidl context(ret.desc);
+ if (!context.isValid()) {
+ ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
+ __func__, ret.desc.toString().c_str());
+ return NO_INIT;
+ }
+ *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
+ std::move(ret.stream));
cleanups.disarmAll();
return OK;
}
@@ -347,6 +543,7 @@
unsigned int num_sinks,
const struct audio_port_config* sinks,
audio_patch_handle_t* patch) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mModule) return NO_INIT;
if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
@@ -389,6 +586,9 @@
aidlPatch.sinkPortConfigIds.clear();
}
}
+ ALOGD("%s: sources: %s, sinks: %s",
+ __func__, ::android::internal::ToString(aidlSources).c_str(),
+ ::android::internal::ToString(aidlSinks).c_str());
auto fillPortConfigs = [&](
const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
for (const auto& s : configs) {
@@ -432,6 +632,7 @@
}
status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mModule) return NO_INIT;
auto idMapIt = mFwkHandles.find(patch);
@@ -529,22 +730,42 @@
return INVALID_OPERATION;
}
-status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
- AudioPortConfig* appliedPortConfig) {
+bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
+ if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
+ return p.ext.get<AudioPortExt::Tag::device>().device == device;
+}
+
+bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
+ if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
+ if (device.type.type == AudioDeviceType::IN_DEFAULT) {
+ return p.portId == mDefaultInputPortId;
+ } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
+ return p.portId == mDefaultOutputPortId;
+ }
+ return p.ext.get<AudioPortExt::Tag::device>().device == device;
+}
+
+status_t DeviceHalAidl::createPortConfig(
+ const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
TIME_CHECK();
+ AudioPortConfig appliedPortConfig;
bool applied = false;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
- requestedPortConfig, appliedPortConfig, &applied)));
+ requestedPortConfig, &appliedPortConfig, &applied)));
if (!applied) {
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
- *appliedPortConfig, appliedPortConfig, &applied)));
+ appliedPortConfig, &appliedPortConfig, &applied)));
if (!applied) {
ALOGE("%s: module %s did not apply suggested config %s",
- __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
+ __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
return NO_INIT;
}
}
- mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
+ auto id = appliedPortConfig.id;
+ auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
+ LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
+ __func__, it->first);
+ *result = it;
return OK;
}
@@ -591,10 +812,7 @@
}
AudioPortConfig requestedPortConfig;
requestedPortConfig.portId = portsIt->first;
- AudioPortConfig appliedPortConfig;
- RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
- portConfigIt = mPortConfigs.insert(
- mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
*created = true;
} else {
*created = false;
@@ -604,26 +822,48 @@
}
status_t DeviceHalAidl::findOrCreatePortConfig(
- const AudioConfig& config, const AudioIoFlags& flags, int32_t ioHandle,
+ const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
AudioPortConfig* portConfig, bool* created) {
+ // These flags get removed one by one in this order when retrying port finding.
+ static const std::vector<AudioInputFlags> kOptionalInputFlags{
+ AudioInputFlags::FAST, AudioInputFlags::RAW };
auto portConfigIt = findPortConfig(config, flags, ioHandle);
- if (portConfigIt == mPortConfigs.end()) {
- auto portsIt = findPort(config, flags);
+ if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
+ auto optionalInputFlagsIt = kOptionalInputFlags.begin();
+ AudioIoFlags matchFlags = flags.value();
+ auto portsIt = findPort(config, matchFlags);
+ while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
+ && optionalInputFlagsIt != kOptionalInputFlags.end()) {
+ if (!isBitPositionFlagSet(
+ matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
+ ++optionalInputFlagsIt;
+ continue;
+ }
+ matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
+ ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
+ portsIt = findPort(config, matchFlags);
+ ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
+ "retried with flags %s", __func__, config.toString().c_str(),
+ flags.value().toString().c_str(), mInstance.c_str(),
+ matchFlags.toString().c_str());
+ }
if (portsIt == mPorts.end()) {
ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
- __func__, config.toString().c_str(), flags.toString().c_str(),
+ __func__, config.toString().c_str(), matchFlags.toString().c_str(),
mInstance.c_str());
return BAD_VALUE;
}
AudioPortConfig requestedPortConfig;
requestedPortConfig.portId = portsIt->first;
setPortConfigFromConfig(&requestedPortConfig, config);
- AudioPortConfig appliedPortConfig;
- RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
- appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
- portConfigIt = mPortConfigs.insert(
- mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
+ requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
*created = true;
+ } else if (!flags.has_value()) {
+ ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
+ "and was not created as flags are not specified",
+ __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
+ return BAD_VALUE;
} else {
*created = false;
}
@@ -637,14 +877,14 @@
if (requestedPortConfig.ext.getTag() == Tag::mix) {
if (const auto& p = requestedPortConfig;
!p.sampleRate.has_value() || !p.channelMask.has_value() ||
- !p.format.has_value() || !p.flags.has_value()) {
+ !p.format.has_value()) {
ALOGW("%s: provided mix port config is not fully specified: %s",
__func__, p.toString().c_str());
return BAD_VALUE;
}
AudioConfig config;
setConfigFromPortConfig(&config, requestedPortConfig);
- return findOrCreatePortConfig(config, requestedPortConfig.flags.value(),
+ return findOrCreatePortConfig(config, requestedPortConfig.flags,
requestedPortConfig.ext.get<Tag::mix>().handle, portConfig, created);
} else if (requestedPortConfig.ext.getTag() == Tag::device) {
return findOrCreatePortConfig(
@@ -668,47 +908,39 @@
}
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
- using Tag = AudioPortExt::Tag;
+ if (device.type.type == AudioDeviceType::IN_DEFAULT) {
+ return mPorts.find(mDefaultInputPortId);
+ } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
+ return mPorts.find(mDefaultOutputPortId);
+ }
return std::find_if(mPorts.begin(), mPorts.end(),
- [&](const auto& pair) {
- const auto& p = pair.second;
- return p.ext.getTag() == Tag::device &&
- p.ext.template get<Tag::device>().device == device; });
+ [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
}
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
const AudioConfig& config, const AudioIoFlags& flags) {
- using Tag = AudioPortExt::Tag;
- return std::find_if(mPorts.begin(), mPorts.end(),
- [&](const auto& pair) {
- const auto& p = pair.second;
- return p.ext.getTag() == Tag::mix &&
- p.flags == flags &&
- std::find_if(p.profiles.begin(), p.profiles.end(),
- [&](const auto& prof) {
- return prof.format == config.base.format &&
- std::find(prof.channelMasks.begin(),
- prof.channelMasks.end(),
- config.base.channelMask) !=
- prof.channelMasks.end() &&
- std::find(prof.sampleRates.begin(),
- prof.sampleRates.end(),
- config.base.sampleRate) !=
- prof.sampleRates.end();
- }) != p.profiles.end(); });
+ auto matcher = [&](const auto& pair) {
+ const auto& p = pair.second;
+ return p.ext.getTag() == AudioPortExt::Tag::mix &&
+ p.flags == flags &&
+ std::find_if(p.profiles.begin(), p.profiles.end(),
+ [&](const auto& prof) {
+ return prof.format == config.base.format &&
+ std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
+ config.base.channelMask) != prof.channelMasks.end() &&
+ std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
+ config.base.sampleRate) != prof.sampleRates.end();
+ }) != p.profiles.end(); };
+ return std::find_if(mPorts.begin(), mPorts.end(), matcher);
}
DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
- using Tag = AudioPortExt::Tag;
return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
- [&](const auto& pair) {
- const auto& p = pair.second;
- return p.ext.getTag() == Tag::device &&
- p.ext.template get<Tag::device>().device == device; });
+ [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
}
DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
- const AudioConfig& config, const AudioIoFlags& flags, int32_t ioHandle) {
+ const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
using Tag = AudioPortExt::Tag;
return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
[&](const auto& pair) {
@@ -720,7 +952,7 @@
__func__, p.toString().c_str());
return p.ext.getTag() == Tag::mix &&
isConfigEqualToPortConfig(config, p) &&
- p.flags.value() == flags &&
+ (!flags.has_value() || p.flags.value() == flags.value()) &&
p.ext.template get<Tag::mix>().handle == ioHandle; });
}
/*
@@ -778,4 +1010,55 @@
ALOGE("%s: port config id %d not found", __func__, portConfigId);
}
+void DeviceHalAidl::clearCallbacks(void* cookie) {
+ std::lock_guard l(mLock);
+ mCallbacks.erase(cookie);
+}
+
+sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::out);
+}
+
+void DeviceHalAidl::setStreamOutCallback(
+ void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::out, cb);
+}
+
+sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
+ void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::event);
+}
+
+void DeviceHalAidl::setStreamOutEventCallback(
+ void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::event, cb);
+}
+
+sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
+ void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::latency);
+}
+
+void DeviceHalAidl::setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::latency, cb);
+}
+
+template<class C>
+sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
+ std::lock_guard l(mLock);
+ if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+ return ((it->second).*field).promote();
+ }
+ return nullptr;
+}
+template<class C>
+void DeviceHalAidl::setCallbackImpl(
+ void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
+ std::lock_guard l(mLock);
+ if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+ (it->second).*field = cb;
+ }
+}
+
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 95a8219..5e6f662 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -21,6 +21,7 @@
#include <vector>
#include <aidl/android/hardware/audio/core/BpModule.h>
+#include <android-base/thread_annotations.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -28,7 +29,35 @@
namespace android {
-class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl {
+class StreamOutHalInterfaceCallback;
+class StreamOutHalInterfaceEventCallback;
+class StreamOutHalInterfaceLatencyModeCallback;
+
+// The role of the broker is to connect AIDL callback interface implementations
+// with StreamOut callback implementations. Since AIDL requires all callbacks
+// to be provided upfront, while libaudiohal interfaces allow late registration,
+// there is a need to coordinate the matching process.
+class CallbackBroker : public virtual RefBase {
+ public:
+ virtual ~CallbackBroker() = default;
+ // The cookie is always the stream instance pointer. We don't use weak pointers to avoid extra
+ // costs on reference counting. The stream cleans up related entries on destruction. Since
+ // access to the callbacks map is synchronized, the possibility for pointer aliasing due to
+ // allocation of a new stream at the address of previously deleted stream is avoided.
+ virtual void clearCallbacks(void* cookie) = 0;
+ virtual sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) = 0;
+ virtual void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>&) = 0;
+ virtual sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) = 0;
+ virtual void setStreamOutEventCallback(void* cookie,
+ const sp<StreamOutHalInterfaceEventCallback>&) = 0;
+ virtual sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+ void* cookie) = 0;
+ virtual void setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>&) = 0;
+};
+
+class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
+ public CallbackBroker {
public:
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
@@ -123,6 +152,12 @@
private:
friend class sp<DeviceHalAidl>;
+
+ struct Callbacks { // No need to use `atomic_wp` because access is serialized.
+ wp<StreamOutHalInterfaceCallback> out;
+ wp<StreamOutHalInterfaceEventCallback> event;
+ wp<StreamOutHalInterfaceLatencyModeCallback> latency;
+ };
using Patches = std::map<int32_t /*patch ID*/,
::aidl::android::hardware::audio::core::AudioPatch>;
using PortConfigs = std::map<int32_t /*port config ID*/,
@@ -138,9 +173,13 @@
~DeviceHalAidl() override = default;
+ bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
+ const ::aidl::android::media::audio::common::AudioPort& p);
+ bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
+ const ::aidl::android::media::audio::common::AudioPortConfig& p);
status_t createPortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
- ::aidl::android::media::audio::common::AudioPortConfig* appliedPortConfig);
+ PortConfigs::iterator* result);
status_t findOrCreatePatch(
const std::set<int32_t>& sourcePortConfigIds,
const std::set<int32_t>& sinkPortConfigIds,
@@ -154,7 +193,7 @@
bool* created);
status_t findOrCreatePortConfig(
const ::aidl::android::media::audio::common::AudioConfig& config,
- const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+ const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle,
::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
status_t findOrCreatePortConfig(
@@ -170,7 +209,7 @@
const ::aidl::android::media::audio::common::AudioDevice& device);
PortConfigs::iterator findPortConfig(
const ::aidl::android::media::audio::common::AudioConfig& config,
- const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+ const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle);
// Currently unused but may be useful for implementing setAudioPortConfig
// PortConfigs::iterator findPortConfig(
@@ -182,16 +221,36 @@
struct audio_config* config,
Cleanups* cleanups,
::aidl::android::media::audio::common::AudioConfig* aidlConfig,
- ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig);
+ ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
+ int32_t* nominalLatency);
void resetPatch(int32_t patchId);
void resetPortConfig(int32_t portConfigId);
+ // CallbackBroker implementation
+ void clearCallbacks(void* cookie) override;
+ sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) override;
+ void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) override;
+ sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) override;
+ void setStreamOutEventCallback(void* cookie,
+ const sp<StreamOutHalInterfaceEventCallback>& cb) override;
+ sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+ void* cookie) override;
+ void setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) override;
+ // Implementation helpers.
+ template<class C> sp<C> getCallbackImpl(void* cookie, wp<C> Callbacks::* field);
+ template<class C> void setCallbackImpl(void* cookie, wp<C> Callbacks::* field, const sp<C>& cb);
+
const std::string mInstance;
const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
Ports mPorts;
+ int32_t mDefaultInputPortId = -1;
+ int32_t mDefaultOutputPortId = -1;
PortConfigs mPortConfigs;
Patches mPatches;
- std::map<audio_patch_handle_t, int32_t /* patch ID */> mFwkHandles;
+ std::map<audio_patch_handle_t, int32_t /*patch ID*/> mFwkHandles;
+ std::mutex mLock;
+ std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
};
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index da89e20..dc47d67 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -21,8 +21,10 @@
//#define LOG_NDEBUG 0
#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_visualizer.h>
#include <utils/Log.h>
@@ -36,6 +38,8 @@
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::Parameter;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioMode;
+using ::aidl::android::media::audio::common::AudioSource;
using android::effect::utils::EffectParamReader;
using android::effect::utils::EffectParamWriter;
@@ -51,11 +55,15 @@
{EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
{EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
{EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
+ {EFFECT_CMD_SET_AUDIO_SOURCE, &EffectConversionHelperAidl::handleSetAudioSource},
{EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
{EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
{EFFECT_CMD_SET_VOLUME, &EffectConversionHelperAidl::handleSetVolume},
{EFFECT_CMD_OFFLOAD, &EffectConversionHelperAidl::handleSetOffload},
- {EFFECT_CMD_FIRST_PROPRIETARY, &EffectConversionHelperAidl::handleFirstPriority}};
+ {EFFECT_CMD_FIRST_PROPRIETARY, &EffectConversionHelperAidl::handleFirstPriority},
+ // Only visualizer support these commands
+ {VISUALIZER_CMD_CAPTURE, &EffectConversionHelperAidl::handleVisualizerCapture},
+ {VISUALIZER_CMD_MEASURE, &EffectConversionHelperAidl::handleVisualizerMeasure}};
EffectConversionHelperAidl::EffectConversionHelperAidl(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
@@ -101,7 +109,10 @@
return BAD_VALUE;
}
- return *(status_t*)pReplyData = setParameter(reader);
+ status_t ret = setParameter(reader);
+ EffectParamWriter writer(*(effect_param_t*)pReplyData);
+ writer.setStatus(ret);
+ return *(status_t*)pReplyData = ret;
}
status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
@@ -111,10 +122,8 @@
}
const auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
- if (!reader.validateCmdSize(cmdSize) ||
- *replySize < sizeof(effect_param_t) + reader.getParameterSize()) {
- ALOGE("%s illegal param %s, replySize %u", __func__, reader.toString().c_str(),
- *replySize);
+ if (*replySize < sizeof(effect_param_t) + reader.getParameterSize()) {
+ ALOGE("%s illegal param %s, replySize %u", __func__, reader.toString().c_str(), *replySize);
return BAD_VALUE;
}
@@ -123,32 +132,23 @@
auto writer = EffectParamWriter(*(effect_param_t*)pReplyData);
status_t ret = getParameter(writer);
writer.finishValueWrite();
+ writer.setStatus(ret);
*replySize = writer.getTotalSize();
+ if (ret != OK) {
+ ALOGE("%s error ret %d, %s", __func__, ret, writer.toString().c_str());
+ }
return ret;
}
-status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const void* pCmdData,
+status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize,
+ const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
if (!replySize || *replySize != sizeof(int) || !pReplyData ||
cmdSize != sizeof(effect_config_t)) {
return BAD_VALUE;
}
- const auto& legacyConfig = static_cast<const effect_config_t*>(pCmdData);
- // already open, apply latest settings
- Parameter::Common common;
- common.input.base =
- VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
- legacyConfig->inputCfg, true /* isInput */));
- common.output.base =
- VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
- legacyConfig->outputCfg, false /* isInput */));
- common.session = mSessionId;
- common.ioHandle = mIoId;
- // TODO: add access mode support
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mEffect->setParameter(Parameter::make<Parameter::common>(common))));
- mCommon = common;
+ // TODO: need to implement setConfig with setParameter(common)
return *static_cast<int32_t*>(pReplyData) = OK;
}
@@ -178,7 +178,7 @@
status_t EffectConversionHelperAidl::handleReset(uint32_t cmdSize __unused,
const void* pCmdData __unused, uint32_t* replySize,
void* pReplyData) {
- if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
+ if (!replySize || !pReplyData) {
ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
return BAD_VALUE;
}
@@ -187,9 +187,9 @@
}
status_t EffectConversionHelperAidl::handleEnable(uint32_t cmdSize __unused,
- const void* pCmdData __unused, uint32_t* replySize,
- void* pReplyData) {
- if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
+ const void* pCmdData __unused,
+ uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData) {
ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
return BAD_VALUE;
}
@@ -200,7 +200,7 @@
status_t EffectConversionHelperAidl::handleDisable(uint32_t cmdSize __unused,
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
- if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
+ if (!replySize || !pReplyData) {
ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
return BAD_VALUE;
}
@@ -208,10 +208,40 @@
return statusTFromBinderStatus(mEffect->command(CommandId::STOP));
}
+status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+ pReplyData);
+ return BAD_VALUE;
+ }
+
+ audio_source_t source = *(audio_source_t*)pCmdData;
+ AudioSource aidlSource =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mEffect->setParameter(Parameter::make<Parameter::source>(aidlSource))));
+ return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
+status_t EffectConversionHelperAidl::handleSetAudioMode(uint32_t cmdSize, const void* pCmdData,
+ uint32_t* replySize, void* pReplyData) {
+ if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+ pReplyData);
+ return BAD_VALUE;
+ }
+ audio_mode_t mode = *(audio_mode_t *)pCmdData;
+ AudioMode aidlMode =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mEffect->setParameter(Parameter::make<Parameter::mode>(aidlMode))));
+ return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
- if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize ||
- *replySize != sizeof(effect_config_t) || !pReplyData) {
+ if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
pReplyData);
return BAD_VALUE;
@@ -223,11 +253,9 @@
mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
return *static_cast<int32_t*>(pReplyData) = OK;
}
-
status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
- if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData || !replySize ||
- *replySize != sizeof(effect_config_t) || !pReplyData) {
+ if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
pReplyData);
return BAD_VALUE;
@@ -241,8 +269,7 @@
status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
- if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize ||
- *replySize != sizeof(effect_config_t) || !pReplyData) {
+ if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize || !pReplyData) {
ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
pReplyData);
return BAD_VALUE;
@@ -254,7 +281,7 @@
status_t EffectConversionHelperAidl::handleFirstPriority(uint32_t cmdSize __unused,
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
- if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
+ if (!replySize || !pReplyData) {
ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
return BAD_VALUE;
}
@@ -263,5 +290,45 @@
return OK;
}
+status_t EffectConversionHelperAidl::handleVisualizerCapture(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ const auto& uuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+ if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+ ALOGE("%s visualizer command not supported by %s", __func__,
+ mDesc.common.id.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ return visualizerCapture(replySize, pReplyData);
+}
+
+status_t EffectConversionHelperAidl::handleVisualizerMeasure(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ const auto& uuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+ if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+ ALOGE("%s visualizer command not supported by %s", __func__,
+ mDesc.common.id.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ return visualizerMeasure(replySize, pReplyData);
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 490a1dc..37ca75d 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -82,6 +82,10 @@
void* pReplyData);
status_t handleReset(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
+ status_t handleSetAudioSource(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleSetAudioMode(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
status_t handleSetDevice(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
status_t handleSetVolume(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
@@ -90,10 +94,20 @@
void* pReplyData);
status_t handleFirstPriority(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
+ status_t handleVisualizerCapture(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleVisualizerMeasure(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
// implemented by conversion of each effect
virtual status_t setParameter(utils::EffectParamReader& param) = 0;
virtual status_t getParameter(utils::EffectParamWriter& param) = 0;
+ virtual status_t visualizerCapture(uint32_t* replySize __unused, void* pReplyData __unused) {
+ return BAD_VALUE;
+ }
+ virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
+ return BAD_VALUE;
+ }
};
} // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 08040f3..8fa301a 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include <memory>
#define LOG_TAG "EffectHalAidl"
//#define LOG_NDEBUG 0
+#include <memory>
+
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionEffect.h>
@@ -25,19 +26,11 @@
#include <media/audiohal/AudioEffectUuid.h>
#include <media/EffectsFactoryApi.h>
#include <mediautils/TimeCheck.h>
+#include <system/audio.h>
#include <utils/Log.h>
-#include <system/audio_effects/effect_aec.h>
-#include <system/audio_effects/effect_downmix.h>
-#include <system/audio_effects/effect_dynamicsprocessing.h>
-#include <system/audio_effects/effect_hapticgenerator.h>
-#include <system/audio_effects/effect_ns.h>
-#include <system/audio_effects/effect_spatializer.h>
-#include <system/audio_effects/effect_visualizer.h>
-
#include "EffectHalAidl.h"
-#include <system/audio.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
#include "effectsAidlConversion/AidlConversionAec.h"
@@ -45,6 +38,16 @@
#include "effectsAidlConversion/AidlConversionBassBoost.h"
#include "effectsAidlConversion/AidlConversionDownmix.h"
#include "effectsAidlConversion/AidlConversionDynamicsProcessing.h"
+#include "effectsAidlConversion/AidlConversionEnvReverb.h"
+#include "effectsAidlConversion/AidlConversionEq.h"
+#include "effectsAidlConversion/AidlConversionHapticGenerator.h"
+#include "effectsAidlConversion/AidlConversionLoudnessEnhancer.h"
+#include "effectsAidlConversion/AidlConversionNoiseSuppression.h"
+#include "effectsAidlConversion/AidlConversionPresetReverb.h"
+#include "effectsAidlConversion/AidlConversionSpatializer.h"
+#include "effectsAidlConversion/AidlConversionVendorExtension.h"
+#include "effectsAidlConversion/AidlConversionVirtualizer.h"
+#include "effectsAidlConversion/AidlConversionVisualizer.h"
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
using ::aidl::android::hardware::audio::effect::CommandId;
@@ -81,10 +84,11 @@
int32_t sessionId, int32_t ioId,
const ::aidl::android::hardware::audio::effect::Descriptor& desc) {
const auto& typeUuid = desc.common.id.type;
+ ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
if (typeUuid == kAcousticEchoCancelerTypeUUID) {
mConversion =
std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId, desc);
- } else if (typeUuid == kAutomaticGainControlTypeUUID) {
+ } else if (typeUuid == kAutomaticGainControl2TypeUUID) {
mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
desc);
} else if (typeUuid == kBassBoostTypeUUID) {
@@ -96,10 +100,37 @@
} else if (typeUuid == kDynamicsProcessingTypeUUID) {
mConversion =
std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId, desc);
+ } else if (typeUuid == kEnvReverbTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(effect, sessionId,
+ ioId, desc);
+ } else if (typeUuid == kEqualizerTypeUUID) {
+ mConversion =
+ std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId, desc);
+ } else if (typeUuid == kHapticGeneratorTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid == kLoudnessEnhancerTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid == kNoiseSuppressionTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid == kPresetReverbTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid == kSpatializerTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid == kVirtualizerTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
+ effect, sessionId, ioId, desc);
+ } else if (typeUuid == kVisualizerTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(effect, sessionId,
+ ioId, desc);
} else {
- ALOGE("%s effect not implemented yet, UUID type: %s", __func__,
- typeUuid.toString().c_str());
- return BAD_VALUE;
+ // For unknown UUID, use vendor extension implementation
+ mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
+ effect, sessionId, ioId, desc);
}
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 2b7856b..757215d 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -17,7 +17,10 @@
#define LOG_TAG "StreamHalAidl"
//#define LOG_NDEBUG 0
-#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
+#include <algorithm>
+#include <cstdint>
+
+#include <audio_utils/clock.h>
#include <mediautils/TimeCheck.h>
#include <utils/Log.h>
@@ -31,6 +34,16 @@
namespace android {
+using HalCommand = StreamDescriptor::Command;
+namespace {
+template<HalCommand::Tag cmd> HalCommand makeHalCommand() {
+ return HalCommand::make<cmd>(::aidl::android::media::audio::common::Void{});
+}
+template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) {
+ return HalCommand::make<cmd>(data);
+}
+} // namespace
+
// static
template<class T>
std::shared_ptr<IStreamCommon> StreamHalAidl::getStreamCommon(const std::shared_ptr<T>& stream) {
@@ -47,16 +60,17 @@
StreamHalAidl::StreamHalAidl(
std::string_view className, bool isInput, const audio_config& config,
- const StreamDescriptor& descriptor, const std::shared_ptr<IStreamCommon>& stream)
+ int32_t nominalLatency, StreamContextAidl&& context,
+ const std::shared_ptr<IStreamCommon>& stream)
: ConversionHelperAidl(className),
mIsInput(isInput),
mConfig(configToBase(config)),
- mFrameSizeBytes(descriptor.frameSizeBytes),
- mBufferSizeFrames(descriptor.bufferSizeFrames),
- mCommandMQ(new CommandMQ(descriptor.command)),
- mReplyMQ(new ReplyMQ(descriptor.reply)),
- mDataMQ(maybeCreateDataMQ(descriptor)),
+ mContext(std::move(context)),
mStream(stream) {
+ {
+ std::lock_guard l(mLock);
+ mLastReply.latencyMs = nominalLatency;
+ }
// Instrument audio signal power logging.
// Note: This assumes channel mask, format, and sample rate do not change after creation.
if (audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
@@ -74,17 +88,20 @@
}
status_t StreamHalAidl::getBufferSize(size_t *size) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
if (size == nullptr) {
return BAD_VALUE;
}
- if (mFrameSizeBytes == 0 || mBufferSizeFrames == 0 || !mStream) {
+ if (mContext.getFrameSizeBytes() == 0 || mContext.getBufferSizeFrames() == 0 ||
+ !mStream) {
return NO_INIT;
}
- *size = mFrameSizeBytes * mBufferSizeFrames;
+ *size = mContext.getBufferSizeBytes();
return OK;
}
status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
if (configBase == nullptr) {
return BAD_VALUE;
}
@@ -94,6 +111,7 @@
}
status_t StreamHalAidl::setParameters(const String8& kvPairs __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -101,6 +119,7 @@
}
status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
values->clear();
if (!mStream) return NO_INIT;
@@ -109,17 +128,19 @@
}
status_t StreamHalAidl::getFrameSize(size_t *size) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
if (size == nullptr) {
return BAD_VALUE;
}
- if (mFrameSizeBytes == 0 || !mStream) {
+ if (mContext.getFrameSizeBytes() == 0 || !mStream) {
return NO_INIT;
}
- *size = mFrameSizeBytes;
+ *size = mContext.getFrameSizeBytes();
return OK;
}
status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -127,6 +148,7 @@
}
status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -134,22 +156,59 @@
}
status_t StreamHalAidl::standby() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
- if (mState == StreamDescriptor::State::STANDBY) {
- return OK;
+ const auto state = getState();
+ StreamDescriptor::Reply reply;
+ switch (state) {
+ case StreamDescriptor::State::ACTIVE:
+ if (status_t status = pause(&reply); status != OK) return status;
+ if (reply.state != StreamDescriptor::State::PAUSED) {
+ ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ FALLTHROUGH_INTENDED;
+ case StreamDescriptor::State::PAUSED:
+ case StreamDescriptor::State::DRAIN_PAUSED:
+ if (mIsInput) return flush();
+ if (status_t status = flush(&reply); status != OK) return status;
+ if (reply.state != StreamDescriptor::State::IDLE) {
+ ALOGE("%s: unexpected stream state: %s (expected IDLE)",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ FALLTHROUGH_INTENDED;
+ case StreamDescriptor::State::IDLE:
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
+ &reply, true /*safeFromNonWorkerThread*/); status != OK) {
+ return status;
+ }
+ if (reply.state != StreamDescriptor::State::STANDBY) {
+ ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ FALLTHROUGH_INTENDED;
+ case StreamDescriptor::State::STANDBY:
+ return OK;
+ default:
+ ALOGE("%s: not supported from %s stream state %s",
+ __func__, mIsInput ? "input" : "output", toString(state).c_str());
+ return INVALID_OPERATION;
}
- ALOGE("%s not implemented yet", __func__);
- return OK;
}
status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
return mStream->dump(fd, Args(args).args(), args.size());
}
status_t StreamHalAidl::start() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -157,6 +216,137 @@
}
status_t StreamHalAidl::stop() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
+}
+
+status_t StreamHalAidl::getLatency(uint32_t *latency) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+ return status;
+ }
+ *latency = std::max<int32_t>(0, reply.latencyMs);
+ return OK;
+}
+
+status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestamp) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+ return status;
+ }
+ *frames = reply.observable.frames;
+ *timestamp = reply.observable.timeNs;
+ return OK;
+}
+
+status_t StreamHalAidl::getXruns(int32_t *frames) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+ return status;
+ }
+ *frames = reply.xrunFrames;
+ return OK;
+}
+
+status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
+ mWorkerTid.store(gettid(), std::memory_order_release);
+ // Switch the stream into an active state if needed.
+ // Note: in future we may add support for priming the audio pipeline
+ // with data prior to enabling output (thus we can issue a "burst" command in the "standby"
+ // stream state), however this scenario wasn't supported by the HIDL HAL.
+ if (getState() == StreamDescriptor::State::STANDBY) {
+ StreamDescriptor::Reply reply;
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply);
+ status != OK) {
+ return status;
+ }
+ if (reply.state != StreamDescriptor::State::IDLE) {
+ ALOGE("%s: failed to get the stream out of standby, actual state: %s",
+ __func__, toString(reply.state).c_str());
+ return INVALID_OPERATION;
+ }
+ }
+ if (!mIsInput) {
+ bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite());
+ }
+ StreamDescriptor::Command burst =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes);
+ if (!mIsInput) {
+ if (!mContext.getDataMQ()->write(static_cast<const int8_t*>(buffer), bytes)) {
+ ALOGE("%s: failed to write %zu bytes to data MQ", __func__, bytes);
+ return NOT_ENOUGH_DATA;
+ }
+ }
+ StreamDescriptor::Reply reply;
+ if (status_t status = sendCommand(burst, &reply); status != OK) {
+ return status;
+ }
+ *transferred = reply.fmqByteCount;
+ if (mIsInput) {
+ LOG_ALWAYS_FATAL_IF(*transferred > bytes,
+ "%s: HAL module read %zu bytes, which exceeds requested count %zu",
+ __func__, *transferred, bytes);
+ if (auto toRead = mContext.getDataMQ()->availableToRead();
+ toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) {
+ ALOGE("%s: failed to read %zu bytes to data MQ", __func__, toRead);
+ return NOT_ENOUGH_DATA;
+ }
+ }
+ mStreamPowerLog.log(buffer, *transferred);
+ return OK;
+}
+
+status_t StreamHalAidl::pause(StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return sendCommand(makeHalCommand<HalCommand::Tag::pause>(), reply,
+ true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
+}
+
+status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ if (mIsInput) {
+ return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
+ } else {
+ return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
+ }
+}
+
+status_t StreamHalAidl::drain(bool earlyNotify, StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
+ mIsInput ? StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED :
+ earlyNotify ? StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY :
+ StreamDescriptor::DrainMode::DRAIN_ALL), reply);
+}
+
+status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return sendCommand(makeHalCommand<HalCommand::Tag::flush>(), reply,
+ true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
+}
+
+status_t StreamHalAidl::exit() {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -165,6 +355,7 @@
status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
struct audio_mmap_buffer_info *info __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -172,6 +363,7 @@
}
status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -184,6 +376,7 @@
}
status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -207,50 +400,76 @@
return INVALID_OPERATION;
}
-namespace {
-
-/* Notes on callback ownership.
-
-This is how Binder ownership model looks like. The server implementation
-is owned by Binder framework (via sp<>). Proxies are owned by clients.
-When the last proxy disappears, Binder framework releases the server impl.
-
-Thus, it is not needed to keep any references to StreamCallback (this is
-the server impl) -- it will live as long as HAL server holds a strong ref to
-IStreamCallback proxy.
-
-The callback only keeps a weak reference to the stream. The stream is owned
-by AudioFlinger.
-
-*/
-
-class StreamCallback : public ::aidl::android::hardware::audio::core::BnStreamCallback {
- ndk::ScopedAStatus onTransferReady() override {
- return ndk::ScopedAStatus::ok();
+status_t StreamHalAidl::sendCommand(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
+ bool safeFromNonWorkerThread) {
+ // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ if (!safeFromNonWorkerThread) {
+ const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
+ LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
+ "%s %s: must be invoked from the worker thread (%d)",
+ __func__, command.toString().c_str(), workerTid);
}
- ndk::ScopedAStatus onError() override {
- return ndk::ScopedAStatus::ok();
+ if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
+ ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
+ return NOT_ENOUGH_DATA;
}
- ndk::ScopedAStatus onDrainReady() override {
- return ndk::ScopedAStatus::ok();
+ StreamDescriptor::Reply localReply{};
+ if (reply == nullptr) {
+ reply = &localReply;
}
-};
+ if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
+ ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str());
+ return NOT_ENOUGH_DATA;
+ }
+ {
+ std::lock_guard l(mLock);
+ mLastReply = *reply;
+ }
+ switch (reply->status) {
+ case STATUS_OK: return OK;
+ case STATUS_BAD_VALUE: return BAD_VALUE;
+ case STATUS_INVALID_OPERATION: return INVALID_OPERATION;
+ case STATUS_NOT_ENOUGH_DATA: return NOT_ENOUGH_DATA;
+ default:
+ ALOGE("%s: unexpected status %d returned for command %s",
+ __func__, reply->status, command.toString().c_str());
+ return INVALID_OPERATION;
+ }
+}
-} // namespace
+status_t StreamHalAidl::updateCountersIfNeeded(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) {
+ if (mWorkerTid.load(std::memory_order_acquire) == gettid()) {
+ if (const auto state = getState(); state != StreamDescriptor::State::ACTIVE &&
+ state != StreamDescriptor::State::DRAINING &&
+ state != StreamDescriptor::State::TRANSFERRING) {
+ return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply);
+ }
+ }
+ if (reply != nullptr) {
+ std::lock_guard l(mLock);
+ *reply = mLastReply;
+ }
+ return OK;
+}
StreamOutHalAidl::StreamOutHalAidl(
- const audio_config& config,
- const StreamDescriptor& descriptor, const std::shared_ptr<IStreamOut>& stream)
- : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config,
- descriptor, getStreamCommon(stream)),
- mStream(stream) {}
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+ const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
+ : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
+ std::move(context), getStreamCommon(stream)),
+ mStream(stream), mCallbackBroker(callbackBroker) {}
+
+StreamOutHalAidl::~StreamOutHalAidl() {
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->clearCallbacks(this);
+ }
+}
status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
- TIME_CHECK();
- *latency = 0;
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return StreamHalAidl::getLatency(latency);
}
status_t StreamOutHalAidl::setVolume(float left __unused, float right __unused) {
@@ -267,84 +486,93 @@
return OK;
}
-status_t StreamOutHalAidl::write(
- const void *buffer __unused, size_t bytes __unused, size_t *written __unused) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
- if (!mStream) return NO_INIT;
- *written = 0;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
+ if (buffer == nullptr || written == nullptr) {
+ return BAD_VALUE;
+ }
+ // For the output scenario, 'transfer' does not modify the buffer.
+ return transfer(const_cast<void*>(buffer), bytes, written);
}
-status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames __unused) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames) {
+ if (dspFrames == nullptr) {
+ return BAD_VALUE;
+ }
+ int64_t aidlFrames = 0, aidlTimestamp = 0;
+ if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
+ return OK;
+ }
+ *dspFrames = std::clamp<int64_t>(aidlFrames, 0, UINT32_MAX);
return OK;
}
status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
+ // Obsolete, use getPresentationPosition.
+ return INVALID_OPERATION;
+}
+
+status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ if (auto cb = callback.promote(); cb != nullptr) {
+ broker->setStreamOutCallback(this, cb);
+ } else {
+ // It is expected that the framework never passes a null pointer.
+ // In the AIDL model callbacks can't be "unregistered".
+ LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
+ }
+ }
return OK;
}
-status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback __unused) {
+status_t StreamOutHalAidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
+ if (supportsPause == nullptr || supportsResume == nullptr) {
+ return BAD_VALUE;
+ }
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
-}
-
-status_t StreamOutHalAidl::supportsPauseAndResume(
- bool *supportsPause __unused, bool *supportsResume __unused) {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ *supportsPause = *supportsResume = true;
return OK;
}
status_t StreamOutHalAidl::pause() {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return StreamHalAidl::pause();
}
status_t StreamOutHalAidl::resume() {
+ return StreamHalAidl::resume();
+}
+
+status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain) {
+ if (supportsDrain == nullptr) {
+ return BAD_VALUE;
+ }
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ *supportsDrain = true;
return OK;
}
-status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain __unused) {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
-}
-
-status_t StreamOutHalAidl::drain(bool earlyNotify __unused) {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+status_t StreamOutHalAidl::drain(bool earlyNotify) {
+ return StreamHalAidl::drain(earlyNotify);
}
status_t StreamOutHalAidl::flush() {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return StreamHalAidl::flush();
}
-status_t StreamOutHalAidl::getPresentationPosition(
- uint64_t *frames __unused, struct timespec *timestamp __unused) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
+ if (frames == nullptr || timestamp == nullptr) {
+ return BAD_VALUE;
+ }
+ int64_t aidlFrames = 0, aidlTimestamp = 0;
+ if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
+ return status;
+ }
+ *frames = std::max<int64_t>(0, aidlFrames);
+ timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
+ timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
return OK;
}
@@ -401,23 +629,15 @@
}
status_t StreamOutHalAidl::setEventCallback(
- const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
+ const sp<StreamOutHalInterfaceEventCallback>& callback) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->setStreamOutEventCallback(this, callback);
+ }
return OK;
}
-namespace {
-
-struct StreamOutEventCallback {
- StreamOutEventCallback(const wp<StreamOutHalAidl>& stream) : mStream(stream) {}
- private:
- wp<StreamOutHalAidl> mStream;
-};
-
-} // namespace
-
status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
TIME_CHECK();
if (!mStream) return NO_INIT;
@@ -434,61 +654,24 @@
};
status_t StreamOutHalAidl::setLatencyModeCallback(
- const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
+ const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->setStreamOutLatencyModeCallback(this, callback);
+ }
return OK;
};
-void StreamOutHalAidl::onWriteReady() {
- sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
- if (callback == 0) return;
- ALOGV("asyncCallback onWriteReady");
- callback->onWriteReady();
-}
-
-void StreamOutHalAidl::onDrainReady() {
- sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
- if (callback == 0) return;
- ALOGV("asyncCallback onDrainReady");
- callback->onDrainReady();
-}
-
-void StreamOutHalAidl::onError() {
- sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
- if (callback == 0) return;
- ALOGV("asyncCallback onError");
- callback->onError();
-}
-
-void StreamOutHalAidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs __unused) {
- sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
- if (callback == nullptr) return;
- ALOGV("asyncCodecFormatCallback %s", __func__);
- callback->onCodecFormatChanged(metadataBs);
-}
-
-void StreamOutHalAidl::onRecommendedLatencyModeChanged(
- const std::vector<audio_latency_mode_t>& modes __unused) {
- sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
- if (callback == nullptr) return;
- callback->onRecommendedLatencyModeChanged(modes);
-}
-
status_t StreamOutHalAidl::exit() {
- // FIXME this is using hard-coded strings but in the future, this functionality will be
- // converted to use audio HAL extensions required to support tunneling
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return StreamHalAidl::exit();
}
StreamInHalAidl::StreamInHalAidl(
- const audio_config& config,
- const StreamDescriptor& descriptor, const std::shared_ptr<IStreamIn>& stream)
- : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config,
- descriptor, getStreamCommon(stream)),
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+ const std::shared_ptr<IStreamIn>& stream)
+ : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
+ std::move(context), getStreamCommon(stream)),
mStream(stream) {}
status_t StreamInHalAidl::setGain(float gain __unused) {
@@ -498,31 +681,34 @@
return OK;
}
-status_t StreamInHalAidl::read(
- void *buffer __unused, size_t bytes __unused, size_t *read __unused) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- // FIXME: Don't forget to update mPowerLog
+status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
+ if (buffer == nullptr || read == nullptr) {
+ return BAD_VALUE;
+ }
+ return transfer(buffer, bytes, read);
+}
+
+status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost) {
+ if (framesLost == nullptr) {
+ return BAD_VALUE;
+ }
+ int32_t aidlXruns = 0;
+ if (status_t status = getXruns(&aidlXruns); status != OK) {
+ return status;
+ }
+ *framesLost = std::max<int32_t>(0, aidlXruns);
return OK;
}
-status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost __unused) {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
-}
-
-status_t StreamInHalAidl::getCapturePosition(int64_t *frames __unused, int64_t *time __unused) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+status_t StreamInHalAidl::getCapturePosition(int64_t *frames, int64_t *time) {
+ if (frames == nullptr || time == nullptr) {
+ return BAD_VALUE;
+ }
+ return getObservablePosition(frames, time);
}
status_t StreamInHalAidl::getActiveMicrophones(
- std::vector<media::MicrophoneInfo> *microphones __unused) {
+ std::vector<media::MicrophoneInfoFw> *microphones __unused) {
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index e55c413..f43c8e2 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -16,7 +16,9 @@
#pragma once
+#include <atomic>
#include <memory>
+#include <mutex>
#include <string_view>
#include <aidl/android/hardware/audio/core/BpStreamCommon.h>
@@ -25,14 +27,74 @@
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
-#include <mediautils/Synchronization.h>
#include "ConversionHelperAidl.h"
#include "StreamPowerLog.h"
namespace android {
-class DeviceHalAidl;
+class StreamContextAidl {
+ public:
+ typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Command,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> CommandMQ;
+ typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Reply,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> ReplyMQ;
+ typedef AidlMessageQueue<int8_t,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
+
+ explicit StreamContextAidl(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor)
+ : mFrameSizeBytes(descriptor.frameSizeBytes),
+ mCommandMQ(new CommandMQ(descriptor.command)),
+ mReplyMQ(new ReplyMQ(descriptor.reply)),
+ mBufferSizeFrames(descriptor.bufferSizeFrames),
+ mDataMQ(maybeCreateDataMQ(descriptor)) {}
+ StreamContextAidl(StreamContextAidl&& other) :
+ mFrameSizeBytes(other.mFrameSizeBytes),
+ mCommandMQ(std::move(other.mCommandMQ)),
+ mReplyMQ(std::move(other.mReplyMQ)),
+ mBufferSizeFrames(other.mBufferSizeFrames),
+ mDataMQ(std::move(other.mDataMQ)) {}
+ StreamContextAidl& operator=(StreamContextAidl&& other) {
+ mFrameSizeBytes = other.mFrameSizeBytes;
+ mCommandMQ = std::move(other.mCommandMQ);
+ mReplyMQ = std::move(other.mReplyMQ);
+ mBufferSizeFrames = other.mBufferSizeFrames;
+ mDataMQ = std::move(other.mDataMQ);
+ return *this;
+ }
+ bool isValid() const {
+ return mFrameSizeBytes != 0 &&
+ mCommandMQ != nullptr && mCommandMQ->isValid() &&
+ mReplyMQ != nullptr && mReplyMQ->isValid() &&
+ (mDataMQ != nullptr || (
+ mDataMQ->isValid() &&
+ mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >=
+ mFrameSizeBytes * mBufferSizeFrames));
+ }
+ size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
+ size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
+ CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
+ DataMQ* getDataMQ() const { return mDataMQ.get(); }
+ size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
+ ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
+
+ private:
+ static std::unique_ptr<DataMQ> maybeCreateDataMQ(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+ using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+ if (descriptor.audio.getTag() == Tag::fmq) {
+ return std::make_unique<DataMQ>(descriptor.audio.get<Tag::fmq>());
+ }
+ return nullptr;
+ }
+
+ size_t mFrameSizeBytes;
+ std::unique_ptr<CommandMQ> mCommandMQ;
+ std::unique_ptr<ReplyMQ> mReplyMQ;
+ size_t mBufferSizeFrames;
+ std::unique_ptr<DataMQ> mDataMQ;
+};
class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
public:
@@ -87,13 +149,6 @@
status_t legacyReleaseAudioPatch() override;
protected:
- typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Command,
- ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> CommandMQ;
- typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Reply,
- ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> ReplyMQ;
- typedef AidlMessageQueue<int8_t,
- ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
-
template<class T>
static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon(
const std::shared_ptr<T>& stream);
@@ -102,7 +157,8 @@
StreamHalAidl(std::string_view className,
bool isInput,
const audio_config& config,
- const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
+ int32_t nominalLatency,
+ StreamContextAidl&& context,
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream);
~StreamHalAidl() override;
@@ -111,17 +167,31 @@
bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
+ status_t getLatency(uint32_t *latency);
+
+ status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
+
+ status_t getXruns(int32_t *frames);
+
+ status_t transfer(void *buffer, size_t bytes, size_t *transferred);
+
+ status_t pause(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t resume(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t drain(bool earlyNotify,
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t flush(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+ status_t exit();
+
const bool mIsInput;
const audio_config_base_t mConfig;
- const size_t mFrameSizeBytes;
- const size_t mBufferSizeFrames;
- const std::unique_ptr<CommandMQ> mCommandMQ;
- const std::unique_ptr<ReplyMQ> mReplyMQ;
- const std::unique_ptr<DataMQ> mDataMQ;
- // mStreamPowerLog is used for audio signal power logging.
- StreamPowerLog mStreamPowerLog;
- ::aidl::android::hardware::audio::core::StreamDescriptor::State mState =
- ::aidl::android::hardware::audio::core::StreamDescriptor::State::STANDBY;
+ const StreamContextAidl mContext;
private:
static audio_config_base_t configToBase(const audio_config& config) {
@@ -131,18 +201,27 @@
result.format = config.format;
return result;
}
- static std::unique_ptr<DataMQ> maybeCreateDataMQ(
- const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
- using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
- if (descriptor.audio.getTag() == Tag::fmq) {
- return std::make_unique<DataMQ>(descriptor.audio.get<Tag::fmq>());
- }
- return nullptr;
+ ::aidl::android::hardware::audio::core::StreamDescriptor::State getState() {
+ std::lock_guard l(mLock);
+ return mLastReply.state;
}
+ status_t sendCommand(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr,
+ bool safeFromNonWorkerThread = false);
+ status_t updateCountersIfNeeded(
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
+ std::mutex mLock;
+ ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
+ // mStreamPowerLog is used for audio signal power logging.
+ StreamPowerLog mStreamPowerLog;
+ std::atomic<pid_t> mWorkerTid = -1;
};
+class CallbackBroker;
+
class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
public:
// Return the audio hardware driver estimated latency in milliseconds.
@@ -216,34 +295,21 @@
status_t setLatencyModeCallback(
const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) override;
- void onRecommendedLatencyModeChanged(const std::vector<audio_latency_mode_t>& modes);
-
status_t exit() override;
- void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs);
-
- // Methods used by StreamOutCallback ().
- // FIXME: Consider the required visibility.
- void onWriteReady();
- void onDrainReady();
- void onError();
-
private:
friend class sp<StreamOutHalAidl>;
- mediautils::atomic_wp<StreamOutHalInterfaceCallback> mCallback;
- mediautils::atomic_wp<StreamOutHalInterfaceEventCallback> mEventCallback;
- mediautils::atomic_wp<StreamOutHalInterfaceLatencyModeCallback> mLatencyModeCallback;
-
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream;
+ const wp<CallbackBroker> mCallbackBroker;
// Can not be constructed directly by clients.
StreamOutHalAidl(
- const audio_config& config,
- const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
- const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream);
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream,
+ const sp<CallbackBroker>& callbackBroker);
- ~StreamOutHalAidl() override = default;
+ ~StreamOutHalAidl() override;
};
class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl {
@@ -262,7 +328,7 @@
status_t getCapturePosition(int64_t *frames, int64_t *time) override;
// Get active microphones
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones) override;
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) override;
// Set microphone direction (for processing)
status_t setPreferredMicrophoneDirection(
@@ -281,8 +347,7 @@
// Can not be constructed directly by clients.
StreamInHalAidl(
- const audio_config& config,
- const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
+ const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream);
~StreamInHalAidl() override = default;
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2c289e1..07c6df5 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -24,6 +24,9 @@
#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/TimeCheck.h>
#include <utils/Log.h>
+#if MAJOR_VERSION >= 4
+#include <media/AidlConversion.h>
+#endif
#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutCallback.h)
#include <HidlUtils.h>
@@ -1169,7 +1172,7 @@
#if MAJOR_VERSION == 2
status_t StreamInHalHidl::getActiveMicrophones(
- std::vector<media::MicrophoneInfo> *microphones __unused) {
+ std::vector<media::MicrophoneInfoFw> *microphones __unused) {
if (mStream == 0) return NO_INIT;
return INVALID_OPERATION;
}
@@ -1182,7 +1185,7 @@
#elif MAJOR_VERSION >= 4
status_t StreamInHalHidl::getActiveMicrophones(
- std::vector<media::MicrophoneInfo> *microphonesInfo) {
+ std::vector<media::MicrophoneInfoFw> *microphonesInfo) {
TIME_CHECK();
if (!mStream) return NO_INIT;
Result retval;
@@ -1190,11 +1193,17 @@
[&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
retval = r;
for (size_t k = 0; k < micArrayHal.size(); k++) {
+ // Convert via legacy.
audio_microphone_characteristic_t dst;
- // convert
(void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
- media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
- microphonesInfo->push_back(microphone);
+ auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(dst);
+ if (conv.ok()) {
+ microphonesInfo->push_back(conv.value());
+ } else {
+ ALOGW("getActiveMicrophones: could not convert %s to AIDL: %d",
+ toString(micArrayHal[k]).c_str(), conv.error());
+ microphonesInfo->push_back(media::MicrophoneInfoFw{});
+ }
}
});
return processReturn("getActiveMicrophones", ret, retval);
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 54fbefe..5361047 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -253,7 +253,7 @@
virtual status_t getCapturePosition(int64_t *frames, int64_t *time);
// Get active microphones
- virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) override;
// Set microphone direction (for processing)
virtual status_t setPreferredMicrophoneDirection(
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
index 901566e..15768b3 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
@@ -103,6 +103,7 @@
break;
}
default:
+ // use vendor extension implementation
ALOGW("%s unknown param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
index 80df2b8..b736936 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
@@ -34,7 +34,7 @@
namespace effect {
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
-using ::aidl::android::hardware::audio::effect::AutomaticGainControl;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV2;
using ::aidl::android::hardware::audio::effect::Parameter;
using ::android::status_t;
using utils::EffectParamReader;
@@ -84,8 +84,8 @@
switch (type) {
case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
Parameter::Id id =
- MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControl, automaticGainControlTag,
- AutomaticGainControl::fixedDigitalGainMb);
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+ AutomaticGainControlV2::fixedDigitalGainMb);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
value = VALUE_OR_RETURN_STATUS(
aidl::android::aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(aidlParam));
@@ -93,8 +93,8 @@
}
case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
Parameter::Id id =
- MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControl, automaticGainControlTag,
- AutomaticGainControl::levelEstimator);
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+ AutomaticGainControlV2::levelEstimator);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
value = VALUE_OR_RETURN_STATUS(
aidl::android::aidl2legacy_Parameter_agc_uint32_levelEstimator(aidlParam));
@@ -102,8 +102,8 @@
}
case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
Parameter::Id id =
- MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControl, automaticGainControlTag,
- AutomaticGainControl::saturationMarginMb);
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+ AutomaticGainControlV2::saturationMarginMb);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
value = VALUE_OR_RETURN_STATUS(
aidl::android::aidl2legacy_Parameter_agc_uint32_saturationMargin(aidlParam));
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
index ba8148f..9ec593f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
@@ -24,6 +24,7 @@
#include <media/AidlConversionNdk.h>
#include <media/AidlConversionEffect.h>
#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/aidl_effects_utils.h>
#include <system/audio_effects/effect_bassboost.h>
#include <utils/Log.h>
@@ -37,6 +38,7 @@
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
using ::aidl::android::hardware::audio::effect::BassBoost;
using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
using ::android::status_t;
using utils::EffectParamReader;
using utils::EffectParamWriter;
@@ -70,8 +72,8 @@
}
status_t AidlConversionBassBoost::getParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
OK != param.readFromParameter(&type)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
param.setStatus(BAD_VALUE);
@@ -80,26 +82,26 @@
Parameter aidlParam;
switch (type) {
case BASSBOOST_PARAM_STRENGTH: {
+ uint16_t value;
Parameter::Id id =
MAKE_SPECIFIC_PARAMETER_ID(BassBoost, bassBoostTag, BassBoost::strengthPm);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
value = VALUE_OR_RETURN_STATUS(
aidl::android::aidl2legacy_Parameter_BassBoost_uint16_strengthPm(aidlParam));
- break;
+ return param.writeToValue(&value);
}
case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
- const auto& cap =
- VALUE_OR_RETURN_STATUS(aidl::android::UNION_GET(mDesc.capability, bassBoost));
- value = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(cap.strengthSupported));
- break;
+ // an invalid range indicates not setting support for this parameter
+ uint32_t value =
+ ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::bassBoost>(
+ BassBoost::strengthPm, mDesc.capability);
+ return param.writeToValue(&value);
}
default: {
ALOGW("%s unknown param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
}
-
- return param.writeToValue(&value);
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
index 4ecaa07..4555c9f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -147,8 +147,6 @@
DynamicsProcessing::inputGain);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- DynamicsProcessing::Capability cap =
- mDesc.capability.get<Capability::dynamicsProcessing>();
std::vector<DynamicsProcessing::InputGain> gains =
VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
aidlParam, DynamicsProcessing, dynamicsProcessing,
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
new file mode 100644
index 0000000..0544e3f
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionEnvReverb"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_environmentalreverb.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionEnvReverb.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::EnvironmentalReverb;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+/**
+ * Macro to get a parameter from effect_param_t wrapper and set it to AIDL effect.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamReader, a reader wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define SET_AIDL_PARAMETER(param, aidlType, valueType, tag) \
+ { \
+ Parameter aidlParam; \
+ valueType value; \
+ if (status_t status = param.readFromValue(&value); status != OK) { \
+ ALOGE("%s %s read from parameter failed, ret %d", __func__, #tag, status); \
+ return status; \
+ } \
+ aidlParam = MAKE_SPECIFIC_PARAMETER( \
+ EnvironmentalReverb, environmentalReverb, tag, \
+ VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<aidlType>(value))); \
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); \
+ }
+
+/**
+ * Macro to get a parameter from AIDL effect and write the value to effect_param_t with wrapper.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamWriter, a writer wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define GET_AIDL_PARAMETER(param, aidltype, valueType, tag) \
+ { \
+ aidltype value; \
+ Parameter aidlParam; \
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(EnvironmentalReverb, environmentalReverbTag, \
+ EnvironmentalReverb::tag); \
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam))); \
+ value = VALUE_OR_RETURN_STATUS( \
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, EnvironmentalReverb, environmentalReverb, \
+ EnvironmentalReverb::tag, std::decay_t<aidltype>)); \
+ if (status_t status = param.writeToValue((valueType*)&value); status != OK) { \
+ param.setStatus(status); \
+ ALOGE("%s %s write to parameter failed %d, ret %d", __func__, #tag, value, status); \
+ return status; \
+ } \
+ }
+
+status_t AidlConversionEnvReverb::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (status_t status = param.readFromParameter(&type); status != OK) {
+ ALOGE("%s failed to read type from %s, ret %d", __func__, param.toString().c_str(), status);
+ return BAD_VALUE;
+ }
+
+ switch (type) {
+ case REVERB_PARAM_ROOM_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ break;
+ }
+ case REVERB_PARAM_ROOM_HF_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ break;
+ }
+ case REVERB_PARAM_DECAY_TIME: {
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ break;
+ }
+ case REVERB_PARAM_DECAY_HF_RATIO: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_DELAY: {
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ break;
+ }
+ case REVERB_PARAM_REVERB_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ break;
+ }
+ case REVERB_PARAM_REVERB_DELAY: {
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ break;
+ }
+ case REVERB_PARAM_DIFFUSION: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ break;
+ }
+ case REVERB_PARAM_DENSITY: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ case REVERB_PARAM_BYPASS: {
+ SET_AIDL_PARAMETER(param, bool, int32_t, bypass);
+ break;
+ }
+ case REVERB_PARAM_PROPERTIES: {
+ if (sizeof(t_reverb_settings) > param.getValueSize()) {
+ ALOGE("%s vsize %zu less than t_reverb_settings size %zu", __func__,
+ param.getValueSize(), sizeof(t_reverb_settings));
+ return BAD_VALUE;
+ }
+ // this sequency needs to be aligned with t_reverb_settings
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ default: {
+ // TODO: handle with vendor extension
+ }
+ }
+ return OK;
+}
+
+status_t AidlConversionEnvReverb::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (status_t status = param.readFromParameter(&type); status != OK) {
+ ALOGE("%s failed to read type from %s", __func__, param.toString().c_str());
+ param.setStatus(status);
+ return status;
+ }
+
+ switch (type) {
+ case REVERB_PARAM_ROOM_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ break;
+ }
+ case REVERB_PARAM_ROOM_HF_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ break;
+ }
+ case REVERB_PARAM_DECAY_TIME: {
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ break;
+ }
+ case REVERB_PARAM_DECAY_HF_RATIO: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ break;
+ }
+ case REVERB_PARAM_REFLECTIONS_DELAY: {
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ break;
+ }
+ case REVERB_PARAM_REVERB_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ break;
+ }
+ case REVERB_PARAM_REVERB_DELAY: {
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ break;
+ }
+ case REVERB_PARAM_DIFFUSION: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ break;
+ }
+ case REVERB_PARAM_DENSITY: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ case REVERB_PARAM_BYPASS: {
+ GET_AIDL_PARAMETER(param, bool, int32_t, bypass);
+ break;
+ }
+ case REVERB_PARAM_PROPERTIES: {
+ // this sequency needs to be aligned with t_reverb_settings
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ default: {
+ // TODO: handle with vendor extension
+ return BAD_VALUE;
+ }
+ }
+ return OK;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
new file mode 100644
index 0000000..8b92374
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionEnvReverb : public EffectConversionHelperAidl {
+ public:
+ AidlConversionEnvReverb(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionEnvReverb() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
new file mode 100644
index 0000000..a10d271
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionEQ"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_equalizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionEq.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Equalizer;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionEq::setParameter(EffectParamReader& param) {
+ uint32_t type;
+ uint16_t value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type) ||
+ OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ switch (type) {
+ case EQ_PARAM_CUR_PRESET: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)value);
+ break;
+ }
+ case EQ_PARAM_BAND_LEVEL: {
+ int32_t band;
+ uint16_t level;
+ if (OK != param.readFromParameter(&band) || OK != param.readFromParameter(&level)) {
+ ALOGE("%s invalid bandLevel param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ std::vector<Equalizer::BandLevel> bandLevels = {{.index = band, .levelMb = level}};
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
+ break;
+ }
+ case EQ_PARAM_PROPERTIES: {
+ // TODO: handle properties setting
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+aidl::ConversionResult<Parameter> AidlConversionEq::getAidlParameter(Equalizer::Tag tag) {
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Equalizer, equalizerTag, tag);
+ RETURN_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ return aidlParam;
+}
+
+status_t AidlConversionEq::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ param.setStatus(BAD_VALUE);
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case EQ_PARAM_NUM_BANDS: {
+ aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+ auto bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+ std::vector<Equalizer::BandLevel>));
+ uint32_t num = bandLevels.size();
+ return param.writeToValue(&num);
+ }
+ default:
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
new file mode 100644
index 0000000..0433965
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionEq : public EffectConversionHelperAidl {
+ public:
+ AidlConversionEq(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionEq() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+ aidl::ConversionResult<::aidl::android::hardware::audio::effect::Parameter> getAidlParameter(
+ ::aidl::android::hardware::audio::effect::Equalizer::Tag tag);
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
new file mode 100644
index 0000000..9575e7d
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionHapticGenerator"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionHapticGenerator.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::HapticGenerator;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionHapticGenerator::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case HG_PARAM_HAPTIC_INTENSITY: {
+ int32_t id = 0, scale;
+ if (OK != param.readFromValue(&id) || OK != param.readFromValue(&scale)) {
+ ALOGE("%s invalid intensity %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ HapticGenerator::HapticScale hpScale(
+ {.id = id, .scale = (HapticGenerator::VibratorScale)(scale)});
+ aidlParam = MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, hapticScales,
+ {hpScale});
+ break;
+ }
+ case HG_PARAM_VIBRATOR_INFO: {
+ float resonantFrequencyHz, qFactor, maxAmplitude;
+ if (OK != param.readFromValue(&resonantFrequencyHz) ||
+ OK != param.readFromValue(&qFactor) || OK != param.readFromValue(&maxAmplitude)) {
+ ALOGE("%s invalid vibrator info %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ HapticGenerator::VibratorInformation info({.resonantFrequencyHz = resonantFrequencyHz,
+ .qFactor = qFactor,
+ .maxAmplitude = maxAmplitude});
+ aidlParam =
+ MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, vibratorInfo, info);
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+// No parameter to get for HapticGenerator
+status_t AidlConversionHapticGenerator::getParameter(EffectParamWriter& param __unused) {
+ return OK;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
new file mode 100644
index 0000000..03114a5
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionHapticGenerator : public EffectConversionHelperAidl {
+ public:
+ AidlConversionHapticGenerator(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionHapticGenerator() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
new file mode 100644
index 0000000..e3c898f
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionLoudnessEnhancer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionLoudnessEnhancer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::LoudnessEnhancer;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionLoudnessEnhancer::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ int32_t gain = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&gain)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(LoudnessEnhancer, loudnessEnhancer, gainMb, gain);
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionLoudnessEnhancer::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ switch (type) {
+ case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(LoudnessEnhancer, loudnessEnhancerTag,
+ LoudnessEnhancer::gainMb);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ int32_t gain = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, LoudnessEnhancer, loudnessEnhancer, LoudnessEnhancer::gainMb,
+ std::decay_t<decltype(gain)>));
+ return param.writeToValue(&gain);
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
new file mode 100644
index 0000000..c0402f9
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionLoudnessEnhancer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionLoudnessEnhancer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionLoudnessEnhancer() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
new file mode 100644
index 0000000..69184cf
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionNoiseSuppression"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_ns.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionNoiseSuppression.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::NoiseSuppression;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionNoiseSuppression::setParameter(EffectParamReader& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case NS_PARAM_LEVEL: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, level,
+ static_cast<NoiseSuppression::Level>(value));
+ break;
+ }
+ case NS_PARAM_TYPE: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, type,
+ static_cast<NoiseSuppression::Type>(value));
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionNoiseSuppression::getParameter(EffectParamWriter& param) {
+ uint32_t paramType = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(¶mType)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (paramType) {
+ case NS_PARAM_LEVEL: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(NoiseSuppression, noiseSuppressionTag,
+ NoiseSuppression::level);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ NoiseSuppression::Level level = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, NoiseSuppression, noiseSuppression,
+ NoiseSuppression::level, NoiseSuppression::Level));
+ value = static_cast<uint32_t>(level);
+ break;
+ }
+ case NS_PARAM_TYPE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(NoiseSuppression, noiseSuppressionTag,
+ NoiseSuppression::type);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ NoiseSuppression::Type nsType = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, NoiseSuppression, noiseSuppression,
+ NoiseSuppression::type, NoiseSuppression::Type));
+ value = static_cast<uint32_t>(nsType);
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
new file mode 100644
index 0000000..f51e13a
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionNoiseSuppression : public EffectConversionHelperAidl {
+ public:
+ AidlConversionNoiseSuppression(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionNoiseSuppression() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp
new file mode 100644
index 0000000..3e9bf4b
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionPresetReverb"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_presetreverb.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionPresetReverb.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::PresetReverb;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionPresetReverb::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ if (type == REVERB_PARAM_PRESET) {
+ uint16_t value = 0;
+ if (OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid preset value %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(PresetReverb, presetReverb, preset,
+ static_cast<PresetReverb::Presets>(value));
+ } else {
+ // handle vendor extension
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionPresetReverb::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ uint16_t value = 0;
+ ALOGE("%s enter %s", __func__, param.toString().c_str());
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ if (type == REVERB_PARAM_PRESET) {
+ Parameter aidlParam;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(PresetReverb, presetReverbTag, PresetReverb::preset);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ auto aidlPreset = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, PresetReverb, presetReverb,
+ PresetReverb::preset, PresetReverb::Presets));
+ value = static_cast<uint16_t>(aidlPreset);
+ } else {
+ // handle vendor extension
+ }
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
new file mode 100644
index 0000000..397d6e6
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionPresetReverb : public EffectConversionHelperAidl {
+ public:
+ AidlConversionPresetReverb(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionPresetReverb() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
new file mode 100644
index 0000000..d2a94e4
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionSpatializer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_spatializer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionSpatializer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionSpatializer::setParameter(EffectParamReader& param) {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionSpatializer::getParameter(EffectParamWriter& param) {
+ Parameter aidlParam;
+ Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, 0 /* no tag */);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& extBytes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_vector_uint8(aidlParam));
+ if (param.getValueSize() < extBytes.size()) {
+ ALOGE("%s extension return data %zu exceed vsize %zu", __func__, extBytes.size(),
+ param.getValueSize());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ return param.writeToValue(extBytes.data(), extBytes.size());
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
new file mode 100644
index 0000000..c44567c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionSpatializer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionSpatializer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionSpatializer() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
new file mode 100644
index 0000000..584b60e
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#include <type_traits>
+#define LOG_TAG "AidlConversionVendorExtension"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVendorExtension.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+/**
+ * For all effect types we currently don't support, add a default extension implementation to use
+ * std::vector<uint8_t> to pass through all data in the format of effect_param_t (the data we got
+ * from libaudioclient for now).
+ * This logic will be removed after we adopt to same AIDL parameter union AIDL in libaudioclient,
+ * after that framework doesn't need to do any AIDL conversion, and the vendor extension can be
+ * pass down in Parameter as is.
+ */
+status_t AidlConversionVendorExtension::setParameter(EffectParamReader& param) {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVendorExtension::getParameter(EffectParamWriter& param) {
+ int32_t tag;
+ if (OK != param.readFromParameter(&tag)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, tag /* parameter tag */);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ // copy the AIDL extension data back to effect_param_t
+ return VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam,
+ param));
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
new file mode 100644
index 0000000..fd22e5c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVendorExtension : public EffectConversionHelperAidl {
+ public:
+ AidlConversionVendorExtension(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionVendorExtension() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
new file mode 100644
index 0000000..482114d
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionVirtualizer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_spatializer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVirtualizer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionVirtualizer::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ uint16_t value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ // TODO
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVirtualizer::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ // TODO
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
new file mode 100644
index 0000000..91c0fcd
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVirtualizer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionVirtualizer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionVirtualizer() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
new file mode 100644
index 0000000..7e1e6d7
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionVisualizer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVisualizer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Visualizer;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionVisualizer::setParameter(EffectParamReader& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case VISUALIZER_PARAM_CAPTURE_SIZE: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, captureSamples, value);
+ break;
+ }
+ case VISUALIZER_PARAM_SCALING_MODE: {
+ Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(value));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, scalingMode, mode);
+ break;
+ }
+ case VISUALIZER_PARAM_LATENCY: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, latencyMs, value);
+ break;
+ }
+ case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+ Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(value));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, measurementMode, mode);
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVisualizer::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case VISUALIZER_PARAM_CAPTURE_SIZE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::captureSamples);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::captureSamples, int32_t));
+ mCaptureSize = value;
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_SCALING_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::scalingMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+ Visualizer::scalingMode, Visualizer::ScalingMode));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(mode));
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_LATENCY: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::latencyMs);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = (int32_t)VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::latencyMs, int32_t));
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::measurementMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::measurementMode,
+ Visualizer::MeasurementMode));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(mode));
+ return param.writeToValue(&value);
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+}
+
+status_t AidlConversionVisualizer::visualizerCapture(uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData || *replySize != mCaptureSize) {
+ ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::captureSampleBuffer);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& samples = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+ Visualizer::captureSampleBuffer, std::vector<uint8_t>));
+ size_t len = std::min((size_t)*replySize, samples.size());
+ std::memcpy(pReplyData, samples.data(), *replySize = len);
+ return OK;
+}
+
+status_t AidlConversionVisualizer::visualizerMeasure(uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData || *replySize != 2 * sizeof(int32_t)) {
+ ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag, Visualizer::measurement);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& measure = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::measurement, Visualizer::Measurement));
+ int32_t* reply = (int32_t *) pReplyData;
+ *reply++ = measure.rms;
+ *reply = measure.peak;
+ return OK;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
new file mode 100644
index 0000000..891c331
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVisualizer : public EffectConversionHelperAidl {
+ public:
+ AidlConversionVisualizer(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionVisualizer() {}
+
+ private:
+ uint32_t mCaptureSize;
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+ status_t visualizerCapture(uint32_t* replySize, void* pReplyData) override;
+ status_t visualizerMeasure(uint32_t* replySize, void* pReplyData) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h b/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
index 77563e8..3b8076f 100644
--- a/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
+++ b/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
@@ -30,11 +30,11 @@
0xbd61,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// 0xae3c653b-be18-4ab8-8938-418f0a7f06ac
-static const AudioUuid kAutomaticGainControlTypeUUID = {static_cast<int32_t>(0xae3c653b),
- 0xbe18,
- 0x4ab8,
- 0x8938,
- {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}};
+static const AudioUuid kAutomaticGainControl2TypeUUID = {static_cast<int32_t>(0xae3c653b),
+ 0xbe18,
+ 0x4ab8,
+ 0x8938,
+ {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}};
// 0634f220-ddd4-11db-a0fc-0002a5d5c51b
static const AudioUuid kBassBoostTypeUUID = {static_cast<int32_t>(0x0634f220),
0xddd4,
@@ -42,11 +42,11 @@
0xa0fc,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81862a-588b-11ed-9b6a-0242ac120002
-static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
- 0x588b,
- 0x11ed,
- 0x9b6a,
- {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0x381e49cc),
+ 0xa858,
+ 0x4aa2,
+ 0x87f6,
+ {0xe8, 0x38, 0x8e, 0x76, 0x01, 0xb2}};
// 7261676f-6d75-7369-6364-28e2fd3ac39e
static const AudioUuid kDynamicsProcessingTypeUUID = {static_cast<int32_t>(0x7261676f),
0x6d75,
@@ -89,18 +89,24 @@
0x11db,
0xbf3a,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// ccd4cf09-a79d-46c2-9aae-06a1698d6c8f
+static const AudioUuid kSpatializerTypeUUID = {static_cast<int32_t>(0xccd4cf09),
+ 0xa79d,
+ 0x46c2,
+ 0x9aae,
+ {0x06, 0xa1, 0x69, 0x8d, 0x6c, 0x8f}};
// 37cc2c00-dddd-11db-8577-0002a5d5c51b
static const AudioUuid kVirtualizerTypeUUID = {static_cast<int32_t>(0x37cc2c00),
0xdddd,
0x11db,
0x8577,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-// fa819f3e-588b-11ed-9b6a-0242ac120002
-static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xfa819f3e),
- 0x588b,
- 0x11ed,
- 0x9b6a,
- {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// e46b26a0-dddd-11db-8afd-0002a5d5c51b
+static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xe46b26a0),
+ 0xdddd,
+ 0x11db,
+ 0x8afd,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81a2b8-588b-11ed-9b6a-0242ac120002
static const AudioUuid kVolumeTypeUUID = {static_cast<int32_t>(0xfa81a2b8),
0x588b,
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 094b415..c685345 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -31,7 +31,7 @@
class StreamInHalInterface;
class StreamOutHalInterface;
-class DeviceHalInterface : public RefBase
+class DeviceHalInterface : public virtual RefBase
{
public:
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index 1d52b7d..a780a17 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -19,8 +19,8 @@
#include <vector>
+#include <android/media/MicrophoneInfoFw.h>
#include <media/audiohal/EffectHalInterface.h>
-#include <media/MicrophoneInfo.h>
#include <system/audio.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -110,8 +110,8 @@
virtual void onError() {}
protected:
- StreamOutHalInterfaceCallback() {}
- virtual ~StreamOutHalInterfaceCallback() {}
+ StreamOutHalInterfaceCallback() = default;
+ virtual ~StreamOutHalInterfaceCallback() = default;
};
class StreamOutHalInterfaceEventCallback : public virtual RefBase {
@@ -119,8 +119,8 @@
virtual void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) = 0;
protected:
- StreamOutHalInterfaceEventCallback() {}
- virtual ~StreamOutHalInterfaceEventCallback() {}
+ StreamOutHalInterfaceEventCallback() = default;
+ virtual ~StreamOutHalInterfaceEventCallback() = default;
};
class StreamOutHalInterfaceLatencyModeCallback : public virtual RefBase {
@@ -131,8 +131,8 @@
virtual void onRecommendedLatencyModeChanged(std::vector<audio_latency_mode_t> modes) = 0;
protected:
- StreamOutHalInterfaceLatencyModeCallback() {}
- virtual ~StreamOutHalInterfaceLatencyModeCallback() {}
+ StreamOutHalInterfaceLatencyModeCallback() = default;
+ virtual ~StreamOutHalInterfaceLatencyModeCallback() = default;
};
class StreamOutHalInterface : public virtual StreamHalInterface {
@@ -273,7 +273,7 @@
virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
// Get active microphones
- virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+ virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
// Set direction for capture processing
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t) = 0;
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index e20f74c..2f78dd0 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -29,7 +29,7 @@
],
defaults: [
- "latest_android_media_audio_common_types_cpp_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
],
cflags: [
@@ -37,12 +37,16 @@
"-Wextra",
"-Werror",
"-Wthread-safety",
+ "-DBACKEND_NDK",
],
shared_libs: [
"audioclient-types-aidl-cpp",
+ "libaudio_aidl_conversion_common_ndk",
"libaudiohal",
+ "liblog",
"libutils",
+ "libvibrator",
],
header_libs: [
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index 9b2d0e2..a8843d6 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -15,23 +15,36 @@
*/
//#define LOG_NDEBUG 0
+#include <cstddef>
#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <utility>
#define LOG_TAG "EffectsFactoryHalInterfaceTest"
+#include <aidl/android/media/audio/common/AudioUuid.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
-
#include <system/audio_effects/audio_effects_utils.h>
#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_agc2.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_downmix.h>
#include <system/audio_effects/effect_dynamicsprocessing.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+#include <system/audio_effects/effect_ns.h>
#include <system/audio_effect.h>
#include <gtest/gtest.h>
#include <utils/RefBase.h>
+#include <vibrator/ExternalVibrationUtils.h>
namespace android {
using effect::utils::EffectParamReader;
using effect::utils::EffectParamWriter;
+using ::aidl::android::media::audio::common::AudioUuid;
// EffectsFactoryHalInterface
TEST(libAudioHalTest, createEffectsFactoryHalInterface) {
@@ -86,80 +99,211 @@
EXPECT_NE(0, version.getMajorVersion());
}
-static char testDataBuffer[sizeof(effect_param_t) + 0xff] = {};
-static char testResponseBuffer[sizeof(effect_param_t) + 0xff] = {};
-TEST(libAudioHalTest, agcNotInit) {
- auto factory = EffectsFactoryHalInterface::create();
- ASSERT_NE(nullptr, factory);
+class EffectParamCombination {
+ public:
+ template <typename P, typename V>
+ void init(const P& p, const V& v, size_t len) {
+ setBuffer.resize(sizeof(effect_param_t) + sizeof(p) + sizeof(v) + 4);
+ getBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
+ expectBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
+ parameterSet =
+ std::make_shared<EffectParamReader>(createEffectParam(setBuffer.data(), p, v));
+ parameterGet =
+ std::make_shared<EffectParamReader>(createEffectParam(getBuffer.data(), p, v));
+ parameterExpect =
+ std::make_shared<EffectParamReader>(createEffectParam(expectBuffer.data(), p, v));
+ valueSize = len;
+ }
- std::vector<effect_descriptor_t> descs;
- EXPECT_EQ(OK, factory->getDescriptors(&FX_IID_AEC_, &descs));
- for (const auto& desc : descs) {
- ASSERT_EQ(0, std::memcmp(&desc.type, &FX_IID_AEC_, sizeof(FX_IID_AEC_)));
- sp<EffectHalInterface> interface;
- EXPECT_EQ(OK, factory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
- 1 /* deviceId */, &interface));
- EXPECT_NE(nullptr, interface);
- effect_param_t* param = (effect_param_t*)testDataBuffer;
- uint32_t type = AEC_PARAM_ECHO_DELAY, value = 0xbead;
- param->psize = sizeof(type);
- param->vsize = sizeof(value);
- //EXPECT_EQ(1, 0) << param->psize << " " << param->vsize;
- EffectParamWriter writer(*param);
- EXPECT_EQ(OK, writer.writeToParameter(&type)) << writer.toString();
- EXPECT_EQ(OK, writer.writeToValue(&value)) << writer.toString();
- status_t reply = 0;
- uint32_t replySize = sizeof(reply);
- EXPECT_NE(OK, interface->command(EFFECT_CMD_SET_PARAM, (uint32_t)writer.getTotalSize(),
- param, &replySize, &reply));
- EXPECT_EQ(replySize, sizeof(reply));
- EXPECT_NE(OK, reply);
+ std::shared_ptr<EffectParamReader> parameterSet; /* setParameter */
+ std::shared_ptr<EffectParamReader> parameterGet; /* getParameter */
+ std::shared_ptr<EffectParamReader> parameterExpect; /* expected from getParameter */
+ size_t valueSize; /* ValueSize expect to write in reply data buffer */
+
+ private:
+ std::vector<uint8_t> setBuffer;
+ std::vector<uint8_t> getBuffer;
+ std::vector<uint8_t> expectBuffer;
+
+ template <typename P, typename V>
+ EffectParamReader createEffectParam(void* buf, const P& p, const V& v) {
+ effect_param_t* paramRet = (effect_param_t*)buf;
+ paramRet->psize = sizeof(P);
+ paramRet->vsize = sizeof(V);
+ EffectParamWriter writer(*paramRet);
+ EXPECT_EQ(OK, writer.writeToParameter(&p));
+ EXPECT_EQ(OK, writer.writeToValue(&v));
+ writer.finishValueWrite();
+ return writer;
+ }
+};
+
+template <typename P, typename V>
+std::shared_ptr<EffectParamCombination> createEffectParamCombination(const P& p, const V& v,
+ size_t len) {
+ auto comb = std::make_shared<EffectParamCombination>();
+ comb->init(p, v, len);
+ return comb;
+}
+
+enum ParamName { TUPLE_UUID, TUPLE_PARAM_COMBINATION };
+using EffectParamTestTuple =
+ std::tuple<const effect_uuid_t* /* type UUID */, std::shared_ptr<EffectParamCombination>>;
+
+static const effect_uuid_t EXTEND_EFFECT_TYPE_UUID = {
+ 0xfa81dbde, 0x588b, 0x11ed, 0x9b6a, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+std::vector<EffectParamTestTuple> testPairs = {
+ std::make_tuple(FX_IID_AEC,
+ createEffectParamCombination(AEC_PARAM_ECHO_DELAY, 0xff /* echoDelayMs */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(FX_IID_AGC2, createEffectParamCombination(
+ AGC2_PARAM_FIXED_DIGITAL_GAIN, 15 /* digitalGainDb */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(SL_IID_BASSBOOST,
+ createEffectParamCombination(BASSBOOST_PARAM_STRENGTH, 20 /* strength */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(EFFECT_UIID_DOWNMIX,
+ createEffectParamCombination(DOWNMIX_PARAM_TYPE, DOWNMIX_TYPE_FOLD,
+ sizeof(int16_t) /* returnValueSize */)),
+ std::make_tuple(SL_IID_DYNAMICSPROCESSING,
+ createEffectParamCombination(
+ std::array<uint32_t, 2>({DP_PARAM_INPUT_GAIN, 0 /* channel */}),
+ 30 /* gainDb */, sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(
+ FX_IID_HAPTICGENERATOR,
+ createEffectParamCombination(
+ HG_PARAM_HAPTIC_INTENSITY,
+ std::array<uint32_t, 2>(
+ {1, uint32_t(::android::os::HapticScale::HIGH) /* scale */}),
+ 0 /* returnValueSize */)),
+ std::make_tuple(
+ FX_IID_LOUDNESS_ENHANCER,
+ createEffectParamCombination(LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB, 5 /* gain */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(FX_IID_NS,
+ createEffectParamCombination(NS_PARAM_LEVEL, 1 /* level */,
+ sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(&EXTEND_EFFECT_TYPE_UUID,
+ createEffectParamCombination(1, 0xbead, sizeof(int32_t)))};
+
+class libAudioHalEffectParamTest : public ::testing::TestWithParam<EffectParamTestTuple> {
+ public:
+ libAudioHalEffectParamTest()
+ : mParamTuple(GetParam()),
+ mFactory(EffectsFactoryHalInterface::create()),
+ mTypeUuid(std::get<TUPLE_UUID>(mParamTuple)),
+ mCombination(std::get<TUPLE_PARAM_COMBINATION>(mParamTuple)),
+ mExpectedValue([&]() {
+ std::vector<uint8_t> expectData(mCombination->valueSize);
+ mCombination->parameterExpect->readFromValue(expectData.data(),
+ mCombination->valueSize);
+ return expectData;
+ }()),
+ mDescs([&]() {
+ std::vector<effect_descriptor_t> descs;
+ if (mFactory && mTypeUuid && OK == mFactory->getDescriptors(mTypeUuid, &descs)) {
+ return descs;
+ }
+ return descs;
+ }()) {}
+
+ void SetUp() override {
+ ASSERT_NE(0ul, mDescs.size());
+ for (const auto& desc : mDescs) {
+ sp<EffectHalInterface> interface = createEffectHal(desc);
+ ASSERT_NE(nullptr, interface);
+ mHalInterfaces.push_back(interface);
+ }
+ }
+
+ void initEffect(const sp<EffectHalInterface>& interface) {
+ uint32_t initReply = 0;
+ uint32_t initReplySize = sizeof(initReply);
+ ASSERT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &initReplySize, &initReply));
+ }
+
+ void TearDown() override {
+ for (auto& interface : mHalInterfaces) {
+ interface->close();
+ }
+ }
+
+ sp<EffectHalInterface> createEffectHal(const effect_descriptor_t& desc) {
+ sp<EffectHalInterface> interface = nullptr;
+ if (0 == std::memcmp(&desc.type, mTypeUuid, sizeof(effect_uuid_t)) &&
+ OK == mFactory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
+ 1 /* deviceId */, &interface)) {
+ return interface;
+ }
+ return nullptr;
+ }
+
+ void setAndGetParameter(const sp<EffectHalInterface>& interface) {
+ uint32_t replySize = sizeof(uint32_t);
+ uint8_t reply[replySize];
+ auto parameterSet = mCombination->parameterSet;
+ ASSERT_EQ(OK,
+ interface->command(EFFECT_CMD_SET_PARAM, (uint32_t)parameterSet->getTotalSize(),
+ const_cast<effect_param_t*>(¶meterSet->getEffectParam()),
+ &replySize, &reply))
+ << parameterSet->toString();
+ ASSERT_EQ(replySize, sizeof(uint32_t));
+
+ effect_param_t* getParam =
+ const_cast<effect_param_t*>(&mCombination->parameterGet->getEffectParam());
+ size_t maxReplySize = mCombination->valueSize + sizeof(effect_param_t) +
+ sizeof(parameterSet->getPaddedParameterSize());
+ replySize = maxReplySize;
+ EXPECT_EQ(OK,
+ interface->command(EFFECT_CMD_GET_PARAM, (uint32_t)parameterSet->getTotalSize(),
+ const_cast<effect_param_t*>(¶meterSet->getEffectParam()),
+ &replySize, getParam));
+ EffectParamReader parameterGet(*getParam);
+ EXPECT_EQ(replySize, parameterGet.getTotalSize()) << parameterGet.toString();
+ if (mCombination->valueSize) {
+ std::vector<uint8_t> response(mCombination->valueSize);
+ EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
+ << " try get valueSize " << mCombination->valueSize << " from "
+ << parameterGet.toString();
+ EXPECT_EQ(response, mExpectedValue);
+ }
+ }
+
+ const EffectParamTestTuple mParamTuple;
+ const sp<EffectsFactoryHalInterface> mFactory;
+ const effect_uuid_t* mTypeUuid;
+ std::shared_ptr<EffectParamCombination> mCombination;
+ const std::vector<uint8_t> mExpectedValue;
+ const std::vector<effect_descriptor_t> mDescs;
+ std::vector<sp<EffectHalInterface>> mHalInterfaces;
+};
+
+TEST_P(libAudioHalEffectParamTest, setAndGetParam) {
+ for (auto& interface : mHalInterfaces) {
+ EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+ EXPECT_NO_FATAL_FAILURE(setAndGetParameter(interface));
}
}
-// TODO: rethink about this test case to make it general for all types of effects
-TEST(libAudioHalTest, aecInitSetAndGet) {
- auto factory = EffectsFactoryHalInterface::create();
- ASSERT_NE(nullptr, factory);
+INSTANTIATE_TEST_SUITE_P(
+ libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs),
+ [](const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) {
+ AudioUuid uuid = ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(
+ *std::get<TUPLE_UUID>(info.param))
+ .value();
+ std::string name = "UUID_" + uuid.toString();
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(libAudioHalEffectParamTest);
- std::vector<effect_descriptor_t> descs;
- EXPECT_EQ(OK, factory->getDescriptors(&FX_IID_AEC_, &descs));
- static constexpr uint32_t delayValue = 0x20;
- for (const auto& desc : descs) {
- ASSERT_EQ(0, std::memcmp(&desc.type, &FX_IID_AEC_, sizeof(effect_uuid_t)));
- sp<EffectHalInterface> interface;
- EXPECT_EQ(OK, factory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
- 1 /* deviceId */, &interface));
- EXPECT_NE(nullptr, interface);
- effect_param_t* param = (effect_param_t*)testDataBuffer;
- uint32_t type = AEC_PARAM_ECHO_DELAY, value = delayValue;
- param->psize = sizeof(type);
- param->vsize = sizeof(value);
- EffectParamWriter writer(*param);
- EXPECT_EQ(OK, writer.writeToParameter(&type)) << writer.toString();
- EXPECT_EQ(OK, writer.writeToValue(&value)) << writer.toString();
- status_t reply = 0;
- uint32_t replySize = sizeof(reply);
- EXPECT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &replySize, &reply));
- EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_PARAM, (uint32_t)writer.getTotalSize(),
- param, &replySize, &reply)) << writer.toString();
- EXPECT_EQ(replySize, sizeof(reply));
- EXPECT_EQ(OK, reply);
-
- effect_param_t* responseParam = (effect_param_t*)testResponseBuffer;
- param->psize = sizeof(type);
- param->vsize = sizeof(value);
- EffectParamWriter request(*param);
- EXPECT_EQ(OK, request.writeToParameter(&type)) << request.toString();
- replySize = request.getTotalSize();
- EXPECT_EQ(OK, interface->command(EFFECT_CMD_GET_PARAM, (uint32_t)writer.getTotalSize(),
- param, &replySize, responseParam));
- EffectParamReader response(*responseParam);
- EXPECT_EQ(replySize, response.getTotalSize()) << response.toString();
- EXPECT_EQ(OK, response.readFromValue(&value)) << response.toString();
- EXPECT_EQ(delayValue, value) << response.toString();
- }
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
}
+
// TODO: b/263986405 Add multi-thread testing
} // namespace android
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index 203a27b..4af5fd8 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -59,8 +59,34 @@
namespace aidl::android::hardware::audio::effect {
const std::string DynamicsProcessingImpl::kEffectName = "DynamicsProcessing";
-const DynamicsProcessing::Capability DynamicsProcessingImpl::kCapability = {.minCutOffFreq = 220,
- .maxCutOffFreq = 20000};
+
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMin =
+ DynamicsProcessing::EqBandConfig({.channel = 0,
+ .band = 0,
+ .enable = false,
+ .cutoffFrequencyHz = 220,
+ .gainDb = std::numeric_limits<float>::min()});
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMax =
+ DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
+ .band = std::numeric_limits<int>::max(),
+ .enable = true,
+ .cutoffFrequencyHz = 20000,
+ .gainDb = std::numeric_limits<float>::max()});
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPreEqBandRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPostEqBandRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+ {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range DynamicsProcessingImpl::kRange =
+ Range::make<Range::dynamicsProcessing>({DynamicsProcessingImpl::kPreEqBandRange});
+
+const Capability DynamicsProcessingImpl::kCapability = {.range = {DynamicsProcessingImpl::kRange}};
+
const Descriptor DynamicsProcessingImpl::kDescriptor = {
.common = {.id = {.type = kDynamicsProcessingTypeUUID,
.uuid = kDynamicsProcessingImplUUID,
@@ -70,8 +96,7 @@
.volume = Flags::Volume::CTRL},
.name = DynamicsProcessingImpl::kEffectName,
.implementor = "The Android Open Source Project"},
- .capability = Capability::make<Capability::dynamicsProcessing>(
- DynamicsProcessingImpl::kCapability)};
+ .capability = DynamicsProcessingImpl::kCapability};
ndk::ScopedAStatus DynamicsProcessingImpl::open(const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
@@ -138,6 +163,7 @@
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
auto& param = specific.get<Parameter::Specific::dynamicsProcessing>();
+ // TODO: check range here, dynamicsProcessing need customized method for nested parameters.
auto tag = param.getTag();
switch (tag) {
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
index 824ebea..26b6ead 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -28,7 +28,7 @@
public:
static const std::string kEffectName;
static const Descriptor kDescriptor;
- static const DynamicsProcessing::Capability kCapability;
+ static const Capability kCapability;
DynamicsProcessingImpl() { LOG(DEBUG) << __func__; }
~DynamicsProcessingImpl() {
@@ -52,6 +52,11 @@
std::string getEffectName() override { return kEffectName; }
private:
+ static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
+ static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
+ static const Range::DynamicsProcessingRange kPreEqBandRange;
+ static const Range::DynamicsProcessingRange kPostEqBandRange;
+ static const Range kRange;
std::shared_ptr<DynamicsProcessingContext> mContext;
ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
Parameter::Specific* specific);
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index 57a2be9..7978cc5 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -420,24 +420,18 @@
validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
}
-inline bool DynamicsProcessingContext::validateCutoffFrequency(float freq) {
- return freq >= DynamicsProcessingImpl::kCapability.minCutOffFreq &&
- freq <= DynamicsProcessingImpl::kCapability.maxCutOffFreq;
-}
-
bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
int maxChannel, int maxBand) {
- return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
- validateCutoffFrequency(band.cutoffFrequencyHz);
+ return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
}
bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
int maxChannel, int maxBand) {
return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
- validateCutoffFrequency(band.cutoffFrequencyHz) && validateTime(band.attackTimeMs) &&
- validateTime(band.releaseTimeMs) && validateRatio(band.ratio) &&
- validateBandDb(band.thresholdDb) && validateBandDb(band.kneeWidthDb) &&
- validateBandDb(band.noiseGateThresholdDb) && validateRatio(band.expanderRatio);
+ validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
+ validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
+ validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
+ validateRatio(band.expanderRatio);
}
bool DynamicsProcessingContext::validateLimiterConfig(
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index 0568fbd..de6d30b 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -14,6 +14,10 @@
defaults: [
"libeffects-test-defaults",
],
+ // TODO(b/269868814)
+ test_options: {
+ unit_test: false,
+ },
srcs: [
"EffectReverbTest.cpp",
],
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index c601c38..6124356 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -24,8 +24,9 @@
namespace aidl::android::hardware::audio::effect {
-using aidl::android::media::audio::common::AudioDeviceDescription;
-using aidl::android::media::audio::common::AudioDeviceType;
+using ::aidl::android::media::audio::common::AudioChannelLayout;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioDeviceType;
RetCode BundleContext::init() {
std::lock_guard lg(mMutex);
@@ -317,6 +318,11 @@
return true;
}
+bool BundleContext::isConfigSupportedVirtualizer(size_t channelCount,
+ const AudioDeviceDescription& device) {
+ return (channelCount >= 1 && channelCount <= FCC_2) && isDeviceSupportedVirtualizer({device});
+}
+
RetCode BundleContext::setOutputDevice(
const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
mOutputDevice = devices;
@@ -469,6 +475,23 @@
return bandLevels;
}
+std::vector<int32_t> BundleContext::getEqualizerCenterFreqs() {
+ std::vector<int32_t> freqs;
+
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ /* Get the current settings */
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms), freqs,
+ " getControlParamFailed");
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ freqs.push_back((int32_t)params.pEQNB_BandDefinition[i].Frequency * 1000);
+ }
+ }
+
+ return freqs;
+}
+
bool BundleContext::isBandLevelIndexInRange(
const std::vector<Equalizer::BandLevel>& bandLevels) const {
const auto [min, max] =
@@ -508,11 +531,6 @@
}
RetCode BundleContext::setBassBoostStrength(int strength) {
- if (strength < 0 || strength > lvm::kBassBoostCap.maxStrengthPm) {
- LOG(ERROR) << __func__ << " invalid strength: " << strength;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVM_ControlParams_t params;
{
@@ -532,10 +550,6 @@
}
RetCode BundleContext::setVolumeLevel(int level) {
- if (level < lvm::kVolumeCap.minLevelDb || level > lvm::kVolumeCap.maxLevelDb) {
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
if (mMuteEnabled) {
mLevelSaved = level / 100;
} else {
@@ -561,10 +575,6 @@
}
RetCode BundleContext::setVirtualizerStrength(int strength) {
- if (strength < 0 || strength > lvm::kVirtualizerCap.maxStrengthPm) {
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVM_ControlParams_t params;
{
@@ -583,6 +593,15 @@
return limitLevel();
}
+
+RetCode BundleContext::setForcedDevice(
+ const ::aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ RETURN_VALUE_IF(true != isDeviceSupportedVirtualizer({device}), RetCode::ERROR_EFFECT_LIB_ERROR,
+ " deviceNotSupportVirtualizer");
+ mForceDevice = device;
+ return RetCode::SUCCESS;
+}
+
void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
/* General parameters */
params.OperatingMode = LVM_MODE_ON;
@@ -668,6 +687,28 @@
return HeadroomBandDef;
}
+std::vector<Virtualizer::ChannelAngle> BundleContext::getSpeakerAngles(
+ const Virtualizer::SpeakerAnglesPayload payload) {
+ std::vector<Virtualizer::ChannelAngle> angles;
+ auto chCount = ::android::hardware::audio::common::getChannelCount(payload.layout);
+ RETURN_VALUE_IF(!isConfigSupportedVirtualizer(chCount, payload.device), angles,
+ "payloadNotSupported");
+
+ if (chCount == 1) {
+ angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
+ .azimuthDegree = 0,
+ .elevationDegree = 0}};
+ } else {
+ angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
+ .azimuthDegree = -90,
+ .elevationDegree = 0},
+ {.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_RIGHT,
+ .azimuthDegree = 90,
+ .elevationDegree = 0}};
+ }
+ return angles;
+}
+
IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
IEffect::Status status = {EX_NULL_POINTER, 0, 0};
RETURN_VALUE_IF(!in, status, "nullInput");
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 1f328fc..47d5e5a 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -62,6 +62,10 @@
bool isDeviceSupportedVirtualizer(
const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>&
devices);
+ bool isConfigSupportedVirtualizer(
+ size_t channelCount,
+ const aidl::android::media::audio::common::AudioDeviceDescription& device);
+
RetCode setOutputDevice(
const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices)
override;
@@ -71,6 +75,8 @@
RetCode setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
std::vector<Equalizer::BandLevel> getEqualizerBandLevels() const;
+ std::vector<int32_t> getEqualizerCenterFreqs();
+
RetCode setBassBoostStrength(int strength);
int getBassBoostStrength() const { return mBassStrengthSaved; }
@@ -83,6 +89,14 @@
RetCode setVirtualizerStrength(int strength);
int getVirtualizerStrength() const { return mVirtStrengthSaved; }
+ RetCode setForcedDevice(
+ const ::aidl::android::media::audio::common::AudioDeviceDescription& device);
+ aidl::android::media::audio::common::AudioDeviceDescription getForcedDevice() const {
+ return mForceDevice;
+ }
+ std::vector<Virtualizer::ChannelAngle> getSpeakerAngles(
+ const Virtualizer::SpeakerAnglesPayload payload);
+
RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
@@ -125,6 +139,7 @@
// Virtualizer
int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
bool mVirtualizerTempDisabled = false;
+ ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice;
// Volume
int mLevelSaved = 0; /* for when mute is set, level must be saved */
int mVolume = 0;
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 1996240..4652d8d 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -67,46 +67,53 @@
{0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
{5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
-static const Equalizer::Capability kEqCap = {.bandFrequencies = kEqBandFrequency,
- .presets = kEqPresets};
+const std::vector<Range::EqualizerRange> kEqRanges = {
+ MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
+ MAKE_RANGE(
+ Equalizer, bandLevels,
+ std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
+ {.index = 0, .levelMb = std::numeric_limits<int>::min()})},
+ std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
+ {.index = MAX_NUM_BANDS - 1, .levelMb = std::numeric_limits<int>::max()})}),
+ /* capability definition */
+ MAKE_RANGE(Equalizer, bandFrequencies, kEqBandFrequency, kEqBandFrequency),
+ MAKE_RANGE(Equalizer, presets, kEqPresets, kEqPresets),
+ /* get only parameters with range min > max */
+ MAKE_RANGE(Equalizer, centerFreqMh, std::vector<int>({1}), std::vector<int>({}))};
+static const Capability kEqCap = {.range = kEqRanges};
static const std::string kEqualizerEffectName = "EqualizerBundle";
+static const Descriptor kEqualizerDesc = {.common = {.id = {.type = kEqualizerTypeUUID,
+ .uuid = kEqualizerBundleImplUUID,
+ .proxy = kEqualizerProxyUUID},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = kEqualizerEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kEqCap};
-static const Descriptor kEqualizerDesc = {
- .common = {.id = {.type = kEqualizerTypeUUID,
- .uuid = kEqualizerBundleImplUUID,
- .proxy = kEqualizerProxyUUID},
- .flags = {.type = Flags::Type::INSERT,
- .insert = Flags::Insert::FIRST,
- .volume = Flags::Volume::CTRL},
- .name = kEqualizerEffectName,
- .implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::equalizer>(kEqCap)};
-
-static const bool mStrengthSupported = true;
-
-static const BassBoost::Capability kBassBoostCap = {.maxStrengthPm = 1000,
- .strengthSupported = mStrengthSupported};
-
+static const int mMaxStrengthSupported = 1000;
+static const std::vector<Range::BassBoostRange> kBassBoostRanges = {
+ MAKE_RANGE(BassBoost, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kBassBoostCap = {.range = kBassBoostRanges};
static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
+static const Descriptor kBassBoostDesc = {.common = {.id = {.type = kBassBoostTypeUUID,
+ .uuid = kBassBoostBundleImplUUID,
+ .proxy = kBassBoostProxyUUID},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL,
+ .deviceIndication = true},
+ .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kBassBoostEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kBassBoostCap};
-static const Descriptor kBassBoostDesc = {
- .common = {.id = {.type = kBassBoostTypeUUID,
- .uuid = kBassBoostBundleImplUUID,
- .proxy = kBassBoostProxyUUID},
- .flags = {.type = Flags::Type::INSERT,
- .insert = Flags::Insert::FIRST,
- .volume = Flags::Volume::CTRL,
- .deviceIndication = true},
- .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
- .memoryUsage = BUNDLE_MEM_USAGE,
- .name = kBassBoostEffectName,
- .implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::bassBoost>(kBassBoostCap)};
-
-static const Virtualizer::Capability kVirtualizerCap = {.maxStrengthPm = 1000,
- .strengthSupported = mStrengthSupported};
-
+static const std::vector<Range::VirtualizerRange> kVirtualizerRanges = {
+ MAKE_RANGE(Virtualizer, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kVirtualizerCap = {.range = kVirtualizerRanges};
static const std::string kVirtualizerEffectName = "Virtualizer";
static const Descriptor kVirtualizerDesc = {
@@ -121,24 +128,23 @@
.memoryUsage = BUNDLE_MEM_USAGE,
.name = kVirtualizerEffectName,
.implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::virtualizer>(kVirtualizerCap)};
+ .capability = kVirtualizerCap};
-static const Volume::Capability kVolumeCap = {.minLevelDb = -9600, .maxLevelDb = 0};
-
+static const std::vector<Range::VolumeRange> kVolumeRanges = {
+ MAKE_RANGE(Volume, levelDb, -9600, 0)};
+static const Capability kVolumeCap = {.range = kVolumeRanges};
static const std::string kVolumeEffectName = "Volume";
-
-static const Descriptor kVolumeDesc = {
- .common = {.id = {.type = kVolumeTypeUUID,
- .uuid = kVolumeBundleImplUUID,
- .proxy = std::nullopt},
- .flags = {.type = Flags::Type::INSERT,
- .insert = Flags::Insert::LAST,
- .volume = Flags::Volume::CTRL},
- .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
- .memoryUsage = BUNDLE_MEM_USAGE,
- .name = kVolumeEffectName,
- .implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::volume>(kVolumeCap)};
+static const Descriptor kVolumeDesc = {.common = {.id = {.type = kVolumeTypeUUID,
+ .uuid = kVolumeBundleImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL},
+ .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kVolumeEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kVolumeCap};
/* The following tables have been computed using the actual levels measured by the output of
* white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index 81b8aca..dc52c16 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "BundleTypes.h"
#define LOG_TAG "EffectBundleAidl"
#include <Utils.h>
#include <algorithm>
@@ -173,6 +174,7 @@
ndk::ScopedAStatus EffectBundleAidl::setParameterEqualizer(const Parameter::Specific& specific) {
auto& eq = specific.get<Parameter::Specific::equalizer>();
+ RETURN_IF(!inRange(eq, lvm::kEqRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto eqTag = eq.getTag();
switch (eqTag) {
case Equalizer::preset:
@@ -193,6 +195,7 @@
ndk::ScopedAStatus EffectBundleAidl::setParameterBassBoost(const Parameter::Specific& specific) {
auto& bb = specific.get<Parameter::Specific::bassBoost>();
+ RETURN_IF(!inRange(bb, lvm::kBassBoostRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto bbTag = bb.getTag();
switch (bbTag) {
case BassBoost::strengthPm: {
@@ -210,6 +213,7 @@
ndk::ScopedAStatus EffectBundleAidl::setParameterVirtualizer(const Parameter::Specific& specific) {
auto& vr = specific.get<Parameter::Specific::virtualizer>();
+ RETURN_IF(!inRange(vr, lvm::kVirtualizerRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto vrTag = vr.getTag();
switch (vrTag) {
case Virtualizer::strengthPm: {
@@ -218,15 +222,24 @@
EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
return ndk::ScopedAStatus::ok();
}
- default:
- LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ case Virtualizer::device: {
+ RETURN_IF(mContext->setForcedDevice(vr.get<Virtualizer::device>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Virtualizer::speakerAngles:
+ FALLTHROUGH_INTENDED;
+ case Virtualizer::vendor: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(vrTag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "vrTagNotSupported");
+ "VirtualizerTagNotSupported");
+ }
}
}
ndk::ScopedAStatus EffectBundleAidl::setParameterVolume(const Parameter::Specific& specific) {
auto& vol = specific.get<Parameter::Specific::volume>();
+ RETURN_IF(!inRange(vol, lvm::kVolumeRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto volTag = vol.getTag();
switch (volTag) {
case Volume::levelDb: {
@@ -283,6 +296,10 @@
eqParam.set<Equalizer::preset>(mContext->getEqualizerPreset());
break;
}
+ case Equalizer::centerFreqMh: {
+ eqParam.set<Equalizer::centerFreqMh>(mContext->getEqualizerCenterFreqs());
+ break;
+ }
default: {
LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
@@ -354,14 +371,27 @@
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
Virtualizer vrParam;
+ if (id.getTag() == Virtualizer::Id::speakerAnglesPayload) {
+ auto angles = mContext->getSpeakerAngles(id.get<Virtualizer::Id::speakerAnglesPayload>());
+ Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
+ specific->set<Parameter::Specific::virtualizer>(param);
+ return ndk::ScopedAStatus::ok();
+ }
+
auto tag = id.get<Virtualizer::Id::commonTag>();
switch (tag) {
case Virtualizer::strengthPm: {
vrParam.set<Virtualizer::strengthPm>(mContext->getVirtualizerStrength());
break;
}
- default: {
- LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ case Virtualizer::device: {
+ vrParam.set<Virtualizer::device>(mContext->getForcedDevice());
+ break;
+ }
+ case Virtualizer::speakerAngles:
+ FALLTHROUGH_INTENDED;
+ case Virtualizer::vendor: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
"VirtualizerTagNotSupported");
}
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
index 51825ca..e9bdf94 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "ReverbTypes.h"
#define LOG_TAG "EffectReverb"
#include <Utils.h>
#include <algorithm>
@@ -132,6 +133,7 @@
ndk::ScopedAStatus EffectReverb::setParameterPresetReverb(const Parameter::Specific& specific) {
auto& prParam = specific.get<Parameter::Specific::presetReverb>();
+ RETURN_IF(!inRange(prParam, lvm::kPresetReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto tag = prParam.getTag();
switch (tag) {
@@ -152,6 +154,7 @@
ndk::ScopedAStatus EffectReverb::setParameterEnvironmentalReverb(
const Parameter::Specific& specific) {
auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
+ RETURN_IF(!inRange(erParam, lvm::kEnvReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto tag = erParam.getTag();
switch (tag) {
@@ -181,6 +184,20 @@
EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
return ndk::ScopedAStatus::ok();
}
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ RETURN_IF(mContext->setReflectionsLevel(
+ erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ RETURN_IF(mContext->setReflectionsDelay(
+ erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
+ return ndk::ScopedAStatus::ok();
+ }
case EnvironmentalReverb::levelMb: {
RETURN_IF(mContext->setEnvironmentalReverbLevel(
erParam.get<EnvironmentalReverb::levelMb>()) != RetCode::SUCCESS,
@@ -289,6 +306,14 @@
mContext->getEnvironmentalReverbDecayHfRatio());
break;
}
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getReflectionsLevel());
+ break;
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getReflectionsDelay());
+ break;
+ }
case EnvironmentalReverb::levelMb: {
erParam.set<EnvironmentalReverb::levelMb>(mContext->getEnvironmentalReverbLevel());
break;
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
index d35c22b..87aa12b 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
@@ -139,12 +139,6 @@
}
RetCode ReverbContext::setEnvironmentalReverbRoomLevel(int roomLevel) {
- if (roomLevel < lvm::kEnvReverbCap.minRoomLevelMb ||
- roomLevel > lvm::kEnvReverbCap.maxRoomLevelMb) {
- LOG(ERROR) << __func__ << " invalid roomLevel: " << roomLevel;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVREV_ControlParams_st params;
{
@@ -165,12 +159,6 @@
}
RetCode ReverbContext::setEnvironmentalReverbRoomHfLevel(int roomHfLevel) {
- if (roomHfLevel < lvm::kEnvReverbCap.minRoomHfLevelMb ||
- roomHfLevel > lvm::kEnvReverbCap.maxRoomHfLevelMb) {
- LOG(ERROR) << __func__ << " invalid roomHfLevel: " << roomHfLevel;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVREV_ControlParams_st params;
{
@@ -188,10 +176,6 @@
}
RetCode ReverbContext::setEnvironmentalReverbDecayTime(int decayTime) {
- if (decayTime < 0 || decayTime > lvm::kEnvReverbCap.maxDecayTimeMs) {
- LOG(ERROR) << __func__ << " invalid decayTime: " << decayTime;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
int time = decayTime;
if (time > lvm::kMaxT60) {
time = lvm::kMaxT60;
@@ -215,12 +199,6 @@
}
RetCode ReverbContext::setEnvironmentalReverbDecayHfRatio(int decayHfRatio) {
- if (decayHfRatio < lvm::kEnvReverbCap.minDecayHfRatioPm ||
- decayHfRatio > lvm::kEnvReverbCap.maxDecayHfRatioPm) {
- LOG(ERROR) << __func__ << " invalid decayHfRatio: " << decayHfRatio;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVREV_ControlParams_st params;
{
@@ -238,11 +216,6 @@
}
RetCode ReverbContext::setEnvironmentalReverbLevel(int level) {
- if (level < lvm::kEnvReverbCap.minLevelMb || level > lvm::kEnvReverbCap.maxLevelMb) {
- LOG(ERROR) << __func__ << " invalid level: " << level;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVREV_ControlParams_st params;
{
@@ -263,20 +236,11 @@
}
RetCode ReverbContext::setEnvironmentalReverbDelay(int delay) {
- if (delay < 0 || delay > lvm::kEnvReverbCap.maxDelayMs) {
- LOG(ERROR) << __func__ << " invalid delay: " << delay;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
mDelay = delay;
return RetCode::SUCCESS;
}
RetCode ReverbContext::setEnvironmentalReverbDiffusion(int diffusion) {
- if (diffusion < 0 || diffusion > lvm::kEnvReverbCap.maxDiffusionPm) {
- LOG(ERROR) << __func__ << " invalid diffusion: " << diffusion;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVREV_ControlParams_st params;
{
@@ -294,11 +258,6 @@
}
RetCode ReverbContext::setEnvironmentalReverbDensity(int density) {
- if (density < 0 || density > lvm::kEnvReverbCap.maxDensityPm) {
- LOG(ERROR) << __func__ << " invalid density: " << density;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
// Update Control Parameter
LVREV_ControlParams_st params;
{
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
index af49a25..9bb0b1a 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
@@ -83,6 +83,18 @@
RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+ RetCode setReflectionsDelay(int delay) {
+ mReflectionsDelayMs = delay;
+ return RetCode::SUCCESS;
+ }
+ bool getReflectionsDelay() const { return mReflectionsDelayMs; }
+
+ RetCode setReflectionsLevel(int level) {
+ mReflectionsLevelMb = level;
+ return RetCode::SUCCESS;
+ }
+ bool getReflectionsLevel() const { return mReflectionsLevelMb; }
+
IEffect::Status lvmProcess(float* in, float* out, int samples);
private:
@@ -146,15 +158,17 @@
bool mEnabled = false;
LVREV_Handle_t mInstance GUARDED_BY(mMutex);
- int mRoomLevel;
- int mRoomHfLevel;
- int mDecayTime;
- int mDecayHfRatio;
- int mLevel;
- int mDelay;
- int mDiffusion;
- int mDensity;
- bool mBypass;
+ int mRoomLevel = 0;
+ int mRoomHfLevel = 0;
+ int mDecayTime = 0;
+ int mDecayHfRatio = 0;
+ int mLevel = 0;
+ int mDelay = 0;
+ int mDiffusion = 0;
+ int mDensity = 0;
+ bool mBypass = 0;
+ int mReflectionsLevelMb = 0;
+ int mReflectionsDelayMs = 0;
PresetReverb::Presets mPreset;
PresetReverb::Presets mNextPreset;
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
index e37602c..8dcda87 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
@@ -21,6 +21,7 @@
#include <audio_effects/effect_environmentalreverb.h>
#include <audio_effects/effect_presetreverb.h>
#include "effect-impl/EffectUUID.h"
+#include "effect-impl/EffectTypes.h"
// from Reverb/lib
#include "LVREV.h"
@@ -35,51 +36,51 @@
constexpr inline int kCpuLoadARM9E = 470; // Expressed in 0.1 MIPS
constexpr inline int kMemUsage = (71 + (kMaxFrameSize >> 7)); // Expressed in kB
-static const EnvironmentalReverb::Capability kEnvReverbCap = {.minRoomLevelMb = lvm::kMinLevel,
- .maxRoomLevelMb = 0,
- .minRoomHfLevelMb = -4000,
- .maxRoomHfLevelMb = 0,
- .maxDecayTimeMs = lvm::kMaxT60,
- .minDecayHfRatioPm = 100,
- .maxDecayHfRatioPm = 2000,
- .minLevelMb = lvm::kMinLevel,
- .maxLevelMb = 0,
- .maxDelayMs = 65,
- .maxDiffusionPm = 1000,
- .maxDensityPm = 1000};
+static const std::vector<Range::EnvironmentalReverbRange> kEnvReverbRanges = {
+ MAKE_RANGE(EnvironmentalReverb, roomLevelMb, lvm::kMinLevel, 0),
+ MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
+ MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, lvm::kMaxT60),
+ MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
+ MAKE_RANGE(EnvironmentalReverb, levelMb, lvm::kMinLevel, 0),
+ MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
+ MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
+ MAKE_RANGE(EnvironmentalReverb, densityPm, 0, 1000)};
+static const Capability kEnvReverbCap = {
+ .range = Range::make<Range::environmentalReverb>(kEnvReverbRanges)};
// NXP SW auxiliary environmental reverb
static const std::string kAuxEnvReverbEffectName = "Auxiliary Environmental Reverb";
-static const Descriptor kAuxEnvReverbDesc = {
- .common = {.id = {.type = kEnvReverbTypeUUID,
- .uuid = kAuxEnvReverbImplUUID,
- .proxy = std::nullopt},
- .flags = {.type = Flags::Type::AUXILIARY},
- .cpuLoad = kCpuLoadARM9E,
- .memoryUsage = kMemUsage,
- .name = kAuxEnvReverbEffectName,
- .implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::environmentalReverb>(kEnvReverbCap)};
+static const Descriptor kAuxEnvReverbDesc = {.common = {.id = {.type = kEnvReverbTypeUUID,
+ .uuid = kAuxEnvReverbImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::AUXILIARY},
+ .cpuLoad = kCpuLoadARM9E,
+ .memoryUsage = kMemUsage,
+ .name = kAuxEnvReverbEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kEnvReverbCap};
// NXP SW insert environmental reverb
static const std::string kInsertEnvReverbEffectName = "Insert Environmental Reverb";
-static const Descriptor kInsertEnvReverbDesc = {
- .common = {.id = {.type = kEnvReverbTypeUUID,
- .uuid = kInsertEnvReverbImplUUID,
- .proxy = std::nullopt},
- .flags = {.type = Flags::Type::INSERT,
- .insert = Flags::Insert::FIRST,
- .volume = Flags::Volume::CTRL},
- .cpuLoad = kCpuLoadARM9E,
- .memoryUsage = kMemUsage,
- .name = kInsertEnvReverbEffectName,
- .implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::environmentalReverb>(kEnvReverbCap)};
+static const Descriptor kInsertEnvReverbDesc = {.common = {.id = {.type = kEnvReverbTypeUUID,
+ .uuid = kInsertEnvReverbImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .cpuLoad = kCpuLoadARM9E,
+ .memoryUsage = kMemUsage,
+ .name = kInsertEnvReverbEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = kEnvReverbCap};
static const std::vector<PresetReverb::Presets> kSupportedPresets{
ndk::enum_range<PresetReverb::Presets>().begin(),
ndk::enum_range<PresetReverb::Presets>().end()};
-static const PresetReverb::Capability kPresetReverbCap = {.supportedPresets = kSupportedPresets};
+static const std::vector<Range::PresetReverbRange> kPresetReverbRanges = {
+ MAKE_RANGE(PresetReverb, supportedPresets, kSupportedPresets, kSupportedPresets)};
+static const Capability kPresetReverbCap = {
+ .range = Range::make<Range::presetReverb>(kPresetReverbRanges)};
// NXP SW auxiliary preset reverb
static const std::string kAuxPresetReverbEffectName = "Auxiliary Preset Reverb";
@@ -92,7 +93,7 @@
.memoryUsage = kMemUsage,
.name = kAuxPresetReverbEffectName,
.implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::presetReverb>(kPresetReverbCap)};
+ .capability = kPresetReverbCap};
// NXP SW insert preset reverb
static const std::string kInsertPresetReverbEffectName = "Insert Preset Reverb";
@@ -107,7 +108,7 @@
.memoryUsage = kMemUsage,
.name = kInsertPresetReverbEffectName,
.implementor = "NXP Software Ltd."},
- .capability = Capability::make<Capability::presetReverb>(kPresetReverbCap)};
+ .capability = kPresetReverbCap};
enum class ReverbEffectType {
AUX_ENV,
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
index 28a7287..6e7833c 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.cpp
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -54,9 +54,16 @@
namespace aidl::android::hardware::audio::effect {
const std::string VisualizerImpl::kEffectName = "Visualizer";
-const Visualizer::Capability VisualizerImpl::kCapability = {
- .maxLatencyMs = VisualizerContext::kMaxLatencyMs,
- .captureSampleRange = {.min = 0, .max = VisualizerContext::kMaxCaptureBufSize}};
+const std::vector<Range::VisualizerRange> VisualizerImpl::kRanges = {
+ MAKE_RANGE(Visualizer, latencyMs, 0, VisualizerContext::kMaxLatencyMs),
+ MAKE_RANGE(Visualizer, captureSamples, 0, VisualizerContext::kMaxCaptureBufSize),
+ /* get only parameters, set invalid range (min > max) to indicate not support set */
+ MAKE_RANGE(Visualizer, measurement, Visualizer::Measurement({.peak = 1, .rms = 1}),
+ Visualizer::Measurement({.peak = 0, .rms = 0})),
+ MAKE_RANGE(Visualizer, captureSampleBuffer, std::vector<uint8_t>({1}),
+ std::vector<uint8_t>({0}))};
+const Capability VisualizerImpl::kCapability = {
+ .range = Range::make<Range::visualizer>(VisualizerImpl::kRanges)};
const Descriptor VisualizerImpl::kDescriptor = {
.common = {.id = {.type = kVisualizerTypeUUID,
.uuid = kVisualizerImplUUID,
@@ -66,7 +73,7 @@
.volume = Flags::Volume::CTRL},
.name = VisualizerImpl::kEffectName,
.implementor = "The Android Open Source Project"},
- .capability = Capability::make<Capability::visualizer>(VisualizerImpl::kCapability)};
+ .capability = VisualizerImpl::kCapability};
ndk::ScopedAStatus VisualizerImpl::getDescriptor(Descriptor* _aidl_return) {
RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
@@ -96,32 +103,13 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus VisualizerImpl::setOnlyParameter(
- const Visualizer::SetOnlyParameters& param) {
- auto tag = param.getTag();
- switch (tag) {
- case Visualizer::SetOnlyParameters::latencyMs: {
- RETURN_IF(mContext->setDownstreamLatency(
- param.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
- RetCode::SUCCESS,
- EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
- break;
- }
- default: {
- LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
- EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
- }
- }
- return ndk::ScopedAStatus::ok();
-}
-
ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
auto& param = specific.get<Parameter::Specific::visualizer>();
+ RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
const auto tag = param.getTag();
switch (tag) {
case Visualizer::captureSamples: {
@@ -142,8 +130,11 @@
EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
return ndk::ScopedAStatus::ok();
}
- case Visualizer::setOnlyParameters: {
- return setOnlyParameter(param.get<Visualizer::setOnlyParameters>());
+ case Visualizer::latencyMs: {
+ RETURN_IF(mContext->setDownstreamLatency(param.get<Visualizer::latencyMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
+ return ndk::ScopedAStatus::ok();
}
default: {
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
@@ -153,30 +144,6 @@
}
}
-ndk::ScopedAStatus VisualizerImpl::getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
- Parameter::Specific* specific) {
- Visualizer visualizer;
- Visualizer::GetOnlyParameters param;
- switch (tag) {
- case Visualizer::GetOnlyParameters::measurement: {
- param.set<Visualizer::GetOnlyParameters::measurement>(mContext->getMeasure());
- break;
- }
- case Visualizer::GetOnlyParameters::captureSampleBuffer: {
- param.set<Visualizer::GetOnlyParameters::captureSampleBuffer>(mContext->capture());
- break;
- }
- default: {
- LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
- EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
- }
- }
- visualizer.set<Visualizer::getOnlyParameters>(param);
- specific->set<Parameter::Specific::visualizer>(visualizer);
- return ndk::ScopedAStatus::ok();
-}
-
ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
Parameter::Specific* specific) {
RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
@@ -188,9 +155,6 @@
case Visualizer::Id::commonTag: {
return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
}
- case Visualizer::Id::getOnlyParamTag: {
- return getOnlyParameter(specificId.get<Visualizer::Id::getOnlyParamTag>(), specific);
- }
default: {
LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -218,6 +182,18 @@
param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
break;
}
+ case Visualizer::measurement: {
+ param.set<Visualizer::measurement>(mContext->getMeasure());
+ break;
+ }
+ case Visualizer::captureSampleBuffer: {
+ param.set<Visualizer::captureSampleBuffer>(mContext->capture());
+ break;
+ }
+ case Visualizer::latencyMs: {
+ param.set<Visualizer::latencyMs>(mContext->getDownstreamLatency());
+ break;
+ }
default: {
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
index 5908d9a..f6e1d6d 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.h
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -28,7 +28,7 @@
class VisualizerImpl final : public EffectImpl {
public:
static const std::string kEffectName;
- static const Visualizer::Capability kCapability;
+ static const Capability kCapability;
static const Descriptor kDescriptor;
VisualizerImpl() { LOG(DEBUG) << __func__; }
~VisualizerImpl() {
@@ -49,12 +49,10 @@
std::string getEffectName() override { return kEffectName; }
private:
+ static const std::vector<Range::VisualizerRange> kRanges;
std::shared_ptr<VisualizerContext> mContext;
ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
Parameter::Specific* specific);
- ndk::ScopedAStatus setOnlyParameter(const Visualizer::SetOnlyParameters& param);
- ndk::ScopedAStatus getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
- Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
index 1965e0e..4405407 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.cpp
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -88,11 +88,6 @@
RetCode VisualizerContext::setCaptureSamples(int samples) {
std::lock_guard lg(mMutex);
- if (samples < 0 || (unsigned)samples > kMaxCaptureBufSize) {
- LOG(ERROR) << __func__ << " captureSamples " << samples << " exceed valid range: 0 - "
- << kMaxCaptureBufSize;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
mCaptureSamples = samples;
return RetCode::SUCCESS;
}
@@ -122,16 +117,16 @@
}
RetCode VisualizerContext::setDownstreamLatency(int latency) {
- if (latency < 0 || (unsigned)latency > kMaxLatencyMs) {
- LOG(ERROR) << __func__ << " latency " << latency << " exceed valid range: 0 - "
- << kMaxLatencyMs;
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
std::lock_guard lg(mMutex);
mDownstreamLatency = latency;
return RetCode::SUCCESS;
}
+int VisualizerContext::getDownstreamLatency() {
+ std::lock_guard lg(mMutex);
+ return mDownstreamLatency;
+}
+
uint32_t VisualizerContext::getDeltaTimeMsFromUpdatedTime_l() {
uint32_t deltaMs = 0;
if (mBufferUpdateTime.tv_sec != 0) {
@@ -149,7 +144,7 @@
return deltaMs;
}
-Visualizer::GetOnlyParameters::Measurement VisualizerContext::getMeasure() {
+Visualizer::Measurement VisualizerContext::getMeasure() {
uint16_t peakU16 = 0;
float sumRmsSquared = 0.0f;
uint8_t nbValidMeasurements = 0;
@@ -184,7 +179,7 @@
}
float rms = nbValidMeasurements == 0 ? 0.0f : sqrtf(sumRmsSquared / nbValidMeasurements);
- Visualizer::GetOnlyParameters::Measurement measure;
+ Visualizer::Measurement measure;
// convert from I16 sample values to mB and write results
measure.rms = (rms < 0.000016f) ? -9600 : (int32_t)(2000 * log10(rms / 32767.0f));
measure.peak = (peakU16 == 0) ? -9600 : (int32_t)(2000 * log10(peakU16 / 32767.0f));
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.h b/media/libeffects/visualizer/aidl/VisualizerContext.h
index bfda0b9..3cb711e 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.h
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.h
@@ -45,10 +45,11 @@
RetCode setScalingMode(Visualizer::ScalingMode mode);
Visualizer::ScalingMode getScalingMode();
RetCode setDownstreamLatency(int latency);
+ int getDownstreamLatency();
IEffect::Status process(float* in, float* out, int samples);
// Gets the current measurements, measured by process() and consumed by getParameter()
- Visualizer::GetOnlyParameters::Measurement getMeasure();
+ Visualizer::Measurement getMeasure();
// Gets the latest PCM capture, data captured by process() and consumed by getParameter()
std::vector<uint8_t> capture();
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 154988d..e191999 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -428,7 +428,7 @@
return reply.readInt32();
}
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
ALOGV("getActiveMicrophones");
Parcel data, reply;
@@ -756,7 +756,7 @@
case GET_ACTIVE_MICROPHONES: {
ALOGV("GET_ACTIVE_MICROPHONES");
CHECK_INTERFACE(IMediaRecorder, data, reply);
- std::vector<media::MicrophoneInfo> activeMicrophones;
+ std::vector<media::MicrophoneInfoFw> activeMicrophones;
status_t status = getActiveMicrophones(&activeMicrophones);
reply->writeInt32(status);
if (status != NO_ERROR) {
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 85768bd..5aa9adc 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -898,10 +898,9 @@
}
}
- for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) {
+ for (size_t refIndex = 0; refIndex < mCameraIds.size(); ++refIndex) {
+ const int cameraId = mCameraIds[refIndex];
for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
- int refIndex = getRequiredProfileRefIndex(cameraId);
- CHECK(refIndex != -1);
RequiredProfileRefInfo *info =
&mRequiredProfileRefs[refIndex].mRefs[j];
@@ -931,14 +930,14 @@
int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
if (index != -1) {
- ALOGV("Profile quality %d for camera %zu already exists",
+ ALOGV("Profile quality %d for camera %d already exists",
profile->mQuality, cameraId);
CHECK(index == refIndex);
continue;
}
// Insert the new profile
- ALOGV("Add a profile: quality %d=>%d for camera %zu",
+ ALOGV("Add a profile: quality %d=>%d for camera %d",
mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
profile->mQuality, cameraId);
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 6e69782..05da5c2 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -18,8 +18,8 @@
#ifndef ANDROID_IMEDIARECORDER_H
#define ANDROID_IMEDIARECORDER_H
+#include <android/media/MicrophoneInfoFw.h>
#include <binder/IInterface.h>
-#include <media/MicrophoneInfo.h>
#include <system/audio.h>
#include <vector>
@@ -74,7 +74,7 @@
virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) = 0;
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) = 0;
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 2b7818d..82ec9c5 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -19,7 +19,6 @@
#define MEDIA_RECORDER_BASE_H_
#include <media/AudioSystem.h>
-#include <media/MicrophoneInfo.h>
#include <media/mediarecorder.h>
#include <android/content/AttributionSourceState.h>
@@ -74,7 +73,7 @@
virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) = 0;
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) = 0;
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) const = 0;
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index dd18144..602f72e 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -24,7 +24,7 @@
#include <utils/Errors.h>
#include <media/IMediaRecorderClient.h>
#include <media/IMediaDeathNotifier.h>
-#include <media/MicrophoneInfo.h>
+#include <android/media/MicrophoneInfoFw.h>
#include <android/content/AttributionSourceState.h>
namespace android {
@@ -268,7 +268,7 @@
status_t setInputDevice(audio_port_handle_t deviceId);
status_t getRoutedDeviceId(audio_port_handle_t *deviceId);
status_t enableAudioDeviceCallback(bool enabled);
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index cf12c36..bd06fb6 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -884,7 +884,8 @@
return mMediaRecorder->enableAudioDeviceCallback(enabled);
}
-status_t MediaRecorder::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+status_t MediaRecorder::getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
ALOGV("getActiveMicrophones");
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 4aa80be..58fc06d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -563,7 +563,7 @@
}
status_t MediaRecorderClient::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
ALOGV("getActiveMicrophones");
Mutex::Autolock lock(mLock);
if (mRecorder != NULL) {
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index dcb9f82..dec0c99 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -83,7 +83,7 @@
virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
virtual status_t enableAudioDeviceCallback(bool enabled);
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones);
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) override;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index a0bc8ca..18bbf7b 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -2560,7 +2560,7 @@
}
status_t StagefrightRecorder::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
if (mAudioSourceNode != 0) {
return mAudioSourceNode->getActiveMicrophones(activeMicrophones);
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index d7785da..67c6e20 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -83,7 +83,7 @@
virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
virtual status_t enableAudioDeviceCallback(bool enabled);
- virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) const override;
diff --git a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
index b0040fe..43b3c37 100644
--- a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
+++ b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
@@ -193,7 +193,7 @@
mStfRecorder->setInputDevice(deviceId);
mStfRecorder->getRoutedDeviceId(&deviceId);
- vector<android::media::MicrophoneInfo> activeMicrophones{};
+ vector<android::media::MicrophoneInfoFw> activeMicrophones{};
mStfRecorder->getActiveMicrophones(&activeMicrophones);
int32_t portId;
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
index 162c187..9514021 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
@@ -286,7 +286,7 @@
// Record media for 4 secs
std::this_thread::sleep_for(std::chrono::seconds(kClipDurationInSec));
- std::vector<media::MicrophoneInfo> activeMicrophones{};
+ std::vector<media::MicrophoneInfoFw> activeMicrophones{};
status = mStfRecorder->getActiveMicrophones(&activeMicrophones);
ASSERT_EQ(status, OK) << "Failed to get Active Microphones";
ASSERT_GT(activeMicrophones.size(), 0) << "No active microphones are found";
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index bfe8538..584dad6 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -522,7 +522,7 @@
}
status_t AudioSource::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
if (mRecord != 0) {
return mRecord->getActiveMicrophones(activeMicrophones);
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index cf4b849..ebbbb5f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -863,6 +863,9 @@
return NAME_NOT_FOUND;
};
}
+
+ // we want an empty metrics record for any early getMetrics() call
+ // this should be the *only* initMediametrics() call that's not on the Looper thread
initMediametrics();
}
@@ -871,8 +874,17 @@
mResourceManagerProxy->removeClient();
flushMediametrics();
+
+ // clean any saved metrics info we stored as part of configure()
+ if (mConfigureMsg != nullptr) {
+ mediametrics_handle_t metricsHandle;
+ if (mConfigureMsg->findInt64("metrics", &metricsHandle)) {
+ mediametrics_delete(metricsHandle);
+ }
+ }
}
+// except for in constructor, called from the looper thread (and therefore mutexed)
void MediaCodec::initMediametrics() {
if (mMetricsHandle == 0) {
mMetricsHandle = mediametrics_create(kCodecKeyName);
@@ -902,11 +914,12 @@
}
void MediaCodec::updateMediametrics() {
- ALOGV("MediaCodec::updateMediametrics");
if (mMetricsHandle == 0) {
return;
}
+ Mutex::Autolock _lock(mMetricsLock);
+
if (mLatencyHist.getCount() != 0 ) {
mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
@@ -1019,6 +1032,8 @@
}
+// called to update info being passed back via getMetrics(), which is a
+// unique copy for that call, no concurrent access worries.
void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) {
ALOGD("MediaCodec::updateEphemeralMediametrics()");
@@ -1058,7 +1073,13 @@
}
void MediaCodec::flushMediametrics() {
+ ALOGD("flushMediametrics");
+
+ // update does its own mutex locking
updateMediametrics();
+
+ // ensure mutex while we do our own work
+ Mutex::Autolock _lock(mMetricsLock);
if (mMetricsHandle != 0) {
if (mediametrics_count(mMetricsHandle) > 0) {
mediametrics_selfRecord(mMetricsHandle);
@@ -1572,6 +1593,8 @@
}
msg->setString("name", name);
+ // initial naming setup covers the period before the first call to ::configure().
+ // after that, we manage this through ::configure() and the setup message.
if (mMetricsHandle != 0) {
mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str());
mediametrics_setCString(mMetricsHandle, kCodecMode, toCodecMode(mDomain));
@@ -1644,23 +1667,28 @@
const sp<IDescrambler> &descrambler,
uint32_t flags) {
sp<AMessage> msg = new AMessage(kWhatConfigure, this);
+ mediametrics_handle_t nextMetricsHandle = mediametrics_create(kCodecKeyName);
// TODO: validity check log-session-id: it should be a 32-hex-digit.
format->findString("log-session-id", &mLogSessionId);
- if (mMetricsHandle != 0) {
+ if (nextMetricsHandle != 0) {
int32_t profile = 0;
if (format->findInt32("profile", &profile)) {
- mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
+ mediametrics_setInt32(nextMetricsHandle, kCodecProfile, profile);
}
int32_t level = 0;
if (format->findInt32("level", &level)) {
- mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
+ mediametrics_setInt32(nextMetricsHandle, kCodecLevel, level);
}
- mediametrics_setInt32(mMetricsHandle, kCodecEncoder,
+ mediametrics_setInt32(nextMetricsHandle, kCodecEncoder,
(flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
- mediametrics_setCString(mMetricsHandle, kCodecLogSessionId, mLogSessionId.c_str());
+ mediametrics_setCString(nextMetricsHandle, kCodecLogSessionId, mLogSessionId.c_str());
+
+ // moved here from ::init()
+ mediametrics_setCString(nextMetricsHandle, kCodecCodec, mInitName.c_str());
+ mediametrics_setCString(nextMetricsHandle, kCodecMode, toCodecMode(mDomain));
}
if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) {
@@ -1670,38 +1698,38 @@
mRotationDegrees = 0;
}
- if (mMetricsHandle != 0) {
- mediametrics_setInt32(mMetricsHandle, kCodecWidth, mWidth);
- mediametrics_setInt32(mMetricsHandle, kCodecHeight, mHeight);
- mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees);
+ if (nextMetricsHandle != 0) {
+ mediametrics_setInt32(nextMetricsHandle, kCodecWidth, mWidth);
+ mediametrics_setInt32(nextMetricsHandle, kCodecHeight, mHeight);
+ mediametrics_setInt32(nextMetricsHandle, kCodecRotation, mRotationDegrees);
int32_t maxWidth = 0;
if (format->findInt32("max-width", &maxWidth)) {
- mediametrics_setInt32(mMetricsHandle, kCodecMaxWidth, maxWidth);
+ mediametrics_setInt32(nextMetricsHandle, kCodecMaxWidth, maxWidth);
}
int32_t maxHeight = 0;
if (format->findInt32("max-height", &maxHeight)) {
- mediametrics_setInt32(mMetricsHandle, kCodecMaxHeight, maxHeight);
+ mediametrics_setInt32(nextMetricsHandle, kCodecMaxHeight, maxHeight);
}
int32_t colorFormat = -1;
if (format->findInt32("color-format", &colorFormat)) {
- mediametrics_setInt32(mMetricsHandle, kCodecColorFormat, colorFormat);
+ mediametrics_setInt32(nextMetricsHandle, kCodecColorFormat, colorFormat);
}
if (mDomain == DOMAIN_VIDEO) {
float frameRate = -1.0;
if (format->findFloat("frame-rate", &frameRate)) {
- mediametrics_setDouble(mMetricsHandle, kCodecFrameRate, frameRate);
+ mediametrics_setDouble(nextMetricsHandle, kCodecFrameRate, frameRate);
}
float captureRate = -1.0;
if (format->findFloat("capture-rate", &captureRate)) {
- mediametrics_setDouble(mMetricsHandle, kCodecCaptureRate, captureRate);
+ mediametrics_setDouble(nextMetricsHandle, kCodecCaptureRate, captureRate);
}
float operatingRate = -1.0;
if (format->findFloat("operating-rate", &operatingRate)) {
- mediametrics_setDouble(mMetricsHandle, kCodecOperatingRate, operatingRate);
+ mediametrics_setDouble(nextMetricsHandle, kCodecOperatingRate, operatingRate);
}
int32_t priority = -1;
if (format->findInt32("priority", &priority)) {
- mediametrics_setInt32(mMetricsHandle, kCodecPriority, priority);
+ mediametrics_setInt32(nextMetricsHandle, kCodecPriority, priority);
}
}
int32_t colorStandard = -1;
@@ -1732,14 +1760,14 @@
}
} else {
- if (mMetricsHandle != 0) {
+ if (nextMetricsHandle != 0) {
int32_t channelCount;
if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)) {
- mediametrics_setInt32(mMetricsHandle, kCodecChannelCount, channelCount);
+ mediametrics_setInt32(nextMetricsHandle, kCodecChannelCount, channelCount);
}
int32_t sampleRate;
if (format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
- mediametrics_setInt32(mMetricsHandle, kCodecSampleRate, sampleRate);
+ mediametrics_setInt32(nextMetricsHandle, kCodecSampleRate, sampleRate);
}
}
}
@@ -1749,41 +1777,41 @@
enableMediaFormatShapingDefault);
if (!enableShaping) {
ALOGI("format shaping disabled, property '%s'", enableMediaFormatShapingProperty);
- if (mMetricsHandle != 0) {
- mediametrics_setInt32(mMetricsHandle, kCodecShapingEnhanced, -1);
+ if (nextMetricsHandle != 0) {
+ mediametrics_setInt32(nextMetricsHandle, kCodecShapingEnhanced, -1);
}
} else {
- (void) shapeMediaFormat(format, flags);
+ (void) shapeMediaFormat(format, flags, nextMetricsHandle);
// XXX: do we want to do this regardless of shaping enablement?
mapFormat(mComponentName, format, nullptr, false);
}
}
// push min/max QP to MediaMetrics after shaping
- if (mDomain == DOMAIN_VIDEO && mMetricsHandle != 0) {
+ if (mDomain == DOMAIN_VIDEO && nextMetricsHandle != 0) {
int32_t qpIMin = -1;
if (format->findInt32("video-qp-i-min", &qpIMin)) {
- mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMin, qpIMin);
+ mediametrics_setInt32(nextMetricsHandle, kCodecRequestedVideoQPIMin, qpIMin);
}
int32_t qpIMax = -1;
if (format->findInt32("video-qp-i-max", &qpIMax)) {
- mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMax, qpIMax);
+ mediametrics_setInt32(nextMetricsHandle, kCodecRequestedVideoQPIMax, qpIMax);
}
int32_t qpPMin = -1;
if (format->findInt32("video-qp-p-min", &qpPMin)) {
- mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMin, qpPMin);
+ mediametrics_setInt32(nextMetricsHandle, kCodecRequestedVideoQPPMin, qpPMin);
}
int32_t qpPMax = -1;
if (format->findInt32("video-qp-p-max", &qpPMax)) {
- mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMax, qpPMax);
+ mediametrics_setInt32(nextMetricsHandle, kCodecRequestedVideoQPPMax, qpPMax);
}
int32_t qpBMin = -1;
if (format->findInt32("video-qp-b-min", &qpBMin)) {
- mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMin, qpBMin);
+ mediametrics_setInt32(nextMetricsHandle, kCodecRequestedVideoQPBMin, qpBMin);
}
int32_t qpBMax = -1;
if (format->findInt32("video-qp-b-max", &qpBMax)) {
- mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMax, qpBMax);
+ mediametrics_setInt32(nextMetricsHandle, kCodecRequestedVideoQPBMax, qpBMax);
}
}
@@ -1799,13 +1827,23 @@
} else {
msg->setPointer("descrambler", descrambler.get());
}
- if (mMetricsHandle != 0) {
- mediametrics_setInt32(mMetricsHandle, kCodecCrypto, 1);
+ if (nextMetricsHandle != 0) {
+ mediametrics_setInt32(nextMetricsHandle, kCodecCrypto, 1);
}
} else if (mFlags & kFlagIsSecure) {
ALOGW("Crypto or descrambler should be given for secure codec");
}
+ if (mConfigureMsg != nullptr) {
+ // if re-configuring, we have one of these from before.
+ // Recover the space before we discard the old mConfigureMsg
+ mediametrics_handle_t metricsHandle;
+ if (mConfigureMsg->findInt64("metrics", &metricsHandle)) {
+ mediametrics_delete(metricsHandle);
+ }
+ }
+ msg->setInt64("metrics", nextMetricsHandle);
+
// save msg for reset
mConfigureMsg = msg;
@@ -2132,7 +2170,8 @@
status_t MediaCodec::shapeMediaFormat(
const sp<AMessage> &format,
- uint32_t flags) {
+ uint32_t flags,
+ mediametrics_handle_t metricsHandle) {
ALOGV("shapeMediaFormat entry");
if (!(flags & CONFIGURE_FLAG_ENCODE)) {
@@ -2188,39 +2227,39 @@
sp<AMessage> deltas = updatedFormat->changesFrom(format, false /* deep */);
size_t changeCount = deltas->countEntries();
ALOGD("shapeMediaFormat: deltas(%zu): %s", changeCount, deltas->debugString(2).c_str());
- if (mMetricsHandle != 0) {
- mediametrics_setInt32(mMetricsHandle, kCodecShapingEnhanced, changeCount);
+ if (metricsHandle != 0) {
+ mediametrics_setInt32(metricsHandle, kCodecShapingEnhanced, changeCount);
}
if (changeCount > 0) {
- if (mMetricsHandle != 0) {
+ if (metricsHandle != 0) {
// save some old properties before we fold in the new ones
int32_t bitrate;
if (format->findInt32(KEY_BIT_RATE, &bitrate)) {
- mediametrics_setInt32(mMetricsHandle, kCodecOriginalBitrate, bitrate);
+ mediametrics_setInt32(metricsHandle, kCodecOriginalBitrate, bitrate);
}
int32_t qpIMin = -1;
if (format->findInt32("original-video-qp-i-min", &qpIMin)) {
- mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPIMin, qpIMin);
+ mediametrics_setInt32(metricsHandle, kCodecOriginalVideoQPIMin, qpIMin);
}
int32_t qpIMax = -1;
if (format->findInt32("original-video-qp-i-max", &qpIMax)) {
- mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPIMax, qpIMax);
+ mediametrics_setInt32(metricsHandle, kCodecOriginalVideoQPIMax, qpIMax);
}
int32_t qpPMin = -1;
if (format->findInt32("original-video-qp-p-min", &qpPMin)) {
- mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPPMin, qpPMin);
+ mediametrics_setInt32(metricsHandle, kCodecOriginalVideoQPPMin, qpPMin);
}
int32_t qpPMax = -1;
if (format->findInt32("original-video-qp-p-max", &qpPMax)) {
- mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPPMax, qpPMax);
+ mediametrics_setInt32(metricsHandle, kCodecOriginalVideoQPPMax, qpPMax);
}
int32_t qpBMin = -1;
if (format->findInt32("original-video-qp-b-min", &qpBMin)) {
- mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPBMin, qpBMin);
+ mediametrics_setInt32(metricsHandle, kCodecOriginalVideoQPBMin, qpBMin);
}
int32_t qpBMax = -1;
if (format->findInt32("original-video-qp-b-max", &qpBMax)) {
- mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPBMax, qpBMax);
+ mediametrics_setInt32(metricsHandle, kCodecOriginalVideoQPBMax, qpBMax);
}
}
// NB: for any field in both format and deltas, the deltas copy wins
@@ -2806,26 +2845,44 @@
return OK;
}
+// this is the user-callable entry point
status_t MediaCodec::getMetrics(mediametrics_handle_t &reply) {
reply = 0;
- // shouldn't happen, but be safe
- if (mMetricsHandle == 0) {
- return UNKNOWN_ERROR;
+ sp<AMessage> msg = new AMessage(kWhatGetMetrics, this);
+ sp<AMessage> response;
+ status_t err;
+ if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
+ return err;
}
- // update any in-flight data that's not carried within the record
- updateMediametrics();
-
- // send it back to the caller.
- reply = mediametrics_dup(mMetricsHandle);
-
- updateEphemeralMediametrics(reply);
+ CHECK(response->findInt64("metrics", &reply));
return OK;
}
+// runs on the looper thread (for mutex purposes)
+void MediaCodec::onGetMetrics(const sp<AMessage>& msg) {
+
+ mediametrics_handle_t results = 0;
+
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mMetricsHandle != 0) {
+ updateMediametrics();
+ results = mediametrics_dup(mMetricsHandle);
+ updateEphemeralMediametrics(results);
+ } else {
+ results = mediametrics_dup(mMetricsHandle);
+ }
+
+ sp<AMessage> response = new AMessage;
+ response->setInt64("metrics", results);
+ response->postReply(replyID);
+}
+
status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
msg->setInt32("portIndex", kPortIndexInput);
@@ -3887,6 +3944,13 @@
break;
}
+ case kWhatGetMetrics:
+ {
+ onGetMetrics(msg);
+ break;
+ }
+
+
case kWhatConfigure:
{
if (mState != INITIALIZED) {
@@ -3907,6 +3971,18 @@
sp<AMessage> format;
CHECK(msg->findMessage("format", &format));
+ // start with a copy of the passed metrics info for use in this run
+ mediametrics_handle_t handle;
+ CHECK(msg->findInt64("metrics", &handle));
+ if (handle != 0) {
+ if (mMetricsHandle != 0) {
+ flushMediametrics();
+ }
+ mMetricsHandle = mediametrics_dup(handle);
+ // and set some additional metrics values
+ initMediametrics();
+ }
+
int32_t push;
if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
mFlags |= kFlagPushBlankBuffersOnShutdown;
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 1f569ef..f26311d 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -193,10 +193,38 @@
status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */) {
status_t err = NO_ERROR;
- ANativeWindowBuffer* anb = NULL;
+ ANativeWindowBuffer* anb = nullptr;
int numBufs = 0;
int minUndequeuedBufs = 0;
+ auto handleError = [](ANativeWindow *nativeWindow, ANativeWindowBuffer* anb, status_t err)
+ {
+ if (anb != nullptr) {
+ nativeWindow->cancelBuffer(nativeWindow, anb, -1);
+ anb = nullptr;
+ }
+
+ // Clean up after success or error.
+ status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
+ if (err2 != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
+ strerror(-err2), -err2);
+ if (err == NO_ERROR) {
+ err = err2;
+ }
+ }
+
+ err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
+ if (err2 != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
+ if (err == NO_ERROR) {
+ err = err2;
+ }
+ }
+
+ return err;
+ };
+
// We need to reconnect to the ANativeWindow as a CPU client to ensure that
// no frames get dropped by SurfaceFlinger assuming that these are video
// frames.
@@ -217,7 +245,7 @@
nativeWindow, 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
false /* reconnect */);
if (err != NO_ERROR) {
- goto error;
+ return handleError(nativeWindow, anb, err);
}
static_cast<Surface*>(nativeWindow)->getIGraphicBufferProducer()->allowAllocation(true);
@@ -227,14 +255,14 @@
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
"failed: %s (%d)", strerror(-err), -err);
- goto error;
+ return handleError(nativeWindow, anb, err);
}
numBufs = minUndequeuedBufs + 1;
err = native_window_set_buffer_count(nativeWindow, numBufs);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", strerror(-err), -err);
- goto error;
+ return handleError(nativeWindow, anb, err);
}
// We push numBufs + 1 buffers to ensure that we've drawn into the same
@@ -252,7 +280,7 @@
sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
// Fill the buffer with the a 1x1 checkerboard pattern ;)
- uint32_t *img = NULL;
+ uint32_t *img = nullptr;
err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err);
@@ -273,34 +301,10 @@
break;
}
- anb = NULL;
+ anb = nullptr;
}
-error:
-
- if (anb != NULL) {
- nativeWindow->cancelBuffer(nativeWindow, anb, -1);
- anb = NULL;
- }
-
- // Clean up after success or error.
- status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
- if (err2 != NO_ERROR) {
- ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err2), -err2);
- if (err == NO_ERROR) {
- err = err2;
- }
- }
-
- err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
- if (err2 != NO_ERROR) {
- ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
- if (err == NO_ERROR) {
- err = err2;
- }
- }
-
- return err;
+ return handleError(nativeWindow, anb, err);
}
status_t nativeWindowConnect(ANativeWindow *surface, const char *reason) {
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index 5e84977..65d5246 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -21,7 +21,6 @@
#include <media/AudioRecord.h>
#include <media/AudioSystem.h>
#include <media/stagefright/MediaSource.h>
-#include <media/MicrophoneInfo.h>
#include <media/stagefright/MediaBuffer.h>
#include <utils/List.h>
@@ -83,7 +82,7 @@
status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 6f6a4e6..703f7ad 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -357,6 +357,7 @@
kWhatSetNotification = 'setN',
kWhatDrmReleaseCrypto = 'rDrm',
kWhatCheckBatteryStats = 'chkB',
+ kWhatGetMetrics = 'getM',
};
enum {
@@ -427,6 +428,7 @@
sp<Surface> mSurface;
SoftwareRenderer *mSoftRenderer;
+ Mutex mMetricsLock;
mediametrics_handle_t mMetricsHandle = 0;
nsecs_t mLifetimeStartNs = 0;
void initMediametrics();
@@ -434,6 +436,7 @@
void flushMediametrics();
void updateEphemeralMediametrics(mediametrics_handle_t item);
void updateLowLatency(const sp<AMessage> &msg);
+ void onGetMetrics(const sp<AMessage>& msg);
constexpr const char *asString(TunnelPeekState state, const char *default_string="?");
void updateTunnelPeek(const sp<AMessage> &msg);
void updatePlaybackDuration(const sp<AMessage> &msg);
@@ -472,7 +475,8 @@
// the (possibly) updated format is returned in place.
status_t shapeMediaFormat(
const sp<AMessage> &format,
- uint32_t flags);
+ uint32_t flags,
+ mediametrics_handle_t handle);
// populate the format shaper library with information for this codec encoding
// for the indicated media type
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index ddf797c..88f7be7 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -332,6 +332,11 @@
}
bool AAVCAssembler::dropFramesUntilIframe(const sp<ABuffer> &buffer) {
+ if (buffer->size() == 0) {
+ ALOGE("b/230630526 buffer->size() == 0");
+ android_errorWriteLog(0x534e4554, "230630526");
+ return false;
+ }
const uint8_t *data = buffer->data();
unsigned nalType = data[0] & 0x1f;
if (!mFirstIFrameProvided && nalType < 0x5) {
@@ -624,8 +629,7 @@
int32_t firstSeqNo = buffer->int32Data();
// This only works for FU-A type & non-start sequence
- int32_t nalType = buffer->size() >= 1 ? buffer->data()[0] & 0x1f : -1;
- if (nalType != 28 || (buffer->size() >= 2 && buffer->data()[1] & 0x80)) {
+ if (buffer->size() < 2 || (buffer->data()[0] & 0x1f) != 28 || buffer->data()[1] & 0x80) {
return firstSeqNo;
}
diff --git a/media/libstagefright/rtsp/AHEVCAssembler.cpp b/media/libstagefright/rtsp/AHEVCAssembler.cpp
index bb42d1f..72dd981 100644
--- a/media/libstagefright/rtsp/AHEVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AHEVCAssembler.cpp
@@ -629,13 +629,13 @@
int32_t AHEVCAssembler::pickStartSeq(const Queue *queue,
uint32_t first, int64_t play, int64_t jit) {
+ CHECK(!queue->empty());
// pick the first sequence number has the start bit.
sp<ABuffer> buffer = *(queue->begin());
int32_t firstSeqNo = buffer->int32Data();
// This only works for FU-A type & non-start sequence
- unsigned nalType = buffer->data()[0] & 0x1f;
- if (nalType != 28 || buffer->data()[2] & 0x80) {
+ if (buffer->size() < 3 || (buffer->data()[0] & 0x1f) != 28 || buffer->data()[2] & 0x80) {
return firstSeqNo;
}
@@ -645,7 +645,7 @@
if (rtpTime + jit >= play) {
break;
}
- if ((data[2] & 0x80)) {
+ if (it->size() >= 3 && (data[2] & 0x80)) {
const int32_t seqNo = it->int32Data();
ALOGE("finding [HEAD] pkt. \t Seq# (%d ~ )[%d", firstSeqNo, seqNo);
firstSeqNo = seqNo;
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 59ce8db..cdbd745 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -197,7 +197,6 @@
}
status_t WebmFrameSinkThread::stop() {
- mDone = true;
mVideoFrames.push(WebmFrame::EOS);
mAudioFrames.push(WebmFrame::EOS);
return WebmFrameThread::stop();
diff --git a/media/module/extractors/ogg/OggExtractor.cpp b/media/module/extractors/ogg/OggExtractor.cpp
index d0e395a..4c106b2 100644
--- a/media/module/extractors/ogg/OggExtractor.cpp
+++ b/media/module/extractors/ogg/OggExtractor.cpp
@@ -34,6 +34,9 @@
#include <system/audio.h>
#include <utils/String8.h>
+#include <inttypes.h>
+#include <stdint.h>
+
extern "C" {
#include <Tremolo/codec_internal.h>
@@ -346,66 +349,118 @@
off64_t startOffset, off64_t *pageOffset) {
*pageOffset = startOffset;
- for (;;) {
- char signature[4];
- ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
+ // balance between larger reads and reducing how much we over-read.
+ const int FIND_BUF_SIZE = 2048;
+ const int lenOggS = strlen("OggS");
+ while(1) {
- if (n < 4) {
+ // work with big buffers to amortize readAt() costs
+ char signatureBuffer[FIND_BUF_SIZE];
+ ssize_t n = mSource->readAt(*pageOffset, &signatureBuffer, sizeof(signatureBuffer));
+
+ if (n < lenOggS) {
*pageOffset = 0;
-
return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
}
- if (!memcmp(signature, "OggS", 4)) {
- if (*pageOffset > startOffset) {
- ALOGV("skipped %lld bytes of junk to reach next frame",
- (long long)(*pageOffset - startOffset));
- }
-
- return OK;
- }
-
- // see how far ahead to skip; avoid some fruitless comparisons
- unsigned int i;
- for (i = 1; i < 4 ; i++) {
- if (signature[i] == 'O')
+ for(int i = 0; i < n - (lenOggS - 1) ; i++) {
+ // fast scan for 1st character in a signature
+ char *p = (char *)memchr(&signatureBuffer[i], 'O', n - (lenOggS - 1) - i);
+ if (p == NULL) {
+ // no signature start in the rest of this buffer.
break;
+ }
+ int jump = (p-&signatureBuffer[i]);
+ i += jump;
+ if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+ *pageOffset += i;
+ if (*pageOffset > startOffset) {
+ ALOGD("skipped %" PRIu64 " bytes of junk to reach next frame",
+ (*pageOffset - startOffset));
+ }
+ return OK;
+ }
}
- *pageOffset += i;
+
+ // on to next block. buffer didn't end with "OggS", but could end with "Ogg".
+ // overlap enough to detect this. n >= lenOggS, so this always advances.
+ *pageOffset += n - (lenOggS - 1);
}
+ return (status_t)ERROR_END_OF_STREAM;
}
// Given the offset of the "current" page, find the page immediately preceding
// it (if any) and return its granule position.
// To do this we back up from the "current" page's offset until we find any
// page preceding it and then scan forward to just before the current page.
+//
status_t MyOggExtractor::findPrevGranulePosition(
off64_t pageOffset, uint64_t *granulePos) {
*granulePos = 0;
- off64_t prevPageOffset = 0;
- off64_t prevGuess = pageOffset;
- for (;;) {
- if (prevGuess >= 5000) {
- prevGuess -= 5000;
+ const int FIND_BUF_SIZE = 2048;
+ const int lenOggS = strlen("OggS");
+
+ if (pageOffset == 0) {
+ ALOGV("no page before the first page");
+ return UNKNOWN_ERROR;
+ }
+
+ off64_t prevPageOffset = pageOffset;
+
+ // we start our search on the byte immediately in front of pageOffset
+ // which could mean "O" immediately before and "ggS" starting at pageOffset
+ //
+ // if there was an "OggS" at pageOffset, we'll have scanned a few extra bytes
+ // but if pageOffset was chosen by a seek operation, we don't know that it
+ // reflects the beginning of a page. By choosing to scan 3 possibly unneeded
+ // bytes at the start we cover both cases.
+ //
+ off64_t firstAfter = pageOffset + lenOggS - 1; // NOT within our buffer
+ off64_t nextOffset = pageOffset;
+
+ while(prevPageOffset == pageOffset) {
+ // work with big buffers to amortize readAt() costs
+ char signatureBuffer[FIND_BUF_SIZE];
+
+ ssize_t desired = sizeof(signatureBuffer);
+ if (firstAfter >= desired) {
+ nextOffset = firstAfter - desired;
} else {
- prevGuess = 0;
+ nextOffset = 0;
+ desired = firstAfter;
}
+ ssize_t n = mSource->readAt(nextOffset, &signatureBuffer, desired);
- ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
-
- status_t err = findNextPage(prevGuess, &prevPageOffset);
- if (err == ERROR_END_OF_STREAM) {
- // We are at the last page and didn't back off enough;
- // back off 5000 bytes more and try again.
- continue;
- } else if (err != OK) {
- return err;
- }
-
- if (prevPageOffset < pageOffset || prevGuess == 0) {
+ if (n < lenOggS) {
+ ALOGD("short read, get out");
break;
}
+
+ // work backwards
+ // loop control ok for n >= 0
+ for(int i = n - lenOggS; i >= 0 ; i--) {
+ // fast scan for 1st character in the signature
+ char *p = (char *)memrchr(&signatureBuffer[0], 'O', i);
+ if (p == NULL) {
+ // no signature start in the rest of this buffer.
+ break;
+ }
+ i = (p-&signatureBuffer[0]);
+ // loop start chosen to ensure we will always have lenOggS bytes
+ if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+ prevPageOffset = nextOffset + i;
+ break;
+ }
+ }
+
+ // back up for next read; make sure we catch overlaps
+ if (nextOffset == 0) {
+ // can't back up any further
+ break;
+ }
+ // current buffer might start with "ggS", include those bytes in the next iteration
+ firstAfter = nextOffset + lenOggS - 1;
}
if (prevPageOffset == pageOffset) {
@@ -413,8 +468,8 @@
return UNKNOWN_ERROR;
}
- ALOGV("prevPageOffset at %lld, pageOffset at %lld",
- (long long)prevPageOffset, (long long)pageOffset);
+ ALOGV("prevPageOffset at %" PRIu64 ", pageOffset at %" PRIu64,
+ prevPageOffset, pageOffset);
uint8_t flag = 0;
for (;;) {
Page prevPage;
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index a38ef57..fddbece 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -69,6 +69,7 @@
"-Wall",
"-Wextra",
"-Werror",
+ "-Wthread-safety",
],
header_libs: [
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 07f4529..83b84e3 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -103,11 +103,10 @@
AttributionSourceState myAttributionSource;
myAttributionSource.uid = VALUE_OR_FATAL(android::legacy2aidl_uid_t_int32_t(getuid()));
myAttributionSource.pid = VALUE_OR_FATAL(android::legacy2aidl_pid_t_int32_t(getpid()));
- if (callerAttributionSource.token != nullptr) {
- myAttributionSource.token = callerAttributionSource.token;
- } else {
- myAttributionSource.token = sp<BBinder>::make();
- }
+ // Create a static token for audioserver requests, which identifies the
+ // audioserver to the app ops system
+ static sp<BBinder> appOpsToken = sp<BBinder>::make();
+ myAttributionSource.token = appOpsToken;
myAttributionSource.next.push_back(nextAttributionSource);
return std::optional<AttributionSourceState>{myAttributionSource};
diff --git a/media/utils/TimerThread.cpp b/media/utils/TimerThread.cpp
index 5e58a3d..d4da28f 100644
--- a/media/utils/TimerThread.cpp
+++ b/media/utils/TimerThread.cpp
@@ -292,6 +292,7 @@
void TimerThread::MonitorThread::threadFunc() {
std::unique_lock _l(mMutex);
+ ::android::base::ScopedLockAssertion lock_assertion(mMutex);
while (!mShouldExit) {
Handle nextDeadline = INVALID_HANDLE;
Handle now = INVALID_HANDLE;
@@ -385,6 +386,7 @@
std::shared_ptr<const TimerThread::Request> TimerThread::MonitorThread::remove(Handle handle) {
std::pair<std::shared_ptr<const Request>, TimerCallback> data;
std::unique_lock ul(mMutex);
+ ::android::base::ScopedLockAssertion lock_assertion(mMutex);
if (const auto it = mMonitorRequests.find(handle);
it != mMonitorRequests.end()) {
data = std::move(it->second);
diff --git a/media/utils/include/mediautils/TimerThread.h b/media/utils/include/mediautils/TimerThread.h
index c76fa7d..1e0d8c2 100644
--- a/media/utils/include/mediautils/TimerThread.h
+++ b/media/utils/include/mediautils/TimerThread.h
@@ -297,7 +297,7 @@
std::pair<std::shared_ptr<const Request>, TimerCallback>>
mSecondChanceRequests GUARDED_BY(mMutex);
- RequestQueue& mTimeoutQueue; // locked internally, added to when request times out.
+ RequestQueue& mTimeoutQueue GUARDED_BY(mMutex); // added to when request times out.
// Worker thread variables
bool mShouldExit GUARDED_BY(mMutex) = false;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e4c4107..c05aac1 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -288,7 +288,6 @@
return opPackageLegacy == package; }) == packages.end()) {
ALOGW("The package name(%s) provided does not correspond to the uid %d",
attributionSource.packageName.value_or("").c_str(), attributionSource.uid);
- checkedAttributionSource.packageName = std::optional<std::string>();
}
}
return checkedAttributionSource;
@@ -588,6 +587,33 @@
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
audio_attributes_t localAttr = *attr;
+
+ // TODO b/182392553: refactor or make clearer
+ pid_t clientPid =
+ VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(client.attributionSource.pid));
+ bool updatePid = (clientPid == (pid_t)-1);
+ const uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+ AttributionSourceState adjAttributionSource = client.attributionSource;
+ if (!isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
+ uid_t clientUid =
+ VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(client.attributionSource.uid));
+ ALOGW_IF(clientUid != callingUid,
+ "%s uid %d tried to pass itself off as %d",
+ __FUNCTION__, callingUid, clientUid);
+ adjAttributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
+ updatePid = true;
+ }
+ if (updatePid) {
+ const pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ ALOGW_IF(clientPid != (pid_t)-1 && clientPid != callingPid,
+ "%s uid %d pid %d tried to pass itself off as pid %d",
+ __func__, callingUid, callingPid, clientPid);
+ adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
+ }
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource);
+
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
audio_config_t fullConfig = AUDIO_CONFIG_INITIALIZER;
fullConfig.sample_rate = config->sample_rate;
@@ -597,7 +623,7 @@
bool isSpatialized;
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
- &streamType, client.attributionSource,
+ &streamType, adjAttributionSource,
&fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
@@ -608,7 +634,7 @@
ret = AudioSystem::getInputForAttr(&localAttr, &io,
RECORD_RIID_INVALID,
actualSessionId,
- client.attributionSource,
+ adjAttributionSource,
config,
AUDIO_INPUT_FLAG_MMAP_NOIRQ, deviceId, &portId);
}
@@ -1057,7 +1083,7 @@
audio_attributes_t localAttr = input.attr;
AttributionSourceState adjAttributionSource = input.clientInfo.attributionSource;
- if (!isAudioServerOrMediaServerUid(callingUid)) {
+ if (!isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
ALOGW_IF(clientUid != callingUid,
"%s uid %d tried to pass itself off as %d",
__FUNCTION__, callingUid, clientUid);
@@ -1073,6 +1099,8 @@
clientPid = callingPid;
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource);
audio_session_t sessionId = input.sessionId;
if (sessionId == AUDIO_SESSION_ALLOCATE) {
@@ -2317,7 +2345,7 @@
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
const uid_t currentUid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(
adjAttributionSource.uid));
- if (!isAudioServerOrMediaServerUid(callingUid)) {
+ if (!isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
ALOGW_IF(currentUid != callingUid,
"%s uid %d tried to pass itself off as %d",
__FUNCTION__, callingUid, currentUid);
@@ -2333,7 +2361,8 @@
__func__, callingUid, callingPid, currentPid);
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
-
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource);
// we don't yet support anything other than linear PCM
if (!audio_is_valid_format(input.config.format) || !audio_is_linear_pcm(input.config.format)) {
ALOGE("createRecord() invalid format %#x", input.config.format);
@@ -2770,7 +2799,7 @@
return NO_ERROR;
}
-status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
+status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones)
{
AutoMutex lock(mHardwareLock);
status_t status = INVALID_OPERATION;
@@ -2783,8 +2812,12 @@
mHardwareStatus = AUDIO_HW_IDLE;
if (devStatus == NO_ERROR) {
// report success if at least one HW module supports the function.
- std::transform(mics.begin(), mics.end(), std::back_inserter(*microphones),
- [](auto& mic) { return media::MicrophoneInfo(mic); });
+ std::transform(mics.begin(), mics.end(), std::back_inserter(*microphones), [](auto& mic)
+ {
+ auto microphone =
+ legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+ return microphone.ok() ? microphone.value() : media::MicrophoneInfoFw{};
+ });
status = NO_ERROR;
}
}
@@ -3967,7 +4000,7 @@
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
adjAttributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
pid_t currentPid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(adjAttributionSource.pid));
- if (currentPid == -1 || !isAudioServerOrMediaServerUid(callingUid)) {
+ if (currentPid == -1 || !isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
const pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW_IF(currentPid != -1 && currentPid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
@@ -3975,6 +4008,7 @@
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
currentPid = callingPid;
}
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(adjAttributionSource);
ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
adjAttributionSource.pid, effectClient.get(), priority, sessionId, io,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index cb303cf..ebfe32c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -274,7 +274,7 @@
bool isAudioPolicyReady() const { return mAudioPolicyReady.load(); }
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
@@ -708,7 +708,7 @@
int /*audio_session_t*/ triggerSession);
virtual binder::Status stop();
virtual binder::Status getActiveMicrophones(
- std::vector<media::MicrophoneInfoData>* activeMicrophones);
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
virtual binder::Status setPreferredMicrophoneDirection(
int /*audio_microphone_direction_t*/ direction);
virtual binder::Status setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index e8552c4..076417e 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -73,7 +73,8 @@
void setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; }
bool isSilenced() const { return mSilenced; }
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9837574..0de7e7d 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8369,8 +8369,6 @@
audio_input_flags_t inputFlags = mInput->flags;
audio_input_flags_t requestedFlags = *flags;
uint32_t sampleRate;
- AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage(
- attributionSource);
lStatus = initCheck();
if (lStatus != NO_ERROR) {
@@ -8385,7 +8383,7 @@
}
if (maxSharedAudioHistoryMs != 0) {
- if (!captureHotwordAllowed(checkedAttributionSource)) {
+ if (!captureHotwordAllowed(attributionSource)) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
@@ -8506,16 +8504,16 @@
Mutex::Autolock _l(mLock);
int32_t startFrames = -1;
if (!mSharedAudioPackageName.empty()
- && mSharedAudioPackageName == checkedAttributionSource.packageName
+ && mSharedAudioPackageName == attributionSource.packageName
&& mSharedAudioSessionId == sessionId
- && captureHotwordAllowed(checkedAttributionSource)) {
+ && captureHotwordAllowed(attributionSource)) {
startFrames = mSharedAudioStartFrames;
}
track = new RecordTrack(this, client, attr, sampleRate,
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
- checkedAttributionSource, *flags, TrackBase::TYPE_DEFAULT, portId,
+ attributionSource, *flags, TrackBase::TYPE_DEFAULT, portId,
startFrames);
lStatus = track->initCheck();
@@ -8724,7 +8722,7 @@
}
status_t AudioFlinger::RecordThread::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones)
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
ALOGV("RecordThread::getActiveMicrophones");
AutoMutex _l(mLock);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index bb42f22..ce90767 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1941,7 +1941,8 @@
// Sets the UID records silence
void setRecordSilenced(audio_port_handle_t portId, bool silenced);
- status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones);
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 02c4aaf..077a01a 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -531,10 +531,7 @@
id, attr.flags);
return nullptr;
}
-
- AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage(
- attributionSource);
- return new OpPlayAudioMonitor(checkedAttributionSource, attr.usage, id);
+ return new OpPlayAudioMonitor(attributionSource, attr.usage, id);
}
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
@@ -2355,15 +2352,9 @@
}
binder::Status AudioFlinger::RecordHandle::getActiveMicrophones(
- std::vector<media::MicrophoneInfoData>* activeMicrophones) {
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
ALOGV("%s()", __func__);
- std::vector<media::MicrophoneInfo> mics;
- status_t status = mRecordTrack->getActiveMicrophones(&mics);
- activeMicrophones->resize(mics.size());
- for (size_t i = 0; status == OK && i < mics.size(); ++i) {
- status = mics[i].writeToParcelable(&activeMicrophones->at(i));
- }
- return binderStatusFromStatusT(status);
+ return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
}
binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
@@ -2683,7 +2674,7 @@
}
status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
- std::vector<media::MicrophoneInfo>* activeMicrophones)
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8c8278c..3d6bc5b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -596,7 +596,10 @@
audioDeviceSet = getAudioDeviceOutAllA2dpSet();
break;
case AUDIO_DEVICE_OUT_BLE_HEADSET:
- audioDeviceSet = getAudioDeviceOutAllBleSet();
+ audioDeviceSet = getAudioDeviceOutLeAudioUnicastSet();
+ break;
+ case AUDIO_DEVICE_OUT_BLE_BROADCAST:
+ audioDeviceSet = getAudioDeviceOutLeAudioBroadcastSet();
break;
default:
ALOGE("%s() device type 0x%08x not supported", __func__, device);
@@ -1027,7 +1030,7 @@
// when searching for direct outputs, if several profiles are compatible, give priority
// to one with offload capability
- if (profile != 0 &&
+ if (profile != 0 &&
((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
continue;
}
@@ -5614,6 +5617,17 @@
return status;
}
+ // If microphones address is empty, set it according to device type
+ for (size_t i = 0; i < mInputDevicesAll.size(); i++) {
+ if (mInputDevicesAll[i]->address().empty()) {
+ if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ mInputDevicesAll[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ } else if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
+ mInputDevicesAll[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
+ }
+ }
+ }
+
mEngine->updateDeviceSelectionCache();
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
@@ -5628,17 +5642,6 @@
mDefaultOutputDevice->toString().c_str());
status = NO_INIT;
}
- // If microphones address is empty, set it according to device type
- for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
- if (mAvailableInputDevices[i]->address().empty()) {
- if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
- mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
- } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
- mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
- }
- }
- }
-
ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
// Silence ALOGV statements
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 4212c1c..fdf5787 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -352,31 +352,20 @@
ALOGV("%s()", __func__);
Mutex::Autolock _l(mLock);
- // TODO b/182392553: refactor or remove
- AttributionSourceState adjAttributionSource = attributionSource;
- const uid_t callingUid = IPCThreadState::self()->getCallingUid();
- if (!isAudioServerOrMediaServerUid(callingUid) || attributionSource.uid == -1) {
- int32_t callingUidAidl = VALUE_OR_RETURN_BINDER_STATUS(
- legacy2aidl_uid_t_int32_t(callingUid));
- ALOGW_IF(attributionSource.uid != -1 && attributionSource.uid != callingUidAidl,
- "%s uid %d tried to pass itself off as %d", __func__,
- callingUidAidl, attributionSource.uid);
- adjAttributionSource.uid = callingUidAidl;
- }
if (!mPackageManager.allowPlaybackCapture(VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_int32_t_uid_t(adjAttributionSource.uid)))) {
+ aidl2legacy_int32_t_uid_t(attributionSource.uid)))) {
attr.flags = static_cast<audio_flags_mask_t>(attr.flags | AUDIO_FLAG_NO_MEDIA_PROJECTION);
}
if (((attr.flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
- && !bypassInterruptionPolicyAllowed(adjAttributionSource)) {
+ && !bypassInterruptionPolicyAllowed(attributionSource)) {
attr.flags = static_cast<audio_flags_mask_t>(
attr.flags & ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE));
}
if (attr.content_type == AUDIO_CONTENT_TYPE_ULTRASOUND) {
- if (!accessUltrasoundAllowed(adjAttributionSource)) {
+ if (!accessUltrasoundAllowed(attributionSource)) {
ALOGE("%s: permission denied: ultrasound not allowed for uid %d pid %d",
- __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ __func__, attributionSource.uid, attributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
}
@@ -386,7 +375,7 @@
bool isSpatialized = false;
status_t result = mAudioPolicyManager->getOutputForAttr(&attr, &output, session,
&stream,
- adjAttributionSource,
+ attributionSource,
&config,
&flags, &selectedDeviceId, &portId,
&secondaryOutputs,
@@ -401,20 +390,20 @@
break;
case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
if (((attr.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0)
- && !callAudioInterceptionAllowed(adjAttributionSource)) {
+ && !callAudioInterceptionAllowed(attributionSource)) {
ALOGE("%s() permission denied: call redirection not allowed for uid %d",
- __func__, adjAttributionSource.uid);
+ __func__, attributionSource.uid);
result = PERMISSION_DENIED;
- } else if (!modifyPhoneStateAllowed(adjAttributionSource)) {
+ } else if (!modifyPhoneStateAllowed(attributionSource)) {
ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
- __func__, adjAttributionSource.uid);
+ __func__, attributionSource.uid);
result = PERMISSION_DENIED;
}
break;
case AudioPolicyInterface::API_OUT_MIX_PLAYBACK:
- if (!modifyAudioRoutingAllowed(adjAttributionSource)) {
+ if (!modifyAudioRoutingAllowed(attributionSource)) {
ALOGE("%s() permission denied: modify audio routing not allowed for uid %d",
- __func__, adjAttributionSource.uid);
+ __func__, attributionSource.uid);
result = PERMISSION_DENIED;
}
break;
@@ -427,7 +416,7 @@
if (result == NO_ERROR) {
sp<AudioPlaybackClient> client =
- new AudioPlaybackClient(attr, output, adjAttributionSource, session,
+ new AudioPlaybackClient(attr, output, attributionSource, session,
portId, selectedDeviceId, stream, isSpatialized);
mAudioPlaybackClients.add(portId, client);
@@ -613,33 +602,8 @@
return binderStatusFromStatusT(BAD_VALUE);
}
- // Make sure attribution source represents the current caller
- AttributionSourceState adjAttributionSource = attributionSource;
- // TODO b/182392553: refactor or remove
- bool updatePid = (attributionSource.pid == -1);
- const uid_t callingUid =IPCThreadState::self()->getCallingUid();
- const uid_t currentUid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(
- attributionSource.uid));
- if (!isAudioServerOrMediaServerUid(callingUid)) {
- ALOGW_IF(currentUid != (uid_t)-1 && currentUid != callingUid,
- "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid,
- currentUid);
- adjAttributionSource.uid = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_uid_t_int32_t(
- callingUid));
- updatePid = true;
- }
-
- if (updatePid) {
- const int32_t callingPid = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_pid_t_int32_t(
- IPCThreadState::self()->getCallingPid()));
- ALOGW_IF(attributionSource.pid != -1 && attributionSource.pid != callingPid,
- "%s uid %d pid %d tried to pass itself off as pid %d",
- __func__, adjAttributionSource.uid, callingPid, attributionSource.pid);
- adjAttributionSource.pid = callingPid;
- }
-
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(validateUsage(attr,
- adjAttributionSource)));
+ attributionSource)));
// check calling permissions.
// Capturing from the following sources does not require permission RECORD_AUDIO
@@ -650,17 +614,17 @@
// type is API_INPUT_MIX_EXT_POLICY_REROUTE and by AudioService if a media projection
// is used and input type is API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK
// - ECHO_REFERENCE source is controlled by captureAudioOutputAllowed()
- if (!(recordingAllowed(adjAttributionSource, inputSource)
+ if (!(recordingAllowed(attributionSource, inputSource)
|| inputSource == AUDIO_SOURCE_FM_TUNER
|| inputSource == AUDIO_SOURCE_REMOTE_SUBMIX
|| inputSource == AUDIO_SOURCE_ECHO_REFERENCE)) {
ALOGE("%s permission denied: recording not allowed for %s",
- __func__, adjAttributionSource.toString().c_str());
+ __func__, attributionSource.toString().c_str());
return binderStatusFromStatusT(PERMISSION_DENIED);
}
- bool canCaptureOutput = captureAudioOutputAllowed(adjAttributionSource);
- bool canInterceptCallAudio = callAudioInterceptionAllowed(adjAttributionSource);
+ bool canCaptureOutput = captureAudioOutputAllowed(attributionSource);
+ bool canInterceptCallAudio = callAudioInterceptionAllowed(attributionSource);
bool isCallAudioSource = inputSource == AUDIO_SOURCE_VOICE_UPLINK
|| inputSource == AUDIO_SOURCE_VOICE_DOWNLINK
|| inputSource == AUDIO_SOURCE_VOICE_CALL;
@@ -674,11 +638,11 @@
}
if (inputSource == AUDIO_SOURCE_FM_TUNER
&& !canCaptureOutput
- && !captureTunerAudioInputAllowed(adjAttributionSource)) {
+ && !captureTunerAudioInputAllowed(attributionSource)) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
- bool canCaptureHotword = captureHotwordAllowed(adjAttributionSource);
+ bool canCaptureHotword = captureHotwordAllowed(attributionSource);
if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
@@ -686,14 +650,14 @@
if (((flags & AUDIO_INPUT_FLAG_HW_HOTWORD) != 0)
&& !canCaptureHotword) {
ALOGE("%s: permission denied: hotword mode not allowed"
- " for uid %d pid %d", __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ " for uid %d pid %d", __func__, attributionSource.uid, attributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
if (attr.source == AUDIO_SOURCE_ULTRASOUND) {
- if (!accessUltrasoundAllowed(adjAttributionSource)) {
+ if (!accessUltrasoundAllowed(attributionSource)) {
ALOGE("%s: permission denied: ultrasound not allowed for uid %d pid %d",
- __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ __func__, attributionSource.uid, attributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
}
@@ -708,7 +672,7 @@
AutoCallerClear acc;
// the audio_in_acoustics_t parameter is ignored by get_input()
status = mAudioPolicyManager->getInputForAttr(&attr, &input, riid, session,
- adjAttributionSource, &config,
+ attributionSource, &config,
flags, &selectedDeviceId,
&inputType, &portId);
@@ -737,7 +701,7 @@
}
break;
case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
- if (!(modifyAudioRoutingAllowed(adjAttributionSource)
+ if (!(modifyAudioRoutingAllowed(attributionSource)
|| ((attr.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0
&& canInterceptCallAudio))) {
ALOGE("%s permission denied for remote submix capture", __func__);
@@ -760,7 +724,7 @@
}
sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId,
- selectedDeviceId, adjAttributionSource,
+ selectedDeviceId, attributionSource,
canCaptureOutput, canCaptureHotword,
mOutputCommandThread);
mAudioRecordClients.add(portId, client);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 2a8a103..b219cc8 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1851,6 +1851,10 @@
mCompositeStreamMap.clear();
mInputStream = {false, 0, 0, 0, 0};
} else {
+ // In case we failed to register the offline client, ensure that it still initialized
+ // so that all failing requests can return back correctly once the object is released.
+ offlineClient->initialize(nullptr /*cameraProviderManager*/, String8()/*monitorTags*/);
+
switch(ret) {
case BAD_VALUE:
return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index beb655b..2cb3397 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -29,6 +29,11 @@
status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
ATRACE_CALL();
+ if (mFrameProcessor.get() != nullptr) {
+ // Already initialized
+ return OK;
+ }
+
// Verify ops permissions
auto res = startCameraOps();
if (res != OK) {
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index ef68f28..4664946 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -293,7 +293,7 @@
if (link != STATUS_OK) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
__FUNCTION__, mProviderName.c_str());
- mManager->removeProvider(mProviderName);
+ mManager->removeProvider(mProviderInstance);
return nullptr;
}
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index d60565f..e9c4cb8 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -388,7 +388,7 @@
__FUNCTION__,
mProviderName.c_str(),
linked.description().c_str());
- mManager->removeProvider(mProviderName);
+ mManager->removeProvider(mProviderInstance);
return nullptr;
} else if (!linked) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 7dff809..78f3e25 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1018,7 +1018,7 @@
wp<NotificationListener> mListener;
- const String8& mId; // The camera ID
+ const String8 mId; // The camera ID
int mStatusId; // The RequestThread's component ID for
// status tracking
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
index 7cfa255..1e7bd57 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -81,7 +81,6 @@
Camera3OfflineSession::~Camera3OfflineSession() {
ATRACE_CALL();
ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
- disconnectImpl();
}
const String8& Camera3OfflineSession::getId() const {
@@ -96,7 +95,6 @@
status_t Camera3OfflineSession::disconnect() {
ATRACE_CALL();
- disconnectSession();
return disconnectImpl();
}
@@ -132,6 +130,8 @@
streams.push_back(mInputStream);
}
+ closeSessionLocked();
+
FlushInflightReqStates states {
mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
listener, *this, mBufferRecords, *this, mSessionStatsBuilder};
@@ -140,6 +140,7 @@
{
std::lock_guard<std::mutex> lock(mLock);
+ releaseSessionLocked();
mOutputStreams.clear();
mInputStream.clear();
mStatus = STATUS_CLOSED;
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 5ee6ca5..e780043 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -274,7 +274,12 @@
void setErrorStateLockedV(const char *fmt, va_list args);
status_t disconnectImpl();
- virtual void disconnectSession() = 0;
+
+ // Clients need to ensure that 'mInterfaceLock' is acquired before calling this method
+ virtual void closeSessionLocked() = 0;
+
+ // Clients need to ensure that 'mLock' is acquired before calling this method
+ virtual void releaseSessionLocked() = 0;
}; // class Camera3OfflineSession
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
index 8ff0b07..affdda6 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
@@ -48,7 +48,7 @@
AidlCamera3OfflineSession::~AidlCamera3OfflineSession() {
ATRACE_CALL();
ALOGV("%s: Tearing down aidl offline session for camera id %s", __FUNCTION__, mId.string());
- AidlCamera3OfflineSession::disconnectSession();
+ Camera3OfflineSession::disconnectImpl();
}
status_t AidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
@@ -245,12 +245,17 @@
return ::ndk::ScopedAStatus::ok();
}
-void AidlCamera3OfflineSession::disconnectSession() {
- std::lock_guard<std::mutex> lock(mLock);
- if (mSession != nullptr) {
- mSession->close();
- }
- mSession.reset();
+void AidlCamera3OfflineSession::closeSessionLocked() {
+ if (mSession != nullptr) {
+ auto err = mSession->close();
+ if (!err.isOk()) {
+ ALOGE("%s: Close transaction error: %s", __FUNCTION__, err.getDescription().c_str());
+ }
+ }
+}
+
+void AidlCamera3OfflineSession::releaseSessionLocked() {
+ mSession.reset();
}
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
index d107af6..b31ffb7 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
@@ -131,7 +131,9 @@
std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks;
- virtual void disconnectSession() override;
+ virtual void closeSessionLocked() override;
+
+ virtual void releaseSessionLocked() override;
}; // class AidlCamera3OfflineSession
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 2e98fe0..d56ff53 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -81,9 +81,6 @@
const hardware::hidl_vec<
hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
- // Handle one notify message
- void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
-
status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
/*out*/ sp<CameraOfflineSessionBase>* session) override;
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
index 2b4f8a1..de01ac9 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
@@ -39,7 +39,7 @@
HidlCamera3OfflineSession::~HidlCamera3OfflineSession() {
ATRACE_CALL();
ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.string());
- HidlCamera3OfflineSession::disconnectSession();
+ Camera3OfflineSession::disconnectImpl();
}
status_t HidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
@@ -226,13 +226,17 @@
return hardware::Void();
}
-void HidlCamera3OfflineSession::disconnectSession() {
- // TODO: Make sure this locking is correct.
- std::lock_guard<std::mutex> lock(mLock);
- if (mSession != nullptr) {
- mSession->close();
- }
- mSession.clear();
+void HidlCamera3OfflineSession::closeSessionLocked() {
+ if (mSession != nullptr) {
+ auto err = mSession->close();
+ if (!err.isOk()) {
+ ALOGE("%s: Close transaction error: %s", __FUNCTION__, err.description().c_str());
+ }
+ }
+}
+
+void HidlCamera3OfflineSession::releaseSessionLocked() {
+ mSession.clear();
}
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
index 597cc5d..d22a447 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
@@ -101,7 +101,9 @@
// FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
- virtual void disconnectSession() override;
+ virtual void closeSessionLocked() override;
+
+ virtual void releaseSessionLocked() override;
}; // class Camera3OfflineSession
}; // namespace android