Merge "Codec2: remove dependancy from C2 Aidl"
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/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/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 d0ff091..be80055 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;
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2727,6 +2729,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 ad27c64..2df97d1 100644
--- a/media/audioaidlconversion/AidlConversionEffect.cpp
+++ b/media/audioaidlconversion/AidlConversionEffect.cpp
@@ -30,7 +30,7 @@
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::Descriptor;
using ::aidl::android::hardware::audio::effect::Downmix;
@@ -260,46 +260,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(
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
index c412238..abf0231 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>
@@ -371,6 +373,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/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp
index 8b852a2..9102a97 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.cpp
+++ b/media/codec2/components/aom/C2SoftAomEnc.cpp
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/MediaDefs.h>
#include <C2Debug.h>
+#include <Codec2CommonUtils.h>
#include <Codec2Mapper.h>
#include <C2PlatformSupport.h>
#include <SimpleC2Interface.h>
@@ -63,7 +64,8 @@
0u, C2Config::BITRATE_VARIABLE))
.withFields({C2F(mBitrateMode, value)
.oneOf({C2Config::BITRATE_CONST,
- C2Config::BITRATE_VARIABLE})})
+ C2Config::BITRATE_VARIABLE,
+ C2Config::BITRATE_IGNORE})})
.withSetter(Setter<decltype(*mBitrateMode)>::StrictValueWithNoDeps)
.build());
@@ -86,6 +88,12 @@
.withSetter(BitrateSetter)
.build());
+ addParameter(DefineParam(mQuality, C2_PARAMKEY_QUALITY)
+ .withDefault(new C2StreamQualityTuning::output(0u, 80))
+ .withFields({C2F(mQuality, value).inRange(0, 100)})
+ .withSetter(Setter<decltype(*mQuality)>::NonStrictValueWithNoDeps)
+ .build());
+
addParameter(DefineParam(mIntraRefresh, C2_PARAMKEY_INTRA_REFRESH)
.withConstValue(new C2StreamIntraRefreshTuning::output(
0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
@@ -105,19 +113,18 @@
.withSetter(ProfileLevelSetter)
.build());
+ std::vector<uint32_t> pixelFormats = {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ HAL_PIXEL_FORMAT_YCBCR_420_888};
+ if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) {
+ pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010);
+ }
addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
- .withDefault(new C2StreamPixelFormatInfo::output(
+ .withDefault(new C2StreamPixelFormatInfo::input(
0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
- .withFields({C2F(mPixelFormat, value).oneOf({
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
- HAL_PIXEL_FORMAT_YCBCR_420_888,
- HAL_PIXEL_FORMAT_YCBCR_P010
- })
- })
+ .withFields({C2F(mPixelFormat, value).oneOf({pixelFormats})})
.withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
.build());
-
addParameter(DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME)
.withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
.withFields({C2F(mRequestSync, value).oneOf({C2_FALSE, C2_TRUE})})
@@ -293,6 +300,12 @@
return onStop();
}
+// c2Quality is in range of 0-100 (the more - the better),
+// for AOM quality we are using a range of 15-50 (the less - the better)
+static int MapC2QualityToAOMQuality (int c2Quality) {
+ return 15 + 35 * (100 - c2Quality) / 100;
+}
+
aom_codec_err_t C2SoftAomEnc::setupCodecParameters() {
aom_codec_err_t codec_return = AOM_CODEC_OK;
@@ -391,6 +404,15 @@
codec_return = aom_codec_control(mCodecContext, AV1E_SET_MAX_REFERENCE_FRAMES, 3);
if (codec_return != AOM_CODEC_OK) goto BailOut;
+ if (mBitrateControlMode == AOM_Q) {
+ const int aomCQLevel = MapC2QualityToAOMQuality(mQuality->value);
+ ALOGV("Set Q from %d to CQL %d",
+ mQuality->value, aomCQLevel);
+
+ codec_return = aom_codec_control(mCodecContext, AOME_SET_CQ_LEVEL, aomCQLevel);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+ }
+
ColorAspects sfAspects;
if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
@@ -438,6 +460,7 @@
mIntraRefresh = mIntf->getIntraRefresh_l();
mRequestSync = mIntf->getRequestSync_l();
mColorAspects = mIntf->getCodedColorAspects_l();
+ mQuality = mIntf->getQuality_l();
}
@@ -445,6 +468,9 @@
case C2Config::BITRATE_CONST:
mBitrateControlMode = AOM_CBR;
break;
+ case C2Config::BITRATE_IGNORE:
+ mBitrateControlMode = AOM_Q;
+ break;
case C2Config::BITRATE_VARIABLE:
[[fallthrough]];
default:
@@ -484,7 +510,7 @@
mCodecConfiguration->g_timebase.den = 1000000;
// rc_target_bitrate is in kbps, mBitrate in bps
mCodecConfiguration->rc_target_bitrate = (mBitrate->value + 500) / 1000;
- mCodecConfiguration->rc_end_usage = AOM_CBR;
+ mCodecConfiguration->rc_end_usage = mBitrateControlMode == AOM_Q ? AOM_Q : AOM_CBR;
// Disable frame drop - not allowed in MediaCodec now.
mCodecConfiguration->rc_dropframe_thresh = 0;
// Disable lagged encoding.
diff --git a/media/codec2/components/aom/C2SoftAomEnc.h b/media/codec2/components/aom/C2SoftAomEnc.h
index 3e42855..d7832dd 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.h
+++ b/media/codec2/components/aom/C2SoftAomEnc.h
@@ -102,6 +102,7 @@
std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh;
std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+ std::shared_ptr<C2StreamQualityTuning::output> mQuality;
std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
@@ -127,6 +128,7 @@
}
std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; }
std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; }
+ std::shared_ptr<C2StreamQualityTuning::output> getQuality_l() const { return mQuality; }
std::shared_ptr<C2StreamBitrateModeTuning::output> getBitrateMode_l() const {
return mBitrateMode;
}
@@ -136,7 +138,7 @@
std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() const {
return mCodedColorAspects;
}
- std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const {
+ std::shared_ptr<C2StreamPixelFormatInfo::input> getPixelFormat_l() const {
return mPixelFormat;
}
uint32_t getSyncFramePeriod() const;
@@ -152,11 +154,12 @@
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+ std::shared_ptr<C2StreamQualityTuning::output> mQuality;
std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
- std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
+ std::shared_ptr<C2StreamPixelFormatInfo::input> mPixelFormat;
};
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 50e9ea7..2bbfb76 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 12bcec6..f07ea1d 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -1635,16 +1635,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 59016ad..706f51f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1936,7 +1936,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 1c634e7..bbc39e8 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -753,14 +753,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;
}
@@ -1324,11 +1321,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 69810c0..568c865 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -37,7 +37,7 @@
import android.media.IAudioTrack;
import android.media.ISoundDose;
import android.media.ISoundDoseCallback;
-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/aidl/android/media/ICaptureStateListener.aidl b/media/libaudioclient/aidl/android/media/ICaptureStateListener.aidl
index 3b2206a..3ec6e7a 100644
--- a/media/libaudioclient/aidl/android/media/ICaptureStateListener.aidl
+++ b/media/libaudioclient/aidl/android/media/ICaptureStateListener.aidl
@@ -19,6 +19,6 @@
/**
* {@hide}
*/
-interface ICaptureStateListener {
+oneway interface ICaptureStateListener {
void setCaptureState(boolean active);
}
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 47fe0f6..dfdb4cf 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -385,7 +385,7 @@
record->getInputFramesLost();
record->getFlags();
- std::vector<media::MicrophoneInfo> activeMicrophones;
+ std::vector<media::MicrophoneInfoFw> activeMicrophones;
record->getActiveMicrophones(&activeMicrophones);
record->releaseBuffer(&audioBuffer);
@@ -567,7 +567,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 3f33d7a..00f2c7a 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>
@@ -584,10 +583,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 23b0340..d033d4f 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -31,6 +31,7 @@
#include <android/media/ISoundDose.h>
#include <android/media/ISoundDoseCallback.h>
#include <android/media/ISpatializer.h>
+#include <android/media/MicrophoneInfoFw.h>
#include <android/media/RecordClientInfo.h>
#include <android/media/audio/common/AudioConfigBase.h>
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
@@ -43,7 +44,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>
@@ -475,7 +475,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 6b6c407..02d0511 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>
@@ -342,7 +341,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;
@@ -470,7 +469,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(
@@ -698,7 +697,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 5cd17e1..f651a37 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
@@ -668,3 +670,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 7710cf5..2e6915a 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -49,17 +49,11 @@
void TearDown() override {
if (mPlayback) {
mPlayback->stop();
- if (auto handle = mPlayback->getAudioTrackHandle(); handle) {
- handle->removeAudioDeviceCallback(mCbPlayback);
- }
mCbPlayback.clear();
mPlayback.clear();
}
if (mCapture) {
mCapture->stop();
- if (auto handle = mCapture->getAudioRecordHandle(); handle) {
- handle->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 2a14504..88dcee9 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -43,6 +43,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 17993f5..0e98856 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",
@@ -247,7 +251,7 @@
"latest_android_hardware_audio_common_ndk_shared",
"latest_android_hardware_audio_core_ndk_shared",
"latest_android_hardware_audio_core_sounddose_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: [
@@ -287,7 +291,6 @@
"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 62b9ec7..2951752a 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -20,6 +20,8 @@
#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>
@@ -37,6 +39,7 @@
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;
@@ -299,6 +302,123 @@
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,
@@ -326,8 +446,19 @@
&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)));
StreamContextAidl context(ret.desc);
@@ -337,7 +468,14 @@
return NO_INIT;
}
*outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
- std::move(ret.stream));
+ 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;
}
@@ -883,4 +1021,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 f5dd476..76e832d 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -22,6 +22,7 @@
#include <aidl/android/hardware/audio/core/BpModule.h>
#include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
+#include <android-base/thread_annotations.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -29,7 +30,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;
@@ -127,6 +156,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*/,
@@ -195,16 +230,33 @@
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;
std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>
mSoundDose = nullptr;
Ports mPorts;
- int32_t mDefaultInputPortId;
- int32_t mDefaultOutputPortId;
+ 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 6190596..7e25b04 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -136,29 +136,15 @@
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;
}
- return *static_cast<int32_t*>(pReplyData) = OK;
- 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;
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 2b85f97..7aa8231 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -20,7 +20,6 @@
#include <algorithm>
#include <cstdint>
-#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <audio_utils/clock.h>
#include <mediautils/TimeCheck.h>
#include <utils/Log.h>
@@ -287,12 +286,13 @@
if (status_t status = sendCommand(burst, &reply); status != OK) {
return status;
}
+ *transferred = reply.fmqByteCount;
if (mIsInput) {
- *transferred = reply.fmqByteCount;
LOG_ALWAYS_FATAL_IF(*transferred > bytes,
"%s: HAL module read %zu bytes, which exceeds requested count %zu",
__func__, *transferred, bytes);
- if (!mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), *transferred)) {
+ if (!mContext.getDataMQ()->read(static_cast<int8_t*>(buffer),
+ mContext.getDataMQ()->availableToRead())) {
ALOGE("%s: failed to read %zu bytes to data MQ", __func__, *transferred);
return NOT_ENOUGH_DATA;
}
@@ -448,43 +448,18 @@
return OK;
}
-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();
- }
- ndk::ScopedAStatus onError() override {
- return ndk::ScopedAStatus::ok();
- }
- ndk::ScopedAStatus onDrainReady() override {
- return ndk::ScopedAStatus::ok();
- }
-};
-
-} // namespace
-
StreamOutHalAidl::StreamOutHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<IStreamOut>& stream)
+ const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
: StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
std::move(context), getStreamCommon(stream)),
- mStream(stream) {}
+ mStream(stream), mCallbackBroker(callbackBroker) {}
+
+StreamOutHalAidl::~StreamOutHalAidl() {
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->clearCallbacks(this);
+ }
+}
status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
return StreamHalAidl::getLatency(latency);
@@ -529,10 +504,18 @@
return INVALID_OPERATION;
}
-status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback __unused) {
+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;
}
@@ -639,23 +622,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;
@@ -672,48 +647,15 @@
};
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() {
return StreamHalAidl::exit();
}
@@ -759,7 +701,7 @@
}
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 ce6c31c..f43c8e2 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -27,7 +27,6 @@
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
-#include <mediautils/Synchronization.h>
#include "ConversionHelperAidl.h"
#include "StreamPowerLog.h"
@@ -221,6 +220,8 @@
std::atomic<pid_t> mWorkerTid = -1;
};
+class CallbackBroker;
+
class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
public:
// Return the audio hardware driver estimated latency in milliseconds.
@@ -294,33 +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, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream);
+ 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 {
@@ -339,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(
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/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 038b7df..91c3dea 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;
@@ -89,10 +91,10 @@
return param.writeToValue(&value);
}
case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
- uint16_t value;
- const auto& cap =
- VALUE_OR_RETURN_STATUS(aidl::android::UNION_GET(mDesc.capability, bassBoost));
- value = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(cap.strengthSupported));
+ // an invalid range indicates not setting support for this parameter
+ uint16_t value =
+ ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::bassBoost>(
+ BassBoost::strengthPm, mDesc.capability);
return param.writeToValue(&value);
}
default: {
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/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
index efa9e89..a10d271 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -69,25 +69,7 @@
break;
}
case EQ_PARAM_PROPERTIES: {
- if (value >= 0) {
- aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)value);
- } else {
- std::vector<Equalizer::BandLevel> bandLevels;
- uint16_t numBands;
- if (OK != param.readFromValue(&numBands)) {
- ALOGE("%s invalid bandLevel param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- for (int i = 0; i < numBands; i++) {
- uint16_t level;
- if (OK != param.readFromValue(&level)) {
- ALOGE("%s invalid property param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- bandLevels.push_back({.index = i, .levelMb = level});
- }
- aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
- }
+ // TODO: handle properties setting
break;
}
default: {
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
index 814b58f..9575e7d 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
@@ -34,6 +34,7 @@
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;
@@ -41,27 +42,52 @@
status_t AidlConversionHapticGenerator::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)) {
+ OK != param.readFromParameter(&type)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
Parameter aidlParam;
- // TODO
+ 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));
}
-status_t AidlConversionHapticGenerator::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);
+// No parameter to get for HapticGenerator
+status_t AidlConversionHapticGenerator::getParameter(EffectParamWriter& param __unused) {
+ return OK;
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
index 70e0428..e3c898f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
@@ -34,6 +34,8 @@
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;
@@ -41,27 +43,52 @@
status_t AidlConversionLoudnessEnhancer::setParameter(EffectParamReader& param) {
uint32_t type = 0;
- uint16_t value = 0;
+ int32_t gain = 0;
if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&gain)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
Parameter aidlParam;
- // TODO
+ 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, value = 0;
+ 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;
}
- // TODO
- return param.writeToValue(&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
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
index 5faf645..69184cf 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
@@ -34,33 +34,77 @@
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;
- uint16_t value = 0;
+ 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;
- // TODO
+ 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 type = 0, value = 0;
+ uint32_t paramType = 0, value = 0;
if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type)) {
+ OK != param.readFromParameter(¶mType)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
param.setStatus(BAD_VALUE);
return BAD_VALUE;
}
- // TODO
+ 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);
}
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
index a035614..3baf72e 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
@@ -17,9 +17,11 @@
#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>
@@ -32,34 +34,64 @@
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) {
- 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());
+ size_t len = param.getValueSize();
+ DefaultExtension ext;
+ ext.bytes.resize(len);
+ if (OK != param.readFromValue(ext.bytes.data(), len)) {
+ ALOGE("%s read value from param %s failed", __func__, param.toString().c_str());
return BAD_VALUE;
}
- Parameter aidlParam;
- // TODO
+ VendorExtension effectParam;
+ effectParam.extension.setParcelable(ext);
+ Parameter aidlParam = UNION_MAKE(Parameter, specific,
+ UNION_MAKE(Parameter::Specific, vendorEffect, effectParam));
return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
status_t AidlConversionVendorExtension::getParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type)) {
+ 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;
}
- // TODO
- return param.writeToValue(&value);
+
+ Parameter aidlParam;
+ Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, tag /* parameter tag */);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ VendorExtension effectParam = VALUE_OR_RETURN_STATUS(
+ (::aidl::android::getParameterSpecific<Parameter, VendorExtension,
+ Parameter::Specific::vendorEffect>(aidlParam)));
+ std::optional<DefaultExtension> ext;
+ if (STATUS_OK != effectParam.extension.getParcelable(&ext) || !ext.has_value()) {
+ ALOGE("%s get extension parcelable failed", __func__);
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ const auto& extBytes = ext.value().bytes;
+ 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
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index d5a1a60..2df2f5d 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -35,7 +35,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 6600713..2f78dd0 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -46,6 +46,7 @@
"libaudiohal",
"liblog",
"libutils",
+ "libvibrator",
],
header_libs: [
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index b7742e4..71c7586 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -31,10 +31,14 @@
#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 {
@@ -146,6 +150,9 @@
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 */,
@@ -162,7 +169,23 @@
std::make_tuple(SL_IID_DYNAMICSPROCESSING,
createEffectParamCombination(
std::array<uint32_t, 2>({DP_PARAM_INPUT_GAIN, 0 /* channel */}),
- 30 /* gainDb */, sizeof(int32_t) /* returnValueSize */))};
+ 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:
@@ -186,6 +209,7 @@
}()) {}
void SetUp() override {
+ ASSERT_NE(0ul, mDescs.size());
for (const auto& desc : mDescs) {
sp<EffectHalInterface> interface = createEffectHal(desc);
ASSERT_NE(nullptr, interface);
@@ -237,10 +261,12 @@
&replySize, getParam));
EffectParamReader parameterGet(*getParam);
EXPECT_EQ(replySize, parameterGet.getTotalSize()) << parameterGet.toString();
- std::vector<uint8_t> response(mCombination->valueSize);
- EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
+ if (mCombination->valueSize) {
+ std::vector<uint8_t> response(mCombination->valueSize);
+ EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
<< parameterGet.toString();
- EXPECT_EQ(response, mExpectedValue);
+ EXPECT_EQ(response, mExpectedValue);
+ }
}
const EffectParamTestTuple mParamTuple;
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/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..018f3bc 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) {
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/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/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 6497b58..ec79b99 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -2576,7 +2576,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 0801101..0b6a5bb 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 4f2da67..b197042 100644
--- a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
+++ b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
@@ -198,7 +198,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/Android.bp b/media/libstagefright/Android.bp
index 32e40c3..ddc0f2f 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -238,6 +238,7 @@
"CallbackMediaSource.cpp",
"CameraSource.cpp",
"CameraSourceTimeLapse.cpp",
+ "CryptoAsync.cpp",
"FrameDecoder.cpp",
"HevcUtils.cpp",
"InterfaceUtils.cpp",
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/CryptoAsync.cpp b/media/libstagefright/CryptoAsync.cpp
new file mode 100644
index 0000000..32fd3be
--- /dev/null
+++ b/media/libstagefright/CryptoAsync.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CryptoAsync"
+
+#include <log/log.h>
+
+#include "hidl/HidlSupport.h"
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <media/MediaCodecBuffer.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/CryptoAsync.h>
+
+namespace android {
+
+CryptoAsync::~CryptoAsync() {
+}
+
+status_t CryptoAsync::decrypt(sp<AMessage> &msg) {
+ int32_t decryptAction;
+ CHECK(msg->findInt32("action", &decryptAction));
+ if (mCallback == nullptr) {
+ ALOGE("Crypto callback channel is not set");
+ return -ENOSYS;
+ }
+ bool shouldPost = false;
+ Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
+ if (mState != kCryptoAsyncActive) {
+ ALOGE("Cannot decrypt in errored state");
+ return -ENOSYS;
+ }
+ shouldPost = pendingBuffers->size() == 0 ? true : false;
+ pendingBuffers->push_back(std::move(msg));
+ if (shouldPost) {
+ sp<AMessage> decryptMsg = new AMessage(kWhatDecrypt, this);
+ decryptMsg->post();
+ }
+ return OK;
+}
+
+void CryptoAsync::stop(std::list<sp<AMessage>> * const buffers) {
+ sp<AMessage> stopMsg = new AMessage(kWhatStop, this);
+ stopMsg->setPointer("remaining", static_cast<void*>(buffers));
+ sp<AMessage> response;
+ status_t err = stopMsg->postAndAwaitResponse(&response);
+ if (err == OK && response != NULL) {
+ CHECK(response->findInt32("err", &err));
+ } else {
+ ALOGE("Error handling stop in CryptoAsync");
+ //TODO: handle the error here.
+ }
+}
+
+status_t CryptoAsync::decryptAndQueue(sp<AMessage> & msg) {
+ std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
+ status_t err = OK;
+ sp<RefBase> obj;
+ size_t numSubSamples = 0;
+ int32_t secure = 0;
+ CryptoPlugin::Mode mode;
+ CryptoPlugin::Pattern pattern;
+ sp<ABuffer> keyBuffer;
+ sp<ABuffer> ivBuffer;
+ sp<ABuffer> subSamplesBuffer;
+ msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
+ msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
+ msg->findBuffer("key", &keyBuffer);
+ msg->findBuffer("iv", &ivBuffer);
+ msg->findBuffer("subSamples", &subSamplesBuffer);
+ msg->findInt32("secure", &secure);
+ msg->findSize("numSubSamples", &numSubSamples);
+ msg->findObject("buffer", &obj);
+ msg->findInt32("mode", (int32_t*)&mode);
+ AString errorDetailMsg;
+ const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
+ const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
+ const CryptoPlugin::SubSample * subSamples =
+ (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
+ sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+ err = channel->queueSecureInputBuffer(buffer, secure, key, iv, mode,
+ pattern, subSamples, numSubSamples, &errorDetailMsg);
+ if (err != OK) {
+ std::list<sp<AMessage>> errorList;
+ msg->removeEntryByName("buffer");
+ msg->setInt32("err", err);
+ msg->setInt32("actionCode", ACTION_CODE_FATAL);
+ msg->setString("errorDetail", errorDetailMsg);
+ errorList.push_back(std::move(msg));
+ mCallback->onDecryptError(errorList);
+ }
+ return err;
+}
+
+status_t CryptoAsync::attachEncryptedBufferAndQueue(sp<AMessage> & msg) {
+ std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
+ status_t err = OK;
+ sp<RefBase> obj;
+ sp<RefBase> mem_obj;
+ sp<hardware::HidlMemory> memory;
+ size_t numSubSamples = 0;
+ int32_t secure = 0;
+ size_t offset;
+ size_t size;
+ CryptoPlugin::Mode mode;
+ CryptoPlugin::Pattern pattern;
+ sp<ABuffer> keyBuffer;
+ sp<ABuffer> ivBuffer;
+ sp<ABuffer> subSamplesBuffer;
+ msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
+ msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
+ msg->findBuffer("key", &keyBuffer);
+ msg->findBuffer("iv", &ivBuffer);
+ msg->findBuffer("subSamples", &subSamplesBuffer);
+ msg->findInt32("secure", &secure);
+ msg->findSize("numSubSamples", &numSubSamples);
+ msg->findObject("buffer", &obj);
+ msg->findInt32("mode", (int32_t*)&mode);
+ CHECK(msg->findObject("memory", &mem_obj));
+ CHECK(msg->findSize("offset", (size_t*)&offset));
+ AString errorDetailMsg;
+ // get key info
+ const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
+ // get iv info
+ const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
+
+ const CryptoPlugin::SubSample * subSamples =
+ (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
+
+ // get MediaCodecBuffer
+ sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+
+ // get HidlMemory
+ memory = static_cast<MediaCodec::WrapperObject<sp<hardware::HidlMemory>> *>
+ (mem_obj.get())->value;
+
+ // attach buffer
+ err = channel->attachEncryptedBuffer(
+ memory, secure, key, iv, mode, pattern,
+ offset, subSamples, numSubSamples, buffer);
+
+ // a generic error
+ auto handleError = [this, &err, &msg]() {
+ std::list<sp<AMessage>> errorList;
+ msg->removeEntryByName("buffer");
+ msg->setInt32("err", err);
+ msg->setInt32("actionCode", ACTION_CODE_FATAL);
+ errorList.push_back(std::move(msg));
+ mCallback->onDecryptError(errorList);
+ };
+ if (err != OK) {
+ handleError();
+ return err;
+ }
+ offset = buffer->offset();
+ size = buffer->size();
+
+ if (offset + size > buffer->capacity()) {
+ err = -ENOSYS;
+ handleError();
+ return err;
+ }
+ buffer->setRange(offset, size);
+ err = channel->queueInputBuffer(buffer);
+ if (err != OK) {
+ handleError();
+ return err;
+ }
+ return err;
+}
+
+void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
+ status_t err = OK;
+ auto getCurrentAndNextTask =
+ [this](sp<AMessage> * const current, uint32_t & nextTask) -> status_t {
+ sp<AMessage> obj;
+ Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
+ if ((pendingBuffers->size() == 0) || (mState != kCryptoAsyncActive)) {
+ return -ENOMSG;
+ }
+ *current = std::move(*(pendingBuffers->begin()));
+ pendingBuffers->pop_front();
+ //Try to see if we will be able to process next buffer
+ while((nextTask == kWhatDoNothing) && pendingBuffers->size() > 0)
+ {
+ sp<AMessage> & nextBuffer = pendingBuffers->front();
+ if (nextBuffer == nullptr) {
+ pendingBuffers->pop_front();
+ continue;
+ }
+ nextTask = kWhatDecrypt;
+ }
+ return OK;
+ };
+ switch(msg->what()) {
+ case kWhatDecrypt:
+ {
+ sp<AMessage> thisMsg;
+ uint32_t nextTask = kWhatDoNothing;
+ if(OK != getCurrentAndNextTask(&thisMsg, nextTask)) {
+ return;
+ }
+ if (thisMsg != nullptr) {
+ int32_t action;
+ err = OK;
+ CHECK(thisMsg->findInt32("action", &action));
+ switch(action) {
+ case kActionDecrypt:
+ {
+ err = decryptAndQueue(thisMsg);
+ break;
+ }
+
+ case kActionAttachEncryptedBuffer:
+ {
+ err = attachEncryptedBufferAndQueue(thisMsg);
+ break;
+ }
+
+ default:
+ {
+ ALOGE("Unrecognized action in decrypt");
+ }
+ }
+ if (err != OK) {
+ Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
+ mState = kCryptoAsyncError;
+ }
+ }
+ // we won't take next buffers if buffer caused
+ // an error. We want the caller to deal with the error first
+ // Expected behahiour is that the caller acknowledge the error
+ // with a call to stop() which clear the queues.
+ // Then move forward with processing of next set of buffers.
+ if (mState == kCryptoAsyncActive && nextTask != kWhatDoNothing) {
+ sp<AMessage> nextMsg = new AMessage(nextTask,this);
+ nextMsg->post();
+ }
+ break;
+ }
+
+ case kWhatStop:
+ {
+ typedef std::list<sp<AMessage>> ReturnListType;
+ ReturnListType * returnList = nullptr;
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+ sp<AMessage> response = new AMessage;
+ msg->findPointer("remaining", (void**)(&returnList));
+ Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
+ if (returnList) {
+ returnList->clear();
+ returnList->splice(returnList->end(), std::move(*pendingBuffers));
+ }
+ pendingBuffers->clear();
+ mState = kCryptoAsyncActive;
+ response->setInt32("err", OK);
+ response->postReply(replyID);
+
+ break;
+ }
+
+ default:
+ {
+ status_t err = OK;
+ //TODO: do something with error here.
+ (void)err;
+ break;
+ }
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7237bb2..a60c04f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -69,6 +69,7 @@
#include <media/stagefright/BatteryChecker.h>
#include <media/stagefright/BufferProducerWrapper.h>
#include <media/stagefright/CCodec.h>
+#include <media/stagefright/CryptoAsync.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaCodecList.h>
@@ -495,6 +496,7 @@
kWhatReleaseCompleted = 'rcom',
kWhatFlushCompleted = 'fcom',
kWhatError = 'erro',
+ kWhatCryptoError = 'ercp',
kWhatComponentAllocated = 'cAll',
kWhatComponentConfigured = 'cCon',
kWhatInputSurfaceCreated = 'isfc',
@@ -505,6 +507,40 @@
kWhatFirstTunnelFrameReady = 'ftfR',
};
+class CryptoAsyncCallback : public CryptoAsync::CryptoAsyncCallback {
+public:
+
+ explicit CryptoAsyncCallback(const sp<AMessage> & notify):mNotify(notify) {
+ }
+
+ ~CryptoAsyncCallback() {}
+
+ void onDecryptComplete(const sp<AMessage> &result) override {
+ (void)result;
+ }
+
+ void onDecryptError(const std::list<sp<AMessage>> &errorMsgs) override {
+ // This error may be decrypt/queue error.
+ status_t errorCode ;
+ for (auto &emsg : errorMsgs) {
+ sp<AMessage> notify(mNotify->dup());
+ if(emsg->findInt32("err", &errorCode)) {
+ if (isCryptoError(errorCode)) {
+ notify->setInt32("what", kWhatCryptoError);
+ } else {
+ notify->setInt32("what", kWhatError);
+ }
+ notify->extend(emsg);
+ notify->post();
+ } else {
+ ALOGW("Buffers with no errorCode are not expected");
+ }
+ }
+ }
+private:
+ const sp<AMessage> mNotify;
+};
+
class BufferCallback : public CodecBase::BufferCallback {
public:
explicit BufferCallback(const sp<AMessage> ¬ify);
@@ -1686,7 +1722,6 @@
mBufferChannel->setCallback(
std::unique_ptr<CodecBase::BufferCallback>(
new BufferCallback(new AMessage(kWhatCodecNotify, this))));
-
sp<AMessage> msg = new AMessage(kWhatInit, this);
if (mCodecInfo) {
msg->setObject("codecInfo", mCodecInfo);
@@ -1799,7 +1834,6 @@
if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
mRotationDegrees = 0;
}
-
if (nextMetricsHandle != 0) {
mediametrics_setInt32(nextMetricsHandle, kCodecWidth, mWidth);
mediametrics_setInt32(nextMetricsHandle, kCodecHeight, mHeight);
@@ -3275,9 +3309,10 @@
{
int32_t what;
CHECK(msg->findInt32("what", &what));
-
+ AString codecErrorState;
switch (what) {
case kWhatError:
+ case kWhatCryptoError:
{
int32_t err, actionCode;
CHECK(msg->findInt32("err", &err));
@@ -3290,11 +3325,20 @@
mFlags |= kFlagSawMediaServerDie;
mFlags &= ~kFlagIsComponentAllocated;
}
-
bool sendErrorResponse = true;
- std::string origin{"kWhatError:"};
+ std::string origin;
+ if (what == kWhatCryptoError) {
+ origin = "kWhatCryptoError:";
+ } else {
+ origin = "kWhatError:";
+ //TODO: add a new error state
+ }
+ codecErrorState = kCodecErrorState;
origin += stateString(mState);
-
+ if (mCryptoAsync) {
+ //TODO: do some book keeping on the buffers
+ mCryptoAsync->stop();
+ }
switch (mState) {
case INITIALIZING:
{
@@ -3396,7 +3440,11 @@
cancelPendingDequeueOperations();
if (mFlags & kFlagIsAsync) {
- onError(err, actionCode);
+ if (what == kWhatError) {
+ onError(err, actionCode);
+ } else if (what == kWhatCryptoError) {
+ onCryptoError(msg);
+ }
}
switch (actionCode) {
case ACTION_CODE_TRANSIENT:
@@ -3428,7 +3476,11 @@
actionCode = ACTION_CODE_FATAL;
}
if (mFlags & kFlagIsAsync) {
- onError(err, actionCode);
+ if (what == kWhatError) {
+ onError(err, actionCode);
+ } else if (what == kWhatCryptoError) {
+ onCryptoError(msg);
+ }
}
switch (actionCode) {
case ACTION_CODE_TRANSIENT:
@@ -4110,12 +4162,24 @@
uint32_t flags;
CHECK(msg->findInt32("flags", (int32_t *)&flags));
- if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) {
+ if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL ||
+ flags & CONFIGURE_FLAG_USE_CRYPTO_ASYNC) {
if (!(mFlags & kFlagIsAsync)) {
+ ALOGE("Error: configuration requires async operation");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
- mFlags |= kFlagUseBlockModel;
+ if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) {
+ mFlags |= kFlagUseBlockModel;
+ }
+ if (flags & CONFIGURE_FLAG_USE_CRYPTO_ASYNC) {
+ // silently disable crytoasync with blockmodel
+ if (!(mFlags & kFlagUseBlockModel)) {
+ mFlags |= kFlagUseCryptoAsync;
+ } else {
+ ALOGW("CrytoAsync not yet enabled for block model, falling back to normal");
+ }
+ }
}
mReplyID = replyID;
setState(CONFIGURING);
@@ -4141,6 +4205,21 @@
mDescrambler = static_cast<IDescrambler *>(descrambler);
mBufferChannel->setDescrambler(mDescrambler);
+ if ((mFlags & kFlagUseCryptoAsync) &&
+ mCrypto && (mDomain == DOMAIN_VIDEO)) {
+ mCryptoAsync = new CryptoAsync(mBufferChannel);
+ mCryptoAsync->setCallback(
+ std::make_unique<CryptoAsyncCallback>(new AMessage(kWhatCodecNotify, this)));
+ mCryptoLooper = new ALooper();
+ mCryptoLooper->setName("CryptoAsyncLooper");
+ mCryptoLooper->registerHandler(mCryptoAsync);
+ status_t err = mCryptoLooper->start();
+ if (err != OK) {
+ ALOGE("Crypto Looper failed to start");
+ mCryptoAsync = nullptr;
+ mCryptoLooper = nullptr;
+ }
+ }
format->setInt32("flags", flags);
if (flags & CONFIGURE_FLAG_ENCODE) {
@@ -4310,7 +4389,9 @@
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
-
+ if (mCryptoAsync) {
+ mCryptoAsync->stop();
+ }
sp<AMessage> asyncNotify;
(void)msg->findMessage("async", &asyncNotify);
// post asyncNotify if going out of scope.
@@ -4730,7 +4811,11 @@
mReplyID = replyID;
// TODO: skip flushing if already FLUSHED
setState(FLUSHING);
-
+ if (mCryptoAsync) {
+ std::list<sp<AMessage>> pendingBuffers;
+ mCryptoAsync->stop(&pendingBuffers);
+ //TODO: do something with these buffers
+ }
mCodec->signalFlush();
returnBuffersToCodec();
TunnelPeekState previousState = mTunnelPeekState;
@@ -5168,7 +5253,7 @@
CHECK(msg->findSize("offset", &offset));
}
const CryptoPlugin::SubSample *subSamples;
- size_t numSubSamples;
+ size_t numSubSamples = 0;
const uint8_t *key = NULL;
const uint8_t *iv = NULL;
CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
@@ -5194,7 +5279,6 @@
mComponentName.c_str());
return -EINVAL;
}
-
CHECK(msg->findPointer("subSamples", (void **)&subSamples));
CHECK(msg->findSize("numSubSamples", &numSubSamples));
CHECK(msg->findPointer("key", (void **)&key));
@@ -5220,13 +5304,83 @@
BufferInfo *info = &mPortBuffers[kPortIndexInput][index];
sp<MediaCodecBuffer> buffer = info->mData;
+ if (buffer == nullptr || !info->mOwnedByClient) {
+ return -EACCES;
+ }
+ auto setInputBufferParams = [this, &buffer]
+ (int64_t timeUs, uint32_t flags = 0) -> status_t {
+ status_t err = OK;
+ buffer->meta()->setInt64("timeUs", timeUs);
+ if (flags & BUFFER_FLAG_EOS) {
+ buffer->meta()->setInt32("eos", true);
+ }
+ if (flags & BUFFER_FLAG_CODECCONFIG) {
+ buffer->meta()->setInt32("csd", true);
+ }
+ bool isBufferDecodeOnly = ((flags & BUFFER_FLAG_DECODE_ONLY) != 0);
+ if (isBufferDecodeOnly) {
+ buffer->meta()->setInt32("decode-only", true);
+ }
+ if (mTunneled && !isBufferDecodeOnly) {
+ TunnelPeekState previousState = mTunnelPeekState;
+ switch(mTunnelPeekState){
+ case TunnelPeekState::kEnabledNoBuffer:
+ buffer->meta()->setInt32("tunnel-first-frame", 1);
+ mTunnelPeekState = TunnelPeekState::kEnabledQueued;
+ ALOGV("TunnelPeekState: %s -> %s",
+ asString(previousState),
+ asString(mTunnelPeekState));
+ break;
+ case TunnelPeekState::kDisabledNoBuffer:
+ buffer->meta()->setInt32("tunnel-first-frame", 1);
+ mTunnelPeekState = TunnelPeekState::kDisabledQueued;
+ ALOGV("TunnelPeekState: %s -> %s",
+ asString(previousState),
+ asString(mTunnelPeekState));
+ break;
+ default:
+ break;
+ }
+ }
+ return err;
+ };
+ auto buildCryptoInfoAMessage = [&](const sp<AMessage> & cryptoInfo, int32_t action) {
+ size_t key_len = (key != nullptr)? 16 : 0;
+ size_t iv_len = (iv != nullptr)? 16 : 0;
+ sp<ABuffer> shared_key;
+ sp<ABuffer> shared_iv;
+ if (key_len > 0) {
+ shared_key = ABuffer::CreateAsCopy((void*)key, key_len);
+ }
+ if (iv_len > 0) {
+ shared_iv = ABuffer::CreateAsCopy((void*)iv, iv_len);
+ }
+ sp<ABuffer> subSamples_buffer =
+ new ABuffer(sizeof(CryptoPlugin::SubSample) * numSubSamples);
+ CryptoPlugin::SubSample * samples =
+ (CryptoPlugin::SubSample *)(subSamples_buffer.get()->data());
+ for (int s = 0 ; s < numSubSamples ; s++) {
+ samples[s].mNumBytesOfClearData = subSamples[s].mNumBytesOfClearData;
+ samples[s].mNumBytesOfEncryptedData = subSamples[s].mNumBytesOfEncryptedData;
+ }
+ // set decrypt Action
+ cryptoInfo->setInt32("action", action);
+ cryptoInfo->setObject("buffer", buffer);
+ cryptoInfo->setInt32("secure", mFlags & kFlagIsSecure);
+ cryptoInfo->setBuffer("key", shared_key);
+ cryptoInfo->setBuffer("iv", shared_iv);
+ cryptoInfo->setInt32("mode", (int)mode);
+ cryptoInfo->setInt32("encryptBlocks", pattern.mEncryptBlocks);
+ cryptoInfo->setInt32("skipBlocks", pattern.mSkipBlocks);
+ cryptoInfo->setBuffer("subSamples", subSamples_buffer);
+ cryptoInfo->setSize("numSubSamples", numSubSamples);
+ };
if (c2Buffer || memory) {
sp<AMessage> tunings = NULL;
if (msg->findMessage("tunings", &tunings) && tunings != NULL) {
onSetParameters(tunings);
}
-
status_t err = OK;
if (c2Buffer) {
err = mBufferChannel->attachBuffer(c2Buffer, buffer);
@@ -5237,7 +5391,6 @@
} else {
err = UNKNOWN_ERROR;
}
-
if (err == OK && !buffer->asC2Buffer()
&& c2Buffer && c2Buffer->data().type() == C2BufferData::LINEAR) {
C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()};
@@ -5253,63 +5406,23 @@
flags &= ~BUFFER_FLAG_EOS;
}
}
-
offset = buffer->offset();
size = buffer->size();
if (err != OK) {
ALOGI("block model buffer attach failed: err = %s (%d)",
- StrMediaError(err).c_str(), err);
+ StrMediaError(err).c_str(), err);
return err;
}
}
-
- if (buffer == nullptr || !info->mOwnedByClient) {
- return -EACCES;
- }
-
if (offset + size > buffer->capacity()) {
return -EINVAL;
}
-
buffer->setRange(offset, size);
- buffer->meta()->setInt64("timeUs", timeUs);
-
- if (flags & BUFFER_FLAG_EOS) {
- buffer->meta()->setInt32("eos", true);
- }
-
- if (flags & BUFFER_FLAG_CODECCONFIG) {
- buffer->meta()->setInt32("csd", true);
- }
-
- bool isBufferDecodeOnly = ((flags & BUFFER_FLAG_DECODE_ONLY) != 0);
- if (isBufferDecodeOnly) {
- buffer->meta()->setInt32("decode-only", true);
- }
-
- if (mTunneled && !isBufferDecodeOnly) {
- TunnelPeekState previousState = mTunnelPeekState;
- switch(mTunnelPeekState){
- case TunnelPeekState::kEnabledNoBuffer:
- buffer->meta()->setInt32("tunnel-first-frame", 1);
- mTunnelPeekState = TunnelPeekState::kEnabledQueued;
- ALOGV("TunnelPeekState: %s -> %s",
- asString(previousState),
- asString(mTunnelPeekState));
- break;
- case TunnelPeekState::kDisabledNoBuffer:
- buffer->meta()->setInt32("tunnel-first-frame", 1);
- mTunnelPeekState = TunnelPeekState::kDisabledQueued;
- ALOGV("TunnelPeekState: %s -> %s",
- asString(previousState),
- asString(mTunnelPeekState));
- break;
- default:
- break;
- }
- }
-
status_t err = OK;
+ err = setInputBufferParams(timeUs, flags);
+ if (err != OK) {
+ return -EINVAL;
+ }
if (hasCryptoOrDescrambler() && !c2Buffer && !memory) {
AString *errorDetailMsg;
CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
@@ -5325,7 +5438,13 @@
}
}
}
- err = mBufferChannel->queueSecureInputBuffer(
+ if (mCryptoAsync) {
+ // prepare a message and enqueue
+ sp<AMessage> cryptoInfo = new AMessage();
+ buildCryptoInfoAMessage(cryptoInfo, CryptoAsync::kActionDecrypt);
+ mCryptoAsync->decrypt(cryptoInfo);
+ } else {
+ err = mBufferChannel->queueSecureInputBuffer(
buffer,
(mFlags & kFlagIsSecure),
key,
@@ -5335,6 +5454,7 @@
subSamples,
numSubSamples,
errorDetailMsg);
+ }
if (err != OK) {
mediametrics_setInt32(mMetricsHandle, kCodecQueueSecureInputBufferError, err);
ALOGW("Log queueSecureInputBuffer error: %d", err);
@@ -5626,7 +5746,14 @@
msg->post();
}
}
-
+void MediaCodec::onCryptoError(const sp<AMessage> & msg) {
+ if (mCallback != NULL) {
+ sp<AMessage> cb_msg = mCallback->dup();
+ cb_msg->setInt32("callbackID", CB_CRYPTO_ERROR);
+ cb_msg->extend(msg);
+ cb_msg->post();
+ }
+}
void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
if (mCallback != NULL) {
sp<AMessage> msg = mCallback->dup();
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index f526e05..291b892 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);
@@ -232,14 +260,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
@@ -257,7 +285,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);
@@ -278,34 +306,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/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index 2c258e4..b1d7ff4 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -124,7 +124,8 @@
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-3600" />
<Limit name="bitrate" range="1-40000000" />
- <Feature name="bitrate-modes" value="VBR,CBR" />
+ <Limit name="quality" range="0-100" default="80" />
+ <Feature name="bitrate-modes" value="VBR,CBR,CQ" />
</MediaCodec>
</Encoders>
</Included>
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 05f2760..5f113c5 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -357,7 +357,8 @@
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-8200" />
<Limit name="bitrate" range="1-40000000" />
- <Feature name="bitrate-modes" value="VBR,CBR" />
+ <Limit name="quality" range="0-100" default="80" />
+ <Feature name="bitrate-modes" value="VBR,CBR,CQ" />
<Attribute name="software-codec" />
</MediaCodec>
</Encoders>
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/CryptoAsync.h b/media/libstagefright/include/media/stagefright/CryptoAsync.h
new file mode 100644
index 0000000..b675518
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/CryptoAsync.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CRYPTO_ASYNC_H_
+#define CRYPTO_ASYNC_H_
+
+#include <media/stagefright/CodecBase.h>
+#include <media/stagefright/foundation/Mutexed.h>
+namespace android {
+
+class CryptoAsync: public AHandler {
+public:
+
+ class CryptoAsyncCallback {
+ public:
+
+ virtual ~CryptoAsyncCallback() = default;
+
+ /*
+ * Callback with result for queuing the decrypted buffer to the
+ * underlying codec. Cannot block this function
+ */
+ virtual void onDecryptComplete(const sp<AMessage>& result) = 0;
+
+ /*
+ * Callback with error information while decryption. Cannot block
+ * this call. The return should contain the error information
+ * and the buffer the caused the error.
+ */
+ virtual void onDecryptError(const std::list<sp<AMessage>>& errorMsg) = 0;
+ };
+
+ // Ideally we should be returning the output of the decryption in
+ // onDecryptComple() calback and let the next module take over the
+ // rest of the processing. In the current state, the next step will
+ // be to queue the output the codec which is done using BufferChannel
+
+ // In order to prevent thread hop to just do that, we have created
+ // a dependency on BufferChannel here to queue the buffer to the codec
+ // immediately after decryption.
+ CryptoAsync(std::weak_ptr<BufferChannelBase> bufferChannel)
+ :mState(kCryptoAsyncActive) {
+ mBufferChannel = std::move(bufferChannel);
+ }
+
+ // Destructor
+ virtual ~CryptoAsync();
+
+ inline void setCallback(std::unique_ptr<CryptoAsyncCallback>&& callback) {
+ mCallback = std::move(callback);
+ }
+
+ // Call this function to decrypt the buffer in the message.
+ status_t decrypt(sp<AMessage>& msg);
+
+ // This function stops further processing in the thread and returns
+ // with any unprocessed buffers from the queue.
+ // We can use this method in case of flush or clearing the queue
+ // upon error. When the processing hits an error, the self processing
+ // in this looper stops and in-fact., there is a need to clear (call stop())
+ // for the queue to become operational again. Also acts like a rest.
+ void stop(std::list<sp<AMessage>> * const buffers = nullptr);
+
+ // Describes two actions for decrypt();
+ // kActionDecrypt - decrypts the buffer and queues to codec
+ // kActionAttachEncryptedBuffer - decrypts and attaches the buffer
+ // and queues to the codec.
+ // TODO: kActionAttachEncryptedBuffer is meant to work with
+ // BLOCK_MODEL which is not yet implemented.
+ enum : uint32_t {
+ // decryption types
+ kActionDecrypt = (1 << 0),
+ kActionAttachEncryptedBuffer = (1 << 1)
+ };
+protected:
+
+ // Message types for the looper
+ enum : uint32_t {
+ // used with decrypt()
+ // Exact decryption type as described by the above enum
+ // decides what "action" to take. The "action" should be
+ // part of this message
+ kWhatDecrypt = 1,
+ // used with stop()
+ kWhatStop = 2,
+ // place holder
+ kWhatDoNothing = 10
+ };
+
+ // Defines the staste of this thread.
+ typedef enum : uint32_t {
+ // kCryptoAsyncActive as long as we have not encountered
+ // any errors during processing. Any errors will
+ // put the state to error and the thread now refuses to
+ // do further processing until the error state is cleared
+ // with a call to stop()
+
+ kCryptoAsyncActive = (0 << 0),
+ // state of the looper when encountered with error during
+ // processing
+ kCryptoAsyncError = (1 << 8)
+ } CryptoAsyncState;
+
+ // Implements kActionDecrypt
+ status_t decryptAndQueue(sp<AMessage>& msg);
+
+ // Implements kActionAttachEncryptedBuffer
+ status_t attachEncryptedBufferAndQueue(sp<AMessage>& msg);
+
+ // Implements the Looper
+ void onMessageReceived(const sp<AMessage>& msg) override;
+
+ std::unique_ptr<CryptoAsyncCallback> mCallback;
+private:
+
+ CryptoAsyncState mState;
+
+ // Queue holding any pending buffers
+ Mutexed<std::list<sp<AMessage>>> mPendingBuffers;
+
+ std::weak_ptr<BufferChannelBase> mBufferChannel;
+};
+
+} // namespace android
+
+#endif // CRYPTO_ASYNC_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index dbc97db..65d9f7d 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -55,6 +55,7 @@
struct CodecParameterDescriptor;
class IBatteryStats;
struct ICrypto;
+class CryptoAsync;
class MediaCodecBuffer;
class IMemory;
struct PersistentSurface;
@@ -82,6 +83,7 @@
enum ConfigureFlags {
CONFIGURE_FLAG_ENCODE = 1,
CONFIGURE_FLAG_USE_BLOCK_MODEL = 2,
+ CONFIGURE_FLAG_USE_CRYPTO_ASYNC = 4,
};
enum BufferFlags {
@@ -106,6 +108,7 @@
CB_ERROR = 3,
CB_OUTPUT_FORMAT_CHANGED = 4,
CB_RESOURCE_RECLAIMED = 5,
+ CB_CRYPTO_ERROR = 6,
};
static const pid_t kNoPid = -1;
@@ -376,6 +379,7 @@
kFlagIsComponentAllocated = 2048,
kFlagPushBlankBuffersOnShutdown = 4096,
kFlagUseBlockModel = 8192,
+ kFlagUseCryptoAsync = 16384,
};
struct BufferInfo {
@@ -530,6 +534,8 @@
bool mCpuBoostRequested;
std::shared_ptr<BufferChannelBase> mBufferChannel;
+ sp<CryptoAsync> mCryptoAsync;
+ sp<ALooper> mCryptoLooper;
std::unique_ptr<PlaybackDurationAccumulator> mPlaybackDurationAccumulator;
bool mIsSurfaceToScreen;
@@ -583,6 +589,7 @@
void onInputBufferAvailable();
void onOutputBufferAvailable();
+ void onCryptoError(const sp<AMessage> &msg);
void onError(status_t err, int32_t actionCode, const char *detail = NULL);
void onOutputFormatChanged();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
index a4ba36a..9e0d5e4 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -48,6 +48,9 @@
private boolean mSawOutputEOS;
private boolean mSignalledError;
+ private int mNumInFramesProvided;
+ private int mNumInFramesRequired;
+
private int mNumOutputFrame;
private int mIndex;
@@ -87,6 +90,10 @@
}
public void setupDecoder(Surface surface, boolean render,
boolean useFrameReleaseQueue, int frameRate) {
+ setupDecoder(surface, render, useFrameReleaseQueue, frameRate, -1);
+ }
+ public void setupDecoder(Surface surface, boolean render,
+ boolean useFrameReleaseQueue, int frameRate, int numInFramesRequired) {
mSignalledError = false;
mOutputStream = null;
mSurface = surface;
@@ -95,6 +102,8 @@
Log.i(TAG, "Using FrameReleaseQueue with frameRate " + frameRate);
mFrameReleaseQueue = new FrameReleaseQueue(mRender, frameRate);
}
+ mNumInFramesRequired = numInFramesRequired;
+ Log.i(TAG, "Decoding " + mNumInFramesRequired + " frames");
}
private MediaCodec createCodec(String codecName, MediaFormat format) throws IOException {
@@ -147,6 +156,10 @@
mSawOutputEOS = false;
mNumOutputFrame = 0;
mIndex = 0;
+ mNumInFramesProvided = 0;
+ if (mNumInFramesRequired < 0) {
+ mNumInFramesRequired = mInputBuffer.size();
+ }
long sTime = mStats.getCurTime();
mCodec = createCodec(codecName, format);
if (mCodec == null) {
@@ -305,12 +318,22 @@
}
private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
- if ((inputBufferId >= 0) && !mSawInputEOS) {
+ if (inputBufferId >= 0) {
ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
- BufferInfo bufInfo = mInputBufferInfo.get(mIndex);
- inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
- mIndex++;
+ BufferInfo bufInfo;
+ if (mNumInFramesProvided >= mNumInFramesRequired) {
+ Log.i(TAG, "Input frame limit reached");
+ mIndex = mInputBufferInfo.size() - 1;
+ bufInfo = mInputBufferInfo.get(mIndex);
+ if ((bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
+ Log.e(TAG, "Error in EOS flag for Decoder");
+ }
+ }
+ bufInfo = mInputBufferInfo.get(mIndex);
mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
+ mNumInFramesProvided++;
+ mIndex = mNumInFramesProvided % (mInputBufferInfo.size() - 1);
if (mSawInputEOS) {
Log.i(TAG, "Saw input EOS");
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
index 4b9b505..84554d3 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
@@ -31,6 +31,8 @@
private boolean doFrameRelease = false;
private boolean mRender = false;
private int mWaitTime = 40; // milliseconds per frame
+ private int mWaitTimeCorrection = 0;
+ private int mCorrectionLoopCount;
private int firstReleaseTime = -1;
private int THRESHOLD_TIME = 5;
@@ -48,29 +50,40 @@
private class ReleaseThread extends Thread {
public void run() {
int nextReleaseTime = 0;
+ int loopCount = 0;
while (doFrameRelease || mFrameInfoQueue.size() > 0) {
FrameInfo curFrameInfo = mFrameInfoQueue.peek();
if (curFrameInfo == null) {
nextReleaseTime += mWaitTime;
} else {
- if (firstReleaseTime == -1) {
+ if (curFrameInfo.displayTime == 0) {
+ // first frame of loop
firstReleaseTime = getCurSysTime();
nextReleaseTime = firstReleaseTime + mWaitTime;
- popAndRelease(curFrameInfo);
+ popAndRelease(curFrameInfo, true);
+ } else if (!doFrameRelease && mFrameInfoQueue.size() == 1) {
+ // EOS
+ Log.i(TAG, "EOS");
+ popAndRelease(curFrameInfo, false);
} else {
nextReleaseTime += mWaitTime;
int curSysTime = getCurSysTime();
int curMediaTime = curSysTime - firstReleaseTime;
- while (curFrameInfo != null && curFrameInfo.displayTime <= curMediaTime) {
+ while (curFrameInfo != null && curFrameInfo.displayTime > 0 &&
+ curFrameInfo.displayTime <= curMediaTime) {
if (!((curMediaTime - curFrameInfo.displayTime) < THRESHOLD_TIME)) {
- Log.d(TAG, "Dropping expired frame " + curFrameInfo.number);
+ Log.d(TAG, "Dropping expired frame " + curFrameInfo.number +
+ " display time " + curFrameInfo.displayTime +
+ " current time " + curMediaTime);
+ popAndRelease(curFrameInfo, false);
+ } else {
+ popAndRelease(curFrameInfo, true);
}
- popAndRelease(curFrameInfo);
curFrameInfo = mFrameInfoQueue.peek();
}
if (curFrameInfo != null && curFrameInfo.displayTime > curMediaTime) {
if ((curFrameInfo.displayTime - curMediaTime) < THRESHOLD_TIME) {
- popAndRelease(curFrameInfo);
+ popAndRelease(curFrameInfo, true);
}
}
}
@@ -85,6 +98,10 @@
} else {
Log.d(TAG, "Thread sleep time less than 1");
}
+ if (loopCount % mCorrectionLoopCount == 0) {
+ nextReleaseTime += mWaitTimeCorrection;
+ }
+ loopCount += 1;
}
}
}
@@ -94,10 +111,18 @@
this.mReleaseThread = new ReleaseThread();
this.doFrameRelease = true;
this.mRender = render;
- this.mWaitTime = (int)(1.0f/frameRate * 1000); // wait time in milliseconds per frame
+ this.mWaitTime = 1000 / frameRate; // wait time in milliseconds per frame
+ int waitTimeRemainder = 1000 % frameRate;
+ int gcd = gcd(frameRate, waitTimeRemainder);
+ this.mCorrectionLoopCount = frameRate / gcd;
+ this.mWaitTimeCorrection = waitTimeRemainder / gcd;
Log.i(TAG, "Constructed FrameReleaseQueue with wait time " + this.mWaitTime + " ms");
}
+ private static int gcd(int a, int b) {
+ return b == 0 ? a : gcd(b, a % b);
+ }
+
public void setMediaCodec(MediaCodec mediaCodec) {
this.mCodec = mediaCodec;
}
@@ -121,14 +146,15 @@
return (int)(System.nanoTime()/1000000);
}
- private void popAndRelease(FrameInfo curFrameInfo) {
+ private void popAndRelease(FrameInfo curFrameInfo, boolean renderThisFrame) {
try {
curFrameInfo = mFrameInfoQueue.take();
} catch (InterruptedException e) {
Log.e(TAG, "Threw InterruptedException on take");
}
+ boolean actualRender = (renderThisFrame && mRender);
try {
- mCodec.releaseOutputBuffer(curFrameInfo.bufferId, mRender);
+ mCodec.releaseOutputBuffer(curFrameInfo.bufferId, actualRender);
} catch (IllegalStateException e) {
Log.e(TAG,
"Threw IllegalStateException on releaseOutputBuffer for frame "
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 698752f..7abb0b6 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -103,6 +103,13 @@
logtags: ["EventLogTags.logtags"],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ ],
+
export_shared_lib_headers: [
"libpermission",
],
diff --git a/media/utils/TimerThread.cpp b/media/utils/TimerThread.cpp
index b760ee2..3966103 100644
--- a/media/utils/TimerThread.cpp
+++ b/media/utils/TimerThread.cpp
@@ -288,6 +288,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;
@@ -381,6 +382,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 d5be177..d84d682 100644
--- a/media/utils/include/mediautils/TimerThread.h
+++ b/media/utils/include/mediautils/TimerThread.h
@@ -340,7 +340,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 7bb0fd3..3b73333 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2857,7 +2857,7 @@
return mAudioManager.load();
}
-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;
@@ -2870,8 +2870,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;
}
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index e8133d9..9fc503b 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -281,7 +281,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);
@@ -726,7 +726,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 daec57e..f0a5f76 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 4ca8a8e..fdf3306 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8949,7 +8949,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 f829efc..ddae7ae 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1982,7 +1982,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 382e4f9..1fbf720 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2391,15 +2391,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(
@@ -2719,7 +2713,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 f4a3a94..6d7ed75 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -603,7 +603,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);
@@ -1043,7 +1046,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;
}
@@ -2132,6 +2135,10 @@
}
}
+ if (client->hasPreferredDevice()) {
+ // playback activity with preferred device impacts routing occurred, inform upper layers
+ mpClientInterface->onRoutingUpdated();
+ }
if (delayMs != 0) {
usleep(delayMs * 1000);
}
@@ -2392,6 +2399,11 @@
}
sp<TrackClientDescriptor> client = outputDesc->getClient(portId);
+ if (client->hasPreferredDevice(true)) {
+ // playback activity with preferred device impacts routing occurred, inform upper layers
+ mpClientInterface->onRoutingUpdated();
+ }
+
ALOGV("stopOutput() output %d, stream %d, session %d",
outputDesc->mIoHandle, client->stream(), client->session());
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
index 74497d1..e80064a 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.cpp
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "CameraServiceWatchdog"
#include "CameraServiceWatchdog.h"
+#include "utils/CameraServiceProxyWrapper.h"
namespace android {
@@ -43,6 +44,8 @@
if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(),
currentThreadId);
+ mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/,
+ true /*deviceError*/);
// We use abort here so we can get a tombstone for better
// debugging.
abort();
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index e35d69e..6617873 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -32,10 +32,13 @@
#include <chrono>
#include <thread>
#include <time.h>
+#include <utils/String8.h>
#include <utils/Thread.h>
#include <utils/Log.h>
#include <unordered_map>
+#include "utils/CameraServiceProxyWrapper.h"
+
// Used to wrap the call of interest in start and stop calls
#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
@@ -50,12 +53,18 @@
class CameraServiceWatchdog : public Thread {
public:
- explicit CameraServiceWatchdog() : mPause(true), mMaxCycles(kMaxCycles),
- mCycleLengthMs(kCycleLengthMs), mEnabled(true) {};
+ explicit CameraServiceWatchdog(const String8 &cameraId,
+ std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
+ mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
+ mCycleLengthMs(kCycleLengthMs), mEnabled(true),
+ mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
- explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs, bool enabled) :
- mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs), mEnabled(enabled)
- {};
+ explicit CameraServiceWatchdog (const String8 &cameraId, size_t maxCycles,
+ uint32_t cycleLengthMs, bool enabled,
+ std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
+ mCameraId(cameraId), mPause(true), mMaxCycles(maxCycles),
+ mCycleLengthMs(cycleLengthMs), mEnabled(enabled),
+ mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
virtual ~CameraServiceWatchdog() {};
@@ -75,8 +84,8 @@
// Lock for mEnabled
mEnabledLock.lock();
- sp<CameraServiceWatchdog> tempWatchdog =
- new CameraServiceWatchdog(cycles, cycleLength, mEnabled);
+ sp<CameraServiceWatchdog> tempWatchdog = new CameraServiceWatchdog(
+ mCameraId, cycles, cycleLength, mEnabled, mCameraServiceProxyWrapper);
mEnabledLock.unlock();
status_t status = tempWatchdog->run("CameraServiceWatchdog");
@@ -134,11 +143,14 @@
Mutex mWatchdogLock; // Lock for condition variable
Mutex mEnabledLock; // Lock for enabled status
Condition mWatchdogCondition; // Condition variable for stop/start
+ String8 mCameraId; // Camera Id the watchdog belongs to
bool mPause; // True if tid map is empty
uint32_t mMaxCycles; // Max cycles
uint32_t mCycleLengthMs; // Length of time elapsed per cycle
bool mEnabled; // True if watchdog is enabled
+ std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
+
std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
};
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index d20638c..23a70db 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -501,12 +501,13 @@
ALOGV("Camera %d: Disconnecting device", mCameraId);
+ bool hasDeviceError = mDevice->hasDeviceError();
mDevice->disconnect();
CameraService::Client::disconnect();
int32_t closeLatencyMs = ns2ms(systemTime() - startTime);
- mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs);
+ mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs, hasDeviceError);
return res;
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index e59b110..34b3948 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -2100,10 +2100,11 @@
mCompositeStreamMap.clear();
}
+ bool hasDeviceError = mDevice->hasDeviceError();
Camera2ClientBase::detachDevice();
int32_t closeLatencyMs = ns2ms(systemTime() - startTime);
- mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs);
+ mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs, hasDeviceError);
}
/** Device-related methods */
diff --git a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
index 9857fd8..71f52db 100644
--- a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
@@ -26,7 +26,7 @@
#include "common/CameraProviderManager.h"
#include <gui/Surface.h>
-#include <jpegrecoverymap/recoverymap.h>
+#include <jpegrecoverymap/jpegr.h>
#include <utils/ExifUtils.h>
#include <utils/Log.h>
#include "utils/SessionConfigurationUtils.h"
@@ -285,13 +285,13 @@
}
size_t actualJpegRSize = 0;
- recoverymap::jpegr_uncompressed_struct p010;
- recoverymap::jpegr_compressed_struct jpegR;
- recoverymap::RecoveryMap recoveryMap;
+ jpegrecoverymap::jpegr_uncompressed_struct p010;
+ jpegrecoverymap::jpegr_compressed_struct jpegR;
+ jpegrecoverymap::JpegR jpegREncoder;
p010.height = inputFrame.p010Buffer.height;
p010.width = inputFrame.p010Buffer.width;
- p010.colorGamut = recoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ p010.colorGamut = jpegrecoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
size_t yChannelSizeInByte = p010.width * p010.height * 2;
size_t uvChannelSizeInByte = p010.width * p010.height;
p010.data = new uint8_t[yChannelSizeInByte + uvChannelSizeInByte];
@@ -304,18 +304,18 @@
jpegR.data = dstBuffer;
jpegR.maxLength = maxJpegRBufferSize;
- recoverymap::jpegr_transfer_function transferFunction;
+ jpegrecoverymap::jpegr_transfer_function transferFunction;
switch (mP010DynamicRange) {
case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
- transferFunction = recoverymap::jpegr_transfer_function::JPEGR_TF_PQ;
+ transferFunction = jpegrecoverymap::jpegr_transfer_function::JPEGR_TF_PQ;
break;
default:
- transferFunction = recoverymap::jpegr_transfer_function::JPEGR_TF_HLG;
+ transferFunction = jpegrecoverymap::jpegr_transfer_function::JPEGR_TF_HLG;
}
if (mSupportInternalJpeg) {
- recoverymap::jpegr_compressed_struct jpeg;
+ jpegrecoverymap::jpegr_compressed_struct jpeg;
jpeg.data = inputFrame.jpegBuffer.data;
jpeg.length = android::camera2::JpegProcessor::findJpegSize(inputFrame.jpegBuffer.data,
@@ -327,12 +327,12 @@
}
if (mOutputColorSpace == ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3) {
- jpeg.colorGamut = recoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_P3;
+ jpeg.colorGamut = jpegrecoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_P3;
} else {
- jpeg.colorGamut = recoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ jpeg.colorGamut = jpegrecoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
}
- res = recoveryMap.encodeJPEGR(&p010, &jpeg, transferFunction, &jpegR);
+ res = jpegREncoder.encodeJPEGR(&p010, &jpeg, transferFunction, &jpegR);
} else {
const uint8_t* exifBuffer = nullptr;
size_t exifBufferSize = 0;
@@ -347,11 +347,11 @@
ALOGE("%s: Unable to generate App1 buffer", __FUNCTION__);
}
- recoverymap::jpegr_exif_struct exif;
+ jpegrecoverymap::jpegr_exif_struct exif;
exif.data = reinterpret_cast<void*>(const_cast<uint8_t*>(exifBuffer));
exif.length = exifBufferSize;
- res = recoveryMap.encodeJPEGR(&p010, transferFunction, &jpegR, jpegQuality, &exif);
+ res = jpegREncoder.encodeJPEGR(&p010, transferFunction, &jpegR, jpegQuality, &exif);
}
if (res != OK) {
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index f06ed1c..0a2819c 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -158,7 +158,8 @@
}
/** Start watchdog thread */
- mCameraServiceWatchdog = new CameraServiceWatchdog();
+ mCameraServiceWatchdog = new CameraServiceWatchdog(TClientBase::mCameraIdStr,
+ mCameraServiceProxyWrapper);
res = mCameraServiceWatchdog->run("Camera2ClientBaseWatchdog");
if (res != OK) {
ALOGE("%s: Unable to start camera service watchdog thread: %s (%d)",
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 065d0d1..6f15653 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -475,6 +475,11 @@
virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
/**
+ * If the device is in eror state
+ */
+ virtual bool hasDeviceError() = 0;
+
+ /**
* Set bitmask for image dump flag
*/
void setImageDumpMask(int mask) { mImageDumpMask = mask; }
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index a70cc19..3b40da9 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1004,19 +1004,21 @@
auto availableDurations = ch.find(tag);
if (availableDurations.count > 0) {
// Duration entry contains 4 elements (format, width, height, duration)
- for (size_t i = 0; i < availableDurations.count; i += 4) {
- for (const auto& size : sizes) {
- int64_t width = std::get<0>(size);
- int64_t height = std::get<1>(size);
+ for (const auto& size : sizes) {
+ int64_t width = std::get<0>(size);
+ int64_t height = std::get<1>(size);
+ for (size_t i = 0; i < availableDurations.count; i += 4) {
if ((availableDurations.data.i64[i] == format) &&
(availableDurations.data.i64[i+1] == width) &&
(availableDurations.data.i64[i+2] == height)) {
durations->push_back(availableDurations.data.i64[i+3]);
+ break;
}
}
}
}
}
+
void CameraProviderManager::ProviderInfo::DeviceInfo3::getSupportedDynamicDepthDurations(
const std::vector<int64_t>& depthDurations, const std::vector<int64_t>& blobDurations,
std::vector<int64_t> *dynamicDepthDurations /*out*/) {
@@ -1137,8 +1139,7 @@
return BAD_VALUE;
}
- std::vector<std::tuple<size_t, size_t>> supportedP010Sizes, supportedBlobSizes,
- supportedDynamicDepthSizes, internalDepthSizes;
+ std::vector<std::tuple<size_t, size_t>> supportedP010Sizes, supportedBlobSizes;
auto capabilities = c.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
if (capabilities.count == 0) {
ALOGE("%s: Supported camera capabilities is empty!", __FUNCTION__);
@@ -1191,9 +1192,11 @@
getSupportedDurations(c, scalerStallDurationsTag, HAL_PIXEL_FORMAT_BLOB,
supportedP010Sizes, &blobStallDurations);
if (blobStallDurations.empty() || blobMinDurations.empty() ||
- (blobMinDurations.size() != blobStallDurations.size())) {
- ALOGE("%s: Unexpected number of available blob durations! %zu vs. %zu",
- __FUNCTION__, blobMinDurations.size(), blobStallDurations.size());
+ supportedP010Sizes.size() != blobMinDurations.size() ||
+ blobMinDurations.size() != blobStallDurations.size()) {
+ ALOGE("%s: Unexpected number of available blob durations! %zu vs. %zu with "
+ "supportedP010Sizes size: %zu", __FUNCTION__, blobMinDurations.size(),
+ blobStallDurations.size(), supportedP010Sizes.size());
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4047c13..427d972 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -52,15 +52,16 @@
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
-#include "utils/CameraTraces.h"
-#include "mediautils/SchedulingPolicyService.h"
-#include "device3/Camera3Device.h"
-#include "device3/Camera3OutputStream.h"
-#include "device3/Camera3InputStream.h"
-#include "device3/Camera3FakeStream.h"
-#include "device3/Camera3SharedOutputStream.h"
#include "CameraService.h"
+#include "aidl/AidlUtils.h"
+#include "device3/Camera3Device.h"
+#include "device3/Camera3FakeStream.h"
+#include "device3/Camera3InputStream.h"
+#include "device3/Camera3OutputStream.h"
+#include "device3/Camera3SharedOutputStream.h"
+#include "mediautils/SchedulingPolicyService.h"
#include "utils/CameraThreadState.h"
+#include "utils/CameraTraces.h"
#include "utils/SessionConfigurationUtils.h"
#include "utils/TraceHFR.h"
@@ -230,7 +231,7 @@
mInjectionMethods = createCamera3DeviceInjectionMethods(this);
/** Start watchdog thread */
- mCameraServiceWatchdog = new CameraServiceWatchdog();
+ mCameraServiceWatchdog = new CameraServiceWatchdog(mId, mCameraServiceProxyWrapper);
res = mCameraServiceWatchdog->run("CameraServiceWatchdog");
if (res != OK) {
SET_ERR_L("Unable to start camera service watchdog thread: %s (%d)",
@@ -2946,6 +2947,7 @@
mSupportCameraMute(supportCameraMute),
mOverrideToPortrait(overrideToPortrait) {
mStatusId = statusTracker->addComponent("RequestThread");
+ mVndkVersion = property_get_int32("ro.vndk.version", __ANDROID_API_FUTURE__);
}
Camera3Device::RequestThread::~RequestThread() {}
@@ -3740,6 +3742,17 @@
}
captureRequest->mRotationAndCropUpdated = true;
}
+
+ for (it = captureRequest->mSettingsList.begin();
+ it != captureRequest->mSettingsList.end(); it++) {
+ res = hardware::cameraservice::utils::conversion::aidl::filterVndkKeys(
+ mVndkVersion, it->metadata, false /*isStatic*/);
+ if (res != OK) {
+ SET_ERR("RequestThread: Failed during VNDK filter of capture requests "
+ "%d: %s (%d)", halRequest->frame_number, strerror(-res), res);
+ return INVALID_OPERATION;
+ }
+ }
}
}
@@ -4178,6 +4191,12 @@
mStreamUseCaseOverrides.clear();
}
+bool Camera3Device::hasDeviceError() {
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+ return mStatus == STATUS_ERROR;
+}
+
void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
if (mNextRequests.empty()) {
return;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 21cf6fc..3a46ee6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -313,6 +313,9 @@
// Get the status trackeer for the camera device
wp<camera3::StatusTracker> getStatusTracker() { return mStatusTracker; }
+ // Whether the device is in error state
+ bool hasDeviceError();
+
/**
* The injection camera session to replace the internal camera
* session.
@@ -1057,7 +1060,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
@@ -1131,6 +1134,7 @@
const bool mUseHalBufManager;
const bool mSupportCameraMute;
const bool mOverrideToPortrait;
+ int32_t mVndkVersion = -1;
};
virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> /*parent*/,
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 205a899..15bd5ba 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -84,9 +84,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/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index bed576f..7aaf6b2 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -46,11 +46,13 @@
}
void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onClose(
- sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs) {
+ sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs,
+ bool deviceError) {
Mutex::Autolock l(mLock);
mSessionStats.mNewCameraState = CameraSessionStats::CAMERA_STATE_CLOSED;
mSessionStats.mLatencyMs = latencyMs;
+ mSessionStats.mDeviceError = deviceError;
updateProxyDeviceState(proxyBinder);
}
@@ -259,7 +261,7 @@
sessionStats->onOpen(proxyBinder);
}
-void CameraServiceProxyWrapper::logClose(const String8& id, int32_t latencyMs) {
+void CameraServiceProxyWrapper::logClose(const String8& id, int32_t latencyMs, bool deviceError) {
std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
{
Mutex::Autolock l(mLock);
@@ -275,13 +277,15 @@
__FUNCTION__, id.c_str());
return;
}
+
mSessionStatsMap.erase(id);
- ALOGV("%s: Erasing id %s", __FUNCTION__, id.c_str());
+ ALOGV("%s: Erasing id %s, deviceError %d", __FUNCTION__, id.c_str(), deviceError);
}
- ALOGV("%s: id %s, latencyMs %d", __FUNCTION__, id.c_str(), latencyMs);
+ ALOGV("%s: id %s, latencyMs %d, deviceError %d", __FUNCTION__,
+ id.c_str(), latencyMs, deviceError);
sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
- sessionStats->onClose(proxyBinder, latencyMs);
+ sessionStats->onClose(proxyBinder, latencyMs, deviceError);
}
bool CameraServiceProxyWrapper::isCameraDisabled(int userId) {
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index 0f77fc9..f90a841 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -54,7 +54,8 @@
{ }
void onOpen(sp<hardware::ICameraServiceProxy>& proxyBinder);
- void onClose(sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs);
+ void onClose(sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs,
+ bool deviceError);
void onStreamConfigured(int operatingMode, bool internalReconfig, int32_t latencyMs);
void onActive(sp<hardware::ICameraServiceProxy>& proxyBinder, float maxPreviewFps);
void onIdle(sp<hardware::ICameraServiceProxy>& proxyBinder,
@@ -83,7 +84,7 @@
int32_t latencyMs);
// Close
- void logClose(const String8& id, int32_t latencyMs);
+ void logClose(const String8& id, int32_t latencyMs, bool deviceError);
// Stream configuration
void logStreamConfigured(const String8& id, int operatingMode, bool internalReconfig,
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index adf0a5e..5697acd 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -344,7 +344,8 @@
std::shared_ptr<ResourceManagerService> service =
::ndk::SharedRefBase::make<ResourceManagerService>();
binder_status_t status =
- AServiceManager_addService(service->asBinder().get(), getServiceName());
+ AServiceManager_addServiceWithAllowIsolated(
+ service->asBinder().get(), getServiceName(), /*allowIsolated=*/ true);
if (status != STATUS_OK) {
return;
}
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index 4e97406..b64afdc 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -100,8 +100,10 @@
std::shared_ptr<ResourceObserverService> ResourceObserverService::instantiate() {
std::shared_ptr<ResourceObserverService> observerService =
::ndk::SharedRefBase::make<ResourceObserverService>();
- binder_status_t status = AServiceManager_addService(observerService->asBinder().get(),
- ResourceObserverService::getServiceName());
+ binder_status_t status = AServiceManager_addServiceWithAllowIsolated(
+ observerService->asBinder().get(),ResourceObserverService::getServiceName(),
+ /*allowIsolated=*/ true);
+
if (status != STATUS_OK) {
return nullptr;
}