Merge "Set the container field of aconfig flags" into main
diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h
index 0ee8779..e26290f 100644
--- a/include/media/Interpolator.h
+++ b/include/media/Interpolator.h
@@ -204,7 +204,7 @@
mInterpolatorType = interpolatorType;
return NO_ERROR;
default:
- ALOGE("invalid interpolatorType: %d", interpolatorType);
+ ALOGE("invalid interpolatorType: %d", static_cast<int>(interpolatorType));
return BAD_VALUE;
}
}
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index 2328ae2..39a1544 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -128,6 +128,12 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+cc_aconfig_library {
+ name: "android.media.audiopolicy-aconfig-cc",
+ aconfig_declarations: "android.media.audiopolicy-aconfig",
+ defaults: ["audio-aconfig-cc-defaults"],
+}
+
filegroup {
name: "audio-framework-aconfig",
srcs: [
diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig
index 9df79cd..4d0df77 100644
--- a/media/audio/aconfig/audio.aconfig
+++ b/media/audio/aconfig/audio.aconfig
@@ -58,3 +58,10 @@
description: "Enable stereo channel mask for spatialization."
bug: "303920722"
}
+
+flag {
+ name: "volume_refactoring"
+ namespace: "media_audio"
+ description: "Refactor the audio volume internal architecture logic"
+ bug: "324152869"
+}
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index c64deeb..525dceb 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -22,6 +22,13 @@
}
flag {
+ name: "feature_spatial_audio_headtracking_low_latency"
+ namespace: "media_audio"
+ description: "Define feature for low latency headtracking for SA"
+ bug: "324291076"
+}
+
+flag {
name: "focus_exclusive_with_recording"
namespace: "media_audio"
description:
@@ -60,6 +67,7 @@
Enable the API for providing loudness metadata and CTA-2075 \
support."
bug: "298463873"
+ is_exported: true
}
flag {
@@ -77,3 +85,10 @@
description: "Surface new API method AudioManager.getSupportedDeviceTypes()"
bug: "307537538"
}
+
+flag {
+ name: "volume_ringer_api_hardening"
+ namespace: "media_audio"
+ description: "Limit access to volume and ringer SDK APIs in AudioManager"
+ bug: "296232417"
+}
diff --git a/media/audio/aconfig/audiopolicy_framework.aconfig b/media/audio/aconfig/audiopolicy_framework.aconfig
index f54e5fe..72a1e6c 100644
--- a/media/audio/aconfig/audiopolicy_framework.aconfig
+++ b/media/audio/aconfig/audiopolicy_framework.aconfig
@@ -7,6 +7,30 @@
container: "system"
flag {
+ name: "audio_mix_ownership"
+ namespace: "media_audio"
+ description: "Improves ownership model of AudioMixes and the relationship between AudioPolicy and AudioMix."
+ bug: "309080867"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "audio_mix_policy_ordering"
+ namespace: "media_audio"
+ description: "Orders AudioMixes per registered AudioPolicy."
+ bug: "309080867"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "audio_mix_test_api"
+ namespace: "media_audio"
+ description: "Enable new Test APIs that provide access to registered AudioMixes on system server and native side."
+ bug: "309080867"
+ is_fixed_read_only: true
+}
+
+flag {
name: "audio_policy_update_mixing_rules_api"
namespace: "media_audio"
description: "Enable AudioPolicy.updateMixingRules API for hot-swapping audio mixing rules."
@@ -26,3 +50,11 @@
description: "Enable multi-zone audio support in audio product strategies."
bug: "316643994"
}
+
+flag {
+ name: "record_audio_device_aware_permission"
+ namespace: "media_audio"
+ description: "Enable device-aware permission handling for RECORD_AUDIO permission"
+ bug: "291737188"
+ is_fixed_read_only: true
+}
\ No newline at end of file
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 1a6c7f1..77418eb 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -904,7 +904,7 @@
case Tag::voiceMask:
return convert(aidl, mVoice, __func__, "voice");
}
- ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
+ ALOGE("%s: unexpected tag value %d", __func__, static_cast<int>(aidl.getTag()));
return unexpected(BAD_VALUE);
}
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index e938f96..387d2b8 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -427,7 +427,9 @@
inline bool operator==(const C2Param &o) const {
return equals(o) && memcmp(this, &o, _mSize) == 0;
}
+#if __cplusplus < 202002
inline bool operator!=(const C2Param &o) const { return !operator==(o); }
+#endif
/// safe(r) type cast from pointer and size
inline static C2Param* From(void *addr, size_t len) {
diff --git a/media/codec2/core/include/C2ParamDef.h b/media/codec2/core/include/C2ParamDef.h
index 86dfe65..1805464 100644
--- a/media/codec2/core/include/C2ParamDef.h
+++ b/media/codec2/core/include/C2ParamDef.h
@@ -212,6 +212,26 @@
}
};
+/// Define equality (and inequality) operators for params.
+#if __cplusplus < 202002
+
+#define DEFINE_EQUALITY_OPERATORS(_Type, T) \
+ inline bool operator==(const _Type &o) const { \
+ return this->T::operator==(o); \
+ } \
+ inline bool operator!=(const _Type &o) const { \
+ return !operator==(o); \
+ }
+
+#else
+
+#define DEFINE_EQUALITY_OPERATORS(_Type, T) \
+ inline bool operator==(const _Type &o) const { \
+ return this->T::operator==(o); \
+ }
+
+#endif
+
/// Define From() cast operators for params.
#define DEFINE_CAST_OPERATORS(_Type) \
inline static _Type* From(C2Param *other) { \
@@ -404,12 +424,12 @@
/// Specialization for an input port parameter.
struct input : public T, public S,
public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_INPUT> {
- using T::operator!=;
_C2_CORE_INDEX_OVERRIDE(ParamIndex)
/// Wrapper around base structure's constructor.
template<typename ...Args>
inline input(const Args(&... args)) : T(sizeof(_Type), input::PARAM_TYPE), S(args...) { }
+ DEFINE_EQUALITY_OPERATORS(input, T)
DEFINE_CAST_OPERATORS(input)
};
@@ -417,12 +437,12 @@
/// Specialization for an output port parameter.
struct output : public T, public S,
public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_OUTPUT> {
- using T::operator!=;
_C2_CORE_INDEX_OVERRIDE(ParamIndex)
/// Wrapper around base structure's constructor.
template<typename ...Args>
inline output(const Args(&... args)) : T(sizeof(_Type), output::PARAM_TYPE), S(args...) { }
+ DEFINE_EQUALITY_OPERATORS(output, T)
DEFINE_CAST_OPERATORS(output)
};
};
@@ -472,7 +492,6 @@
/// Specialization for an input port parameter.
struct input : public T,
public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_INPUT> {
- using T::operator!=;
private:
/// Wrapper around base structure's constructor while also specifying port/direction.
template<typename ...Args>
@@ -482,6 +501,7 @@
public:
S m; ///< wrapped flexible structure
+ DEFINE_EQUALITY_OPERATORS(input, T)
DEFINE_FLEXIBLE_METHODS(input, S)
DEFINE_CAST_OPERATORS(input)
};
@@ -489,7 +509,6 @@
/// Specialization for an output port parameter.
struct output : public T,
public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_OUTPUT> {
- using T::operator!=;
private:
/// Wrapper around base structure's constructor while also specifying port/direction.
template<typename ...Args>
@@ -499,6 +518,7 @@
public:
S m; ///< wrapped flexible structure
+ DEFINE_EQUALITY_OPERATORS(output, T)
DEFINE_FLEXIBLE_METHODS(output, S)
DEFINE_CAST_OPERATORS(output)
};
@@ -553,7 +573,6 @@
struct input : public T, public S,
public _C2StructCheck<S, ParamIndex,
T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_INPUT> {
- using T::operator!=;
_C2_CORE_INDEX_OVERRIDE(ParamIndex)
/// Default constructor. Stream-ID is undefined.
@@ -565,6 +584,7 @@
/// Set stream-id. \retval true if the stream-id was successfully set.
inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+ DEFINE_EQUALITY_OPERATORS(input, T)
DEFINE_CAST_OPERATORS(input)
};
@@ -572,7 +592,6 @@
struct output : public T, public S,
public _C2StructCheck<S, ParamIndex,
T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_OUTPUT> {
- using T::operator!=;
_C2_CORE_INDEX_OVERRIDE(ParamIndex)
/// Default constructor. Stream-ID is undefined.
@@ -584,6 +603,7 @@
/// Set stream-id. \retval true if the stream-id was successfully set.
inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+ DEFINE_EQUALITY_OPERATORS(output, T)
DEFINE_CAST_OPERATORS(output)
};
};
@@ -640,7 +660,6 @@
struct input : public T,
public _C2FlexStructCheck<S, ParamIndex,
T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_INPUT> {
- using T::operator!=;
private:
/// Default constructor. Stream-ID is undefined.
inline input(size_t flexCount) : T(_Type::CalcSize(flexCount), input::PARAM_TYPE) { }
@@ -655,6 +674,7 @@
/// Set stream-id. \retval true if the stream-id was successfully set.
inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+ DEFINE_EQUALITY_OPERATORS(input, T)
DEFINE_FLEXIBLE_METHODS(input, S)
DEFINE_CAST_OPERATORS(input)
};
@@ -663,7 +683,6 @@
struct output : public T,
public _C2FlexStructCheck<S, ParamIndex,
T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_OUTPUT> {
- using T::operator!=;
private:
/// Default constructor. Stream-ID is undefined.
inline output(size_t flexCount) : T(_Type::CalcSize(flexCount), output::PARAM_TYPE) { }
@@ -678,6 +697,7 @@
/// Set stream-id. \retval true if the stream-id was successfully set.
inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+ DEFINE_EQUALITY_OPERATORS(output, T)
DEFINE_FLEXIBLE_METHODS(output, S)
DEFINE_CAST_OPERATORS(output)
};
diff --git a/media/codec2/hal/common/HalSelection.cpp b/media/codec2/hal/common/HalSelection.cpp
index 761a409..d3ea181 100644
--- a/media/codec2/hal/common/HalSelection.cpp
+++ b/media/codec2/hal/common/HalSelection.cpp
@@ -28,7 +28,12 @@
namespace android {
bool IsCodec2AidlHalSelected() {
- if (!com::android::media::codec::flags::provider_->aidl_hal()) {
+ // For new devices with vendor software targeting 202404, we always want to
+ // use AIDL if it exists
+ constexpr int kAndroidApi202404 = 202404;
+ int vendorVersion = ::android::base::GetIntProperty("ro.vendor.api_level", -1);
+ if (!com::android::media::codec::flags::provider_->aidl_hal() &&
+ vendorVersion < kAndroidApi202404) {
// Cannot select AIDL if not enabled
return false;
}
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 5c1755e..4f466c5 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -1049,11 +1049,8 @@
// Unwrap raw buffer handle from the C2Handle
native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
if (!nh) {
- nh = UnwrapNativeCodec2AhwbHandle(handle);
- if (!nh) {
- ALOGE("handle is not compatible to neither C2HandleGralloc nor C2HandleAhwb");
- return;
- }
+ ALOGE("handle is not compatible to any gralloc C2Handle types");
+ return;
}
// Import the raw handle so IMapper can use the buffer. The imported
// handle must be freed when the client is done with the buffer.
diff --git a/media/codec2/tests/C2ComponentInterface_test.cpp b/media/codec2/tests/C2ComponentInterface_test.cpp
index 67f733d..d1844b0 100644
--- a/media/codec2/tests/C2ComponentInterface_test.cpp
+++ b/media/codec2/tests/C2ComponentInterface_test.cpp
@@ -235,7 +235,7 @@
// |*heapParams[0]| is a parameter value. The size of |heapParams| has to be one.
ASSERT_EQ(1u, heapParams.size());
EXPECT_TRUE(heapParams[0]);
- EXPECT_EQ(*heapParams[0], expected);
+ EXPECT_EQ(*heapParams[0], (C2Param &)(expected));
}
template <typename T> void C2CompIntfTest::querySupportedParam() {
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 60b5b29..71ffefb 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -318,6 +318,14 @@
return reinterpret_cast<C2HandleAhwb *>(res);
}
+ static uint32_t getPixelFormat(const C2Handle *const handle) {
+ if (handle == nullptr) {
+ return 0;
+ }
+ const ExtraData *xd = GetExtraData(handle);
+ return xd->format;
+ }
+
static C2HandleAhwb* WrapNativeHandle(
const native_handle_t *const handle,
uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
@@ -899,7 +907,17 @@
native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
- return C2HandleGralloc::UnwrapNativeHandle(handle);
+ if (handle == nullptr) {
+ return nullptr;
+ }
+ if (C2AllocatorGralloc::CheckHandle(handle)) {
+ return C2HandleGralloc::UnwrapNativeHandle(handle);
+ }
+ if (C2AllocatorAhwb::CheckHandle(handle)) {
+ return C2HandleAhwb::UnwrapNativeHandle(handle);
+ }
+ ALOGE("tried to unwrap non c2 compatible handle");
+ return nullptr;
}
C2Handle *WrapNativeCodec2GrallocHandle(
@@ -911,7 +929,38 @@
}
uint32_t ExtractFormatFromCodec2GrallocHandle(const C2Handle *const handle) {
- return C2HandleGralloc::getPixelFormat(handle);
+ if (C2AllocatorGralloc::CheckHandle(handle)) {
+ return C2HandleGralloc::getPixelFormat(handle);
+ }
+ if (C2AllocatorAhwb::CheckHandle(handle)) {
+ return C2HandleAhwb::getPixelFormat(handle);
+ }
+ ALOGE("tried to extract pixelformat from non c2 compatible handle");
+ return 0;
+}
+
+bool EXtractMetadataFromCodec2GrallocHandle(
+ const C2Handle *const handle,
+ uint32_t *width, uint32_t *height, uint32_t *format, uint64_t *usage, uint32_t *stride) {
+ if (handle == nullptr) {
+ ALOGE("ExtractMetadata from nullptr");
+ return false;
+ }
+ if (C2AllocatorGralloc::CheckHandle(handle)) {
+ uint32_t generation;
+ uint64_t igbp_id;
+ uint32_t igbp_slot;
+ (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
+ &generation, &igbp_id, &igbp_slot);
+ return true;
+ }
+ if (C2AllocatorAhwb::CheckHandle(handle)) {
+ uint64_t origId;
+ (void)C2HandleAhwb::Import(handle, width, height, format, usage, stride, &origId);
+ return true;
+ }
+ ALOGE("EXtractMetadata from non compatible handle");
+ return false;
}
bool MigrateNativeCodec2GrallocHandle(
@@ -1137,8 +1186,17 @@
const C2Handle *const handle,
uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
- (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
- generation, igbp_id, igbp_slot);
+ if (C2AllocatorGralloc::CheckHandle(handle)) {
+ (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
+ generation, igbp_id, igbp_slot);
+ return;
+ }
+ if (C2AllocatorAhwb::CheckHandle(handle)) {
+ uint64_t origId;
+ (void)C2HandleAhwb::Import(handle, width, height, format, usage, stride, &origId);
+ return;
+ }
+ ALOGE("Tried to extract metadata from non c2 compatible handle");
}
C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
@@ -1250,10 +1308,6 @@
}
-native_handle_t *UnwrapNativeCodec2AhwbHandle(const C2Handle *const handle) {
- return C2HandleAhwb::UnwrapNativeHandle(handle);
-}
-
C2Handle *WrapNativeCodec2AhwbHandle(
const native_handle_t *const handle,
uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
@@ -1477,13 +1531,6 @@
c2_status_t mInit;
};
-void _UnwrapNativeCodec2AhwbMetadata(
- const C2Handle *const handle,
- uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
- uint64_t *origId) {
- (void)C2HandleAhwb::Import(handle, width, height, format, usage, stride, origId);
-}
-
C2AllocatorAhwb::Impl::Impl(id_t id)
: mInit(C2_OK) {
// TODO: get this from allocator
diff --git a/media/codec2/vndk/include/C2AllocatorGralloc.h b/media/codec2/vndk/include/C2AllocatorGralloc.h
index 1a34c30..53b6262 100644
--- a/media/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/codec2/vndk/include/C2AllocatorGralloc.h
@@ -22,8 +22,25 @@
#include <C2Buffer.h>
namespace android {
+// VNDK
+/**
+ * Extract pixel format from the extra data of gralloc handle.
+ *
+ * @return 0 when no valid pixel format exists.
+ */
+uint32_t ExtractFormatFromCodec2GrallocHandle(const C2Handle *const handle);
/**
+ * Extract metadata from the extra data of gralloc handle.
+ *
+ * @return {@code false} if extraction was failed, {@code true} otherwise.
+ */
+bool ExtractMetadataFromCodec2GrallocHandle(
+ const C2Handle *const handle,
+ uint32_t *width, uint32_t *height, uint32_t *format, uint64_t *usage, uint32_t *stride);
+
+// Not for VNDK (system partition and inside vndk only)
+/**
* Unwrap the native handle from a Codec2 handle allocated by C2AllocatorGralloc.
*
* @param handle a handle allocated by C2AllocatorGralloc. This includes handles returned for a
@@ -46,13 +63,6 @@
uint32_t generation = 0, uint64_t igbp_id = 0, uint32_t igbp_slot = 0);
/**
- * Extract pixel format from the extra data of gralloc handle.
- *
- * @return 0 when no valid pixel format exists.
- */
-uint32_t ExtractFormatFromCodec2GrallocHandle(const C2Handle *const handle);
-
-/**
* When the gralloc handle is migrated to another bufferqueue, update
* bufferqueue information.
*
@@ -71,16 +81,6 @@
uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot);
/**
- * Unwrap the native handle from a Codec2 handle allocated by C2AllocatorAhwb.
- *
- * @param handle a handle allocated by C2AllocatorAhwb. This includes handles returned for a
- * graphic block allocation handle based on an AHardwareBuffer.
- *
- * @return a new NON-OWNING native handle that must be deleted using native_handle_delete.
- */
-native_handle_t *UnwrapNativeCodec2AhwbHandle(const C2Handle *const handle);
-
-/**
* Wrap the gralloc handle and metadata based on AHardwareBuffer into Codec2 handle
* recognized by C2AllocatorAhwb.
*
@@ -92,14 +92,6 @@
uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
uint64_t origId);
-/**
- * \todo Get this from the buffer
- */
-void _UnwrapNativeCodec2AhwbMetadata(
- const C2Handle *const handle,
- uint32_t *width, uint32_t *height, uint32_t *format, uint64_t *usage, uint32_t *stride,
- uint64_t *origId);
-
class C2AllocatorGralloc : public C2Allocator {
public:
virtual id_t getId() const override;
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 51a679b..369e917 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -67,6 +67,7 @@
"libaudioclient_aidl_conversion",
"libaudioutils",
"libbinder",
+ "libbinder_ndk",
"libcutils",
"liblog",
"libutils",
@@ -121,6 +122,7 @@
"latest_android_media_audio_common_types_cpp_shared",
],
shared_libs: [
+ "android.media.audiopolicy-aconfig-cc",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 5bfdd5f..348e25f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -22,6 +22,7 @@
#include <android/media/IAudioPolicyService.h>
#include <android/media/AudioMixUpdate.h>
#include <android/media/BnCaptureStateListener.h>
+#include <android_media_audiopolicy.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
@@ -44,6 +45,8 @@
// ----------------------------------------------------------------------------
+namespace audio_flags = android::media::audiopolicy;
+
namespace android {
using aidl_utils::statusTFromBinderStatus;
using binder::Status;
@@ -1843,6 +1846,25 @@
return statusTFromBinderStatus(aps->registerPolicyMixes(mixesAidl, registration));
}
+status_t AudioSystem::getRegisteredPolicyMixes(std::vector<AudioMix>& mixes) {
+ if (!audio_flags::audio_mix_test_api()) {
+ return INVALID_OPERATION;
+ }
+
+ const sp<IAudioPolicyService> aps = AudioSystem::get_audio_policy_service();
+ if (aps == nullptr) return PERMISSION_DENIED;
+
+ std::vector<::android::media::AudioMix> aidlMixes;
+ Status status = aps->getRegisteredPolicyMixes(&aidlMixes);
+
+ for (const auto& aidlMix : aidlMixes) {
+ AudioMix mix = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioMix(aidlMix));
+ mixes.push_back(mix);
+ }
+
+ return statusTFromBinderStatus(status);
+}
+
status_t AudioSystem::updatePolicyMixes(
const std::vector<std::pair<AudioMix, std::vector<AudioMixMatchCriterion>>>&
mixesWithUpdates) {
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 52c8da0..633493c 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -263,6 +263,8 @@
void registerPolicyMixes(in AudioMix[] mixes, boolean registration);
+ List<AudioMix> getRegisteredPolicyMixes();
+
void updatePolicyMixes(in AudioMixUpdate[] updates);
void setUidDeviceAffinities(int /* uid_t */ uid, in AudioDevice[] devices);
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index a1f7941..acbcf3f 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -462,6 +462,8 @@
static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
+ static status_t getRegisteredPolicyMixes(std::vector<AudioMix>& mixes);
+
static status_t updatePolicyMixes(
const std::vector<
std::pair<AudioMix, std::vector<AudioMixMatchCriterion>>>& mixesWithUpdates);
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index ae0457f..6dbf284 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -192,7 +192,8 @@
dst->append(
base::StringPrintf("%*s extra audio descriptor %zu:\n", eadSpaces, "", i));
dst->append(base::StringPrintf(
- "%*s- standard: %u\n", descSpaces, "", mExtraAudioDescriptors[i].standard));
+ "%*s- standard: %u\n", descSpaces, "",
+ static_cast<unsigned>(mExtraAudioDescriptors[i].standard)));
dst->append(base::StringPrintf("%*s- descriptor:", descSpaces, ""));
for (auto v : mExtraAudioDescriptors[i].audioDescriptor) {
dst->append(base::StringPrintf(" %02x", v));
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 3c05b0b..b8d0998 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -23,7 +23,6 @@
],
required: [
- "libaudiohal@4.0",
"libaudiohal@5.0",
"libaudiohal@6.0",
"libaudiohal@7.0",
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
index c414e19..15cb297 100644
--- a/media/libaudiohal/FactoryHal.cpp
+++ b/media/libaudiohal/FactoryHal.cpp
@@ -50,13 +50,12 @@
* This list need to keep sync with AudioHalVersionInfo.VERSIONS in
* media/java/android/media/AudioHalVersionInfo.java.
*/
-static const std::array<AudioHalVersionInfo, 6> sAudioHALVersions = {
+static const std::array<AudioHalVersionInfo, 5> sAudioHALVersions = {
AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
- AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 4, 0),
};
static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index a4c2d50..4d81f77 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -41,7 +41,7 @@
],
header_libs: [
"android.hardware.audio.common.util@all-versions",
- ]
+ ],
}
cc_defaults {
@@ -71,7 +71,7 @@
],
header_libs: [
"libaudioclient_headers",
- "libaudiohal_headers"
+ "libaudiohal_headers",
],
defaults: [
"latest_android_media_audio_common_types_cpp_export_shared",
@@ -83,36 +83,10 @@
}
cc_library_shared {
- name: "libaudiohal@4.0",
- defaults: [
- "libaudiohal_default",
- "libaudiohal_hidl_default"
- ],
- srcs: [
- ":audio_core_hal_client_sources",
- ":audio_effect_hidl_hal_client_sources",
- "EffectsFactoryHalEntry.cpp",
- ],
- shared_libs: [
- "android.hardware.audio.common@4.0",
- "android.hardware.audio.common@4.0-util",
- "android.hardware.audio.effect@4.0",
- "android.hardware.audio.effect@4.0-util",
- "android.hardware.audio@4.0",
- "android.hardware.audio@4.0-util",
- ],
- cflags: [
- "-DMAJOR_VERSION=4",
- "-DMINOR_VERSION=0",
- "-include common/all-versions/VersionMacro.h",
- ]
-}
-
-cc_library_shared {
name: "libaudiohal@5.0",
defaults: [
"libaudiohal_default",
- "libaudiohal_hidl_default"
+ "libaudiohal_hidl_default",
],
srcs: [
":audio_core_hal_client_sources",
@@ -131,14 +105,14 @@
"-DMAJOR_VERSION=5",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
name: "libaudiohal@6.0",
defaults: [
"libaudiohal_default",
- "libaudiohal_hidl_default"
+ "libaudiohal_hidl_default",
],
srcs: [
":audio_core_hal_client_sources",
@@ -157,14 +131,14 @@
"-DMAJOR_VERSION=6",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_static {
name: "libaudiohal.effect@7.0",
defaults: [
"libaudiohal_default",
- "libaudiohal_hidl_default"
+ "libaudiohal_hidl_default",
],
srcs: [
":audio_effect_hidl_hal_client_sources",
@@ -179,14 +153,14 @@
"-DMAJOR_VERSION=7",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
name: "libaudiohal@7.0",
defaults: [
"libaudiohal_default",
- "libaudiohal_hidl_default"
+ "libaudiohal_hidl_default",
],
srcs: [
":audio_core_hal_client_sources",
@@ -206,7 +180,7 @@
"-DMAJOR_VERSION=7",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -215,7 +189,7 @@
"latest_android_hardware_audio_core_sounddose_ndk_shared",
"latest_android_hardware_audio_sounddose_ndk_shared",
"libaudiohal_default",
- "libaudiohal_hidl_default"
+ "libaudiohal_hidl_default",
],
srcs: [
":audio_core_hal_client_sources",
@@ -242,7 +216,7 @@
"-DCOMMON_TYPES_MINOR_VERSION=0",
"-DCORE_TYPES_MINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_defaults {
@@ -287,9 +261,30 @@
],
srcs: [
"DevicesFactoryHalEntry.cpp",
+ "EffectsFactoryHalEntry.cpp",
+ ":audio_effect_hal_aidl_src_files",
+ ":core_audio_hal_aidl_src_files",
+ ],
+}
+
+filegroup {
+ name: "core_audio_hal_aidl_src_files",
+ srcs: [
+ "ConversionHelperAidl.cpp",
+ "DeviceHalAidl.cpp",
+ "DevicesFactoryHalAidl.cpp",
+ "Hal2AidlMapper.cpp",
+ "StreamHalAidl.cpp",
+ ],
+}
+
+filegroup {
+ name: "audio_effect_hal_aidl_src_files",
+ srcs: [
"EffectConversionHelperAidl.cpp",
"EffectBufferHalAidl.cpp",
"EffectHalAidl.cpp",
+ "EffectsFactoryHalAidl.cpp",
"effectsAidlConversion/AidlConversionAec.cpp",
"effectsAidlConversion/AidlConversionAgc1.cpp",
"effectsAidlConversion/AidlConversionAgc2.cpp",
@@ -306,21 +301,7 @@
"effectsAidlConversion/AidlConversionVendorExtension.cpp",
"effectsAidlConversion/AidlConversionVirtualizer.cpp",
"effectsAidlConversion/AidlConversionVisualizer.cpp",
- "EffectsFactoryHalAidl.cpp",
- "EffectsFactoryHalEntry.cpp",
":audio_effectproxy_src_files",
- ":core_audio_hal_aidl_src_files",
- ],
-}
-
-filegroup {
- name: "core_audio_hal_aidl_src_files",
- srcs: [
- "ConversionHelperAidl.cpp",
- "DeviceHalAidl.cpp",
- "DevicesFactoryHalAidl.cpp",
- "Hal2AidlMapper.cpp",
- "StreamHalAidl.cpp",
],
}
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp
index 46abfda..7a32811 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperAidl.cpp
@@ -37,10 +37,6 @@
using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
if (parameterKeys.size() == 0) return OK;
const String8 rawKeys = parameterKeys.keysToString();
- if (vendorExt == nullptr) {
- ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str());
- return OK;
- }
std::vector<std::string> parameterIds;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
@@ -85,10 +81,6 @@
using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
if (parameters.size() == 0) return OK;
const String8 rawKeysAndValues = parameters.toString();
- if (vendorExt == nullptr) {
- ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str());
- return OK;
- }
std::vector<VendorParameter> syncParameters, asyncParameters;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index db9a9b1..a601ad5 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -1052,15 +1052,11 @@
(void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
parameters, String8(AudioParameter::keyReconfigA2dp),
[&](const String8& value) -> status_t {
- if (mVendorExt != nullptr) {
- std::vector<VendorParameter> result;
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mVendorExt->parseBluetoothA2dpReconfigureOffload(
- std::string(value.c_str()), &result)));
- reconfigureOffload = std::move(result);
- } else {
- reconfigureOffload = std::vector<VendorParameter>();
- }
+ std::vector<VendorParameter> result;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mVendorExt->parseBluetoothA2dpReconfigureOffload(
+ std::string(value.c_str()), &result)));
+ reconfigureOffload = std::move(result);
return OK;
}));
if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 3dbc14a..01fc7fb 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -17,12 +17,14 @@
#include <algorithm>
#include <map>
#include <memory>
+#include <mutex>
#include <string>
#define LOG_TAG "DevicesFactoryHalAidl"
//#define LOG_NDEBUG 0
#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
#include <android/binder_manager.h>
#include <media/AidlConversionNdkCpp.h>
#include <media/AidlConversionUtil.h>
@@ -35,6 +37,7 @@
using aidl::android::hardware::audio::core::IConfig;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::SurroundSoundConfig;
+using aidl::android::hardware::audio::core::VendorParameter;
using aidl::android::media::audio::common::AudioHalEngineConfig;
using aidl::android::media::audio::IHalAdapterVendorExtension;
using android::detail::AudioHalVersionInfo;
@@ -62,10 +65,84 @@
return cpp;
}
+class HalAdapterVendorExtensionWrapper :
+ public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
+ private:
+ template<typename F>
+ ndk::ScopedAStatus callWithRetryOnCrash(F method) {
+ ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
+ for (auto service = getService(); service != nullptr; service = getService(true)) {
+ status = method(service);
+ if (status.getStatus() != STATUS_DEAD_OBJECT) break;
+ }
+ return status;
+ }
+
+ ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope,
+ const std::string& in_rawKeys,
+ std::vector<std::string>* _aidl_return) override {
+ return callWithRetryOnCrash([&](auto service) {
+ return service->parseVendorParameterIds(in_scope, in_rawKeys, _aidl_return);
+ });
+ }
+
+ ndk::ScopedAStatus parseVendorParameters(
+ ParameterScope in_scope, const std::string& in_rawKeysAndValues,
+ std::vector<VendorParameter>* out_syncParameters,
+ std::vector<VendorParameter>* out_asyncParameters) override {
+ return callWithRetryOnCrash([&](auto service) {
+ return service->parseVendorParameters(in_scope, in_rawKeysAndValues,
+ out_syncParameters, out_asyncParameters);
+ });
+ }
+
+ ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
+ const std::string& in_rawValue, std::vector<VendorParameter>* _aidl_return) override {
+ return callWithRetryOnCrash([&](auto service) {
+ return service->parseBluetoothA2dpReconfigureOffload(in_rawValue, _aidl_return);
+ });
+ }
+
+ ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string& in_rawValue,
+ std::vector<VendorParameter>* _aidl_return) override {
+ return callWithRetryOnCrash([&](auto service) {
+ return service->parseBluetoothLeReconfigureOffload(in_rawValue, _aidl_return);
+ });
+ }
+
+ ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
+ const std::vector<VendorParameter>& in_parameters,
+ std::string* _aidl_return) override {
+ return callWithRetryOnCrash([&](auto service) {
+ return service->processVendorParameters(in_scope, in_parameters, _aidl_return);
+ });
+ }
+
+ std::shared_ptr<IHalAdapterVendorExtension> getService(bool reset = false) {
+ std::lock_guard l(mLock);
+ if (reset || !mVendorExt.has_value()) {
+ auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
+ if (AServiceManager_isDeclared(serviceName.c_str())) {
+ mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
+ IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService(serviceName.c_str()))));
+ } else {
+ mVendorExt = nullptr;
+ }
+ }
+ return mVendorExt.value();
+ }
+
+ std::mutex mLock;
+ std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
+ mVendorExt GUARDED_BY(mLock);
+};
+
} // namespace
DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> config)
- : mConfig(std::move(config)) {
+ : mConfig(std::move(config)),
+ mVendorExt(ndk::SharedRefBase::make<HalAdapterVendorExtensionWrapper>()) {
}
status_t DevicesFactoryHalAidl::getDeviceNames(std::vector<std::string> *names) {
@@ -110,7 +187,7 @@
ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
return NO_INIT;
}
- *device = sp<DeviceHalAidl>::make(name, service, getVendorExtension());
+ *device = sp<DeviceHalAidl>::make(name, service, mVendorExt);
return OK;
}
@@ -149,20 +226,6 @@
return OK;
}
-std::shared_ptr<IHalAdapterVendorExtension> DevicesFactoryHalAidl::getVendorExtension() {
- if (!mVendorExt.has_value()) {
- auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
- if (AServiceManager_isDeclared(serviceName.c_str())) {
- mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
- IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
- AServiceManager_waitForService(serviceName.c_str()))));
- } else {
- mVendorExt = nullptr;
- }
- }
- return mVendorExt.value();
-}
-
// Main entry-point to the shared library.
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
auto serviceName = std::string(IConfig::descriptor) + "/default";
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
index 17bfe43..2a3a9e7 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -45,10 +45,7 @@
private:
const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
- std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
- mVendorExt;
-
- std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> getVendorExtension();
+ const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
~DevicesFactoryHalAidl() = default;
};
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 2836727..ebda86a 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -57,20 +57,22 @@
using ::aidl::android::hardware::audio::effect::IEffect;
using ::aidl::android::hardware::audio::effect::IFactory;
using ::aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate;
+using ::aidl::android::hardware::audio::effect::kReopenSupportedVersion;
using ::aidl::android::hardware::audio::effect::State;
namespace android {
namespace effect {
EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
- const std::shared_ptr<IEffect>& effect,
- int32_t sessionId, int32_t ioId, const Descriptor& desc,
- bool isProxyEffect)
+ const std::shared_ptr<IEffect>& effect, int32_t sessionId,
+ int32_t ioId, const Descriptor& desc, bool isProxyEffect)
: mFactory(factory),
mEffect(effect),
mSessionId(sessionId),
mIoId(ioId),
mIsProxyEffect(isProxyEffect) {
+ assert(mFactory != nullptr);
+ assert(mEffect != nullptr);
createAidlConversion(effect, sessionId, ioId, desc);
}
@@ -184,10 +186,18 @@
return INVALID_OPERATION;
}
- if (uint32_t efState = 0;
- ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState, 1 /* ns */,
- true /* retry */)) {
- ALOGI("%s %s receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str());
+ // use IFactory HAL version because IEffect can be an EffectProxy instance
+ static const int halVersion = [&]() {
+ int version = 0;
+ return mFactory->getInterfaceVersion(&version).isOk() ? version : 0;
+ }();
+
+ if (uint32_t efState = 0; halVersion >= kReopenSupportedVersion &&
+ ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
+ 1 /* ns */, true /* retry */) &&
+ efState & kEventFlagDataMqUpdate) {
+ ALOGI("%s %s V%d receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str(),
+ halVersion);
mConversion->reopen();
}
auto statusQ = mConversion->getStatusMQ();
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 2e3a058..fa12cc4 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -64,3 +64,14 @@
],
header_libs: ["libaudiohalimpl_headers"],
}
+
+cc_test {
+ name: "EffectHalVersionCompatibilityTest",
+ srcs: [
+ "EffectHalVersionCompatibility_test.cpp",
+ ":audio_effect_hal_aidl_src_files",
+ ],
+ defaults: ["libaudiohal_aidl_test_default"],
+ header_libs: ["libaudiohalimpl_headers"],
+ static_libs: ["libgmock"],
+}
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
index 1204a3b..3541078 100644
--- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -443,21 +443,6 @@
EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
}
-// Without a vendor extension, any unrecognized parameters must be ignored.
-TEST_F(DeviceHalAidlTest, VendorParameterIgnored) {
- EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
- EXPECT_EQ(0UL, mModule->getSyncParameters().size());
- EXPECT_EQ(OK, mDevice->setParameters(createParameterString("random_name", "random_value")));
- EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
- EXPECT_EQ(0UL, mModule->getSyncParameters().size());
-
- EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
- String8 values;
- EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values));
- EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
- EXPECT_EQ(0UL, values.length());
-}
-
class DeviceHalAidlVendorParametersTest : public testing::Test {
public:
void SetUp() override {
diff --git a/media/libaudiohal/tests/EffectHalVersionCompatibility_test.cpp b/media/libaudiohal/tests/EffectHalVersionCompatibility_test.cpp
new file mode 100644
index 0000000..e8731ea
--- /dev/null
+++ b/media/libaudiohal/tests/EffectHalVersionCompatibility_test.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+#include <unordered_map>
+#define LOG_TAG "EffectHalVersionCompatibilityTest"
+
+#include <EffectHalAidl.h>
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <system/audio_aidl_utils.h>
+#include <system/audio_config.h>
+#include <system/audio_effects/audio_effects_utils.h>
+#include <system/audio_effects/effect_uuid.h>
+#include <utils/Log.h>
+
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::Processing;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+using android::OK;
+using android::sp;
+using android::effect::EffectHalAidl;
+using testing::_;
+using testing::Eq;
+
+namespace {
+
+/**
+ * Maps of parameter and the version it was introduced.
+ */
+// parameters defined directly in the Parameter union, except Parameter::specific (defined in
+// kParamIdEffectVersionMap).
+static const std::unordered_map<Parameter::Tag, int /* version */> kParamTagVersionMap = {
+ {Parameter::common, 1}, {Parameter::deviceDescription, 1},
+ {Parameter::mode, 1}, {Parameter::source, 1},
+ {Parameter::offload, 1}, {Parameter::volumeStereo, 1},
+ {Parameter::sourceMetadata, 2}, {Parameter::sinkMetadata, 2},
+};
+
+// Map of the version a specific effect type introduction
+// Id tags defined Parameter::Id union, except Parameter::Id::commonTag (defined in
+// kParamTagVersionMap).
+static const std::unordered_map<Parameter::Id::Tag, int /* version */> kParamIdEffectVersionMap = {
+ {Parameter::Id::vendorEffectTag, 1},
+ {Parameter::Id::acousticEchoCancelerTag, 1},
+ {Parameter::Id::automaticGainControlV1Tag, 1},
+ {Parameter::Id::automaticGainControlV2Tag, 1},
+ {Parameter::Id::bassBoostTag, 1},
+ {Parameter::Id::downmixTag, 1},
+ {Parameter::Id::dynamicsProcessingTag, 1},
+ {Parameter::Id::environmentalReverbTag, 1},
+ {Parameter::Id::equalizerTag, 1},
+ {Parameter::Id::hapticGeneratorTag, 1},
+ {Parameter::Id::loudnessEnhancerTag, 1},
+ {Parameter::Id::noiseSuppressionTag, 1},
+ {Parameter::Id::presetReverbTag, 1},
+ {Parameter::Id::virtualizerTag, 1},
+ {Parameter::Id::visualizerTag, 1},
+ {Parameter::Id::volumeTag, 1},
+ {Parameter::Id::spatializerTag, 2},
+};
+// Tags defined Parameter::Specific union.
+static const std::unordered_map<Parameter::Specific::Tag, int /* version */>
+ kParamEffectVersionMap = {
+ {Parameter::Specific::vendorEffect, 1},
+ {Parameter::Specific::acousticEchoCanceler, 1},
+ {Parameter::Specific::automaticGainControlV1, 1},
+ {Parameter::Specific::automaticGainControlV2, 1},
+ {Parameter::Specific::bassBoost, 1},
+ {Parameter::Specific::downmix, 1},
+ {Parameter::Specific::dynamicsProcessing, 1},
+ {Parameter::Specific::environmentalReverb, 1},
+ {Parameter::Specific::equalizer, 1},
+ {Parameter::Specific::hapticGenerator, 1},
+ {Parameter::Specific::loudnessEnhancer, 1},
+ {Parameter::Specific::noiseSuppression, 1},
+ {Parameter::Specific::presetReverb, 1},
+ {Parameter::Specific::virtualizer, 1},
+ {Parameter::Specific::visualizer, 1},
+ {Parameter::Specific::volume, 1},
+ {Parameter::Specific::spatializer, 2},
+};
+
+class MockFactory : public IFactory {
+ public:
+ explicit MockFactory(int version) : IFactory(), mVersion(version) {}
+ MOCK_METHOD(ndk::ScopedAStatus, queryEffects,
+ (const std::optional<AudioUuid>& in_type_uuid,
+ const std::optional<AudioUuid>& in_impl_uuid,
+ const std::optional<AudioUuid>& in_proxy_uuid,
+ std::vector<Descriptor>* _aidl_return),
+ (override));
+
+ MOCK_METHOD(ndk::ScopedAStatus, queryProcessing,
+ (const std::optional<Processing::Type>& in_type,
+ std::vector<Processing>* _aidl_return),
+ (override));
+
+ MOCK_METHOD(ndk::ScopedAStatus, createEffect,
+ (const AudioUuid& in_impl_uuid, std::shared_ptr<IEffect>* _aidl_return),
+ (override));
+
+ MOCK_METHOD(ndk::ScopedAStatus, destroyEffect, (const std::shared_ptr<IEffect>& in_handle),
+ (override));
+
+ ndk::ScopedAStatus getInterfaceVersion(int32_t* _aidl_return) {
+ *_aidl_return = mVersion;
+ return ndk::ScopedAStatus::ok();
+ }
+
+ // these must be implemented but won't be used in this testing
+ ::ndk::SpAIBinder asBinder() { return ::ndk::SpAIBinder(); }
+ bool isRemote() { return false; }
+ ::ndk::ScopedAStatus getInterfaceHash(std::string*) { return ndk::ScopedAStatus::ok(); }
+
+ private:
+ const int mVersion;
+};
+
+class MockEffect : public IEffect {
+ public:
+ explicit MockEffect(int version) : IEffect(), mVersion(version) {}
+ MOCK_METHOD(ndk::ScopedAStatus, open,
+ (const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ IEffect::OpenEffectReturn* ret),
+ (override));
+ MOCK_METHOD(ndk::ScopedAStatus, close, (), (override));
+ MOCK_METHOD(binder_status_t, dump, (int fd, const char** args, uint32_t numArgs), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, command, (CommandId id), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getState, (State * state), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getDescriptor, (Descriptor * desc), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, destroy, (), ());
+
+ // reopen introduced in version kReopenSupportedVersion
+ ndk::ScopedAStatus reopen(IEffect::OpenEffectReturn*) override {
+ return mVersion < kReopenSupportedVersion
+ ? ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)
+ : ndk::ScopedAStatus::ok();
+ }
+
+ // for all parameters introduced
+ ndk::ScopedAStatus setParameter(const Parameter& param) override {
+ const auto paramTag = param.getTag();
+ switch (paramTag) {
+ case Parameter::common:
+ case Parameter::deviceDescription:
+ case Parameter::mode:
+ case Parameter::source:
+ case Parameter::offload:
+ case Parameter::volumeStereo:
+ case Parameter::sinkMetadata:
+ FALLTHROUGH_INTENDED;
+ case Parameter::sourceMetadata: {
+ if (kParamTagVersionMap.find(paramTag) != kParamTagVersionMap.end() &&
+ kParamTagVersionMap.at(paramTag) >= mVersion) {
+ return ndk::ScopedAStatus::ok();
+ }
+ break;
+ }
+ case Parameter::specific: {
+ // TODO
+ break;
+ }
+ }
+ return ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+
+ /**
+ * Only care about version compatibility here:
+ * @return BAD_VALUE if a tag is not supported by current AIDL version.
+ * @return OK if a tag is supported by current AIDL version.
+ */
+ ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter*) override {
+ const auto idTag = id.getTag();
+ switch (idTag) {
+ case Parameter::Id::commonTag: {
+ const auto paramTag = id.get<Parameter::Id::commonTag>();
+ if (kParamTagVersionMap.find(paramTag) != kParamTagVersionMap.end() &&
+ kParamTagVersionMap.at(paramTag) >= mVersion) {
+ return ndk::ScopedAStatus::ok();
+ }
+ break;
+ }
+ case Parameter::Id::vendorEffectTag:
+ case Parameter::Id::acousticEchoCancelerTag:
+ case Parameter::Id::automaticGainControlV1Tag:
+ case Parameter::Id::automaticGainControlV2Tag:
+ case Parameter::Id::bassBoostTag:
+ case Parameter::Id::downmixTag:
+ case Parameter::Id::dynamicsProcessingTag:
+ case Parameter::Id::environmentalReverbTag:
+ case Parameter::Id::equalizerTag:
+ case Parameter::Id::hapticGeneratorTag:
+ case Parameter::Id::loudnessEnhancerTag:
+ case Parameter::Id::noiseSuppressionTag:
+ case Parameter::Id::presetReverbTag:
+ case Parameter::Id::virtualizerTag:
+ case Parameter::Id::visualizerTag:
+ case Parameter::Id::volumeTag:
+ FALLTHROUGH_INTENDED;
+ case Parameter::Id::spatializerTag: {
+ if (kParamIdEffectVersionMap.find(idTag) != kParamIdEffectVersionMap.end() &&
+ kParamIdEffectVersionMap.at(idTag) >= mVersion) {
+ return ndk::ScopedAStatus::ok();
+ }
+ break;
+ }
+ }
+ return ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+
+ ndk::ScopedAStatus getInterfaceVersion(int32_t* _aidl_return) {
+ *_aidl_return = mVersion;
+ return ndk::ScopedAStatus::ok();
+ }
+
+ // these must be implemented but won't be used in this testing
+ ::ndk::SpAIBinder asBinder() { return ::ndk::SpAIBinder(); }
+ bool isRemote() { return false; }
+ ::ndk::ScopedAStatus getInterfaceHash(std::string*) { return ndk::ScopedAStatus::ok(); }
+
+ private:
+ const int mVersion;
+};
+
+static const std::vector<AudioUuid> kTestParamUUIDs = {
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidAutomaticGainControlV1(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidAutomaticGainControlV2(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer(),
+ ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer(),
+ ::aidl::android::hardware::audio::effect::getEffectUuidNull(),
+};
+static const std::vector<int> kTestParamVersion = {1, 2}; // Effect AIDL HAL versions to test
+
+enum ParamName { UUID, VERSION };
+using TestParam = std::tuple<AudioUuid, int /* version */>;
+
+class EffectHalVersionCompatibilityTest : public ::testing::TestWithParam<TestParam> {
+ public:
+ void SetUp() override {
+ mMockFactory = ndk::SharedRefBase::make<MockFactory>(mVersion);
+ ASSERT_NE(mMockFactory, nullptr);
+ mMockEffect = ndk::SharedRefBase::make<MockEffect>(mVersion);
+ ASSERT_NE(mMockEffect, nullptr);
+ mEffectHalAidl = sp<EffectHalAidl>::make(mMockFactory, mMockEffect, 0, 0, mDesc, false);
+ ASSERT_NE(mEffectHalAidl, nullptr);
+ }
+
+ void TearDown() override {
+ EXPECT_CALL(*mMockFactory, destroyEffect(_));
+ mEffectHalAidl.clear();
+ mMockEffect.reset();
+ mMockFactory.reset();
+ }
+
+ protected:
+ const int mVersion = std::get<VERSION>(GetParam());
+ const AudioUuid mTypeUuid = std::get<UUID>(GetParam());
+ const Descriptor mDesc = {.common.id.type = mTypeUuid};
+ std::shared_ptr<MockFactory> mMockFactory = nullptr;
+ std::shared_ptr<MockEffect> mMockEffect = nullptr;
+ sp<EffectHalAidl> mEffectHalAidl = nullptr;
+};
+
+TEST_P(EffectHalVersionCompatibilityTest, testEffectAidlHalCreateDestroy) {
+ // do nothing
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EffectHalVersionCompatibilityTestWithVersion, EffectHalVersionCompatibilityTest,
+ ::testing::Combine(testing::ValuesIn(kTestParamUUIDs),
+ testing::ValuesIn(kTestParamVersion)),
+ [](const testing::TestParamInfo<EffectHalVersionCompatibilityTest::ParamType>& info) {
+ auto version = std::to_string(std::get<VERSION>(info.param));
+ auto uuid = android::audio::utils::toString(std::get<UUID>(info.param));
+ std::string name = "EffectHalVersionCompatibilityTest_V" + version + "_" + uuid;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+} // namespace
\ No newline at end of file
diff --git a/media/libaudioprocessing/AudioResamplerSinc.cpp b/media/libaudioprocessing/AudioResamplerSinc.cpp
index f2c386d..1a08a03 100644
--- a/media/libaudioprocessing/AudioResamplerSinc.cpp
+++ b/media/libaudioprocessing/AudioResamplerSinc.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "AudioResamplerSinc"
//#define LOG_NDEBUG 0
-#define __STDC_CONSTANT_MACROS
#include <malloc.h>
#include <pthread.h>
#include <string.h>
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index 1fedea4..7e1549d 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -215,6 +215,10 @@
RETURN_OK_IF(mState != State::INIT);
mImplContext = createContext(common);
RETURN_IF(!mContext || !mImplContext, EX_NULL_POINTER, "createContextFailed");
+ int version = 0;
+ RETURN_IF(!getInterfaceVersion(&version).isOk(), EX_UNSUPPORTED_OPERATION,
+ "FailedToGetInterfaceVersion");
+ mImplContext->setVersion(version);
mEventFlag = mImplContext->getStatusEventFlag();
if (specific.has_value()) {
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
index e89e501..a8892d8 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
@@ -317,7 +317,7 @@
}
int id = *(int *) value;
os::HapticScale hapticIntensity = static_cast<os::HapticScale>(*((int *) value + 1));
- ALOGD("Setting haptic intensity as %d", hapticIntensity);
+ ALOGD("Setting haptic intensity as %d", static_cast<int>(hapticIntensity));
if (hapticIntensity == os::HapticScale::MUTE) {
context->param.id2Intensity.erase(id);
} else {
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
index 4fc9c4a..7d0ccff 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
@@ -161,7 +161,7 @@
std::mutex mMutex;
const lvm::ReverbEffectType mType;
bool mEnabled = false;
- LVREV_Handle_t mInstance GUARDED_BY(mMutex);
+ LVREV_Handle_t mInstance GUARDED_BY(mMutex) = LVM_NULL;
int mRoomLevel = 0;
int mRoomHfLevel = 0;
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
index 0303842..fa651a6 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.cpp
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -61,8 +61,8 @@
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, measurement, Visualizer::Measurement({.rms = 1, .peak = 1}),
+ Visualizer::Measurement({.rms = 0, .peak = 0})),
MAKE_RANGE(Visualizer, captureSampleBuffer, std::vector<uint8_t>({1}),
std::vector<uint8_t>({0}))};
const Capability VisualizerImpl::kCapability = {
diff --git a/media/libnbaio/SourceAudioBufferProvider.cpp b/media/libnbaio/SourceAudioBufferProvider.cpp
index d58619f..157ebd7 100644
--- a/media/libnbaio/SourceAudioBufferProvider.cpp
+++ b/media/libnbaio/SourceAudioBufferProvider.cpp
@@ -32,7 +32,7 @@
// negotiate with source
NBAIO_Format counterOffers[1];
size_t numCounterOffers = 1;
- ssize_t index = source->negotiate(NULL, 0, counterOffers, numCounterOffers);
+ [[maybe_unused]] ssize_t index = source->negotiate(NULL, 0, counterOffers, numCounterOffers);
ALOG_ASSERT(index == (ssize_t) NEGOTIATE && numCounterOffers > 0);
numCounterOffers = 0;
index = source->negotiate(counterOffers, 1, NULL, numCounterOffers);
diff --git a/media/mediaserver/manifest_media_c2_software.xml b/media/mediaserver/manifest_media_c2_software.xml
index d7fb1a0..31dfafb 100644
--- a/media/mediaserver/manifest_media_c2_software.xml
+++ b/media/mediaserver/manifest_media_c2_software.xml
@@ -1,5 +1,5 @@
<manifest version="1.0" type="framework">
- <hal>
+ <hal format="hidl" max-level="8">
<name>android.hardware.media.c2</name>
<transport>hwbinder</transport>
<version>1.2</version>
diff --git a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
index f95fc4d..caf2524 100644
--- a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
+++ b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
@@ -25,6 +25,7 @@
#include <C2Component.h>
#include <C2PlatformSupport.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.1/ComponentStore.h>
#include <codec2/hidl/1.2/ComponentStore.h>
@@ -834,15 +835,26 @@
}
}
- if (!hidlStore) {
- hidlStore = ::android::sp<V1_2::utils::ComponentStore>::make(
- std::make_shared<H2C2ComponentStore>(nullptr));
- hidlVer = "1.2";
- }
- if (hidlStore->registerAsService("software") == android::OK) {
- registered = true;
+ // If the software component store isn't declared in the manifest, we don't
+ // need to create the service and register it.
+ using ::android::hidl::manager::V1_2::IServiceManager;
+ IServiceManager::Transport transport =
+ android::hardware::defaultServiceManager1_2()->getTransport(
+ V1_2::utils::ComponentStore::descriptor, "software");
+ if (transport == IServiceManager::Transport::HWBINDER) {
+ if (!hidlStore) {
+ hidlStore = ::android::sp<V1_2::utils::ComponentStore>::make(
+ std::make_shared<H2C2ComponentStore>(nullptr));
+ hidlVer = "1.2";
+ }
+ if (hidlStore->registerAsService("software") == android::OK) {
+ registered = true;
+ } else {
+ LOG(ERROR) << "Cannot register software Codec2 v" << hidlVer << " service.";
+ }
} else {
- LOG(ERROR) << "Cannot register software Codec2 v" << hidlVer << " service.";
+ LOG(INFO) << "The HIDL software Codec2 service is deprecated"
+ " so it is not being registered with hwservicemanager.";
}
if (registered) {
diff --git a/media/module/mpeg2ts/ATSParser.cpp b/media/module/mpeg2ts/ATSParser.cpp
index 86187bd..88c3cc2 100644
--- a/media/module/mpeg2ts/ATSParser.cpp
+++ b/media/module/mpeg2ts/ATSParser.cpp
@@ -440,6 +440,10 @@
ATSParser::CADescriptor *caDescriptor) {
bool found = false;
while (infoLength > 2) {
+ if (br->numBitsLeft() < 16) {
+ ALOGE("Not enough data left in bitreader");
+ return false;
+ }
unsigned descriptor_tag = br->getBits(8);
ALOGV(" tag = 0x%02x", descriptor_tag);
@@ -452,6 +456,10 @@
}
if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
found = true;
+ if (br->numBitsLeft() < 32) {
+ ALOGE("Not enough data left in bitreader");
+ return false;
+ }
caDescriptor->mSystemID = br->getBits(16);
caDescriptor->mPID = br->getBits(16) & 0x1fff;
infoLength -= 4;
@@ -460,14 +468,24 @@
break;
} else {
infoLength -= descriptor_length;
- br->skipBits(descriptor_length * 8);
+ if (!br->skipBits(descriptor_length * 8)) {
+ ALOGE("Not enough data left in bitreader");
+ return false;
+ }
}
}
- br->skipBits(infoLength * 8);
+ if (!br->skipBits(infoLength * 8)) {
+ ALOGE("Not enough data left in bitreader");
+ return false;
+ }
return found;
}
status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
+ if (br->numBitsLeft() < 10) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned table_id = br->getBits(8);
ALOGV(" table_id = %u", table_id);
if (table_id != 0x02u) {
@@ -482,6 +500,10 @@
}
br->skipBits(1); // '0'
+ if (br->numBitsLeft() < 86) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
MY_LOGV(" reserved = %u", br->getBits(2));
unsigned section_length = br->getBits(12);
@@ -526,6 +548,10 @@
while (infoBytesRemaining >= 5) {
StreamInfo info;
+ if (br->numBitsLeft() < 40) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
info.mType = br->getBits(8);
ALOGV(" stream_type = 0x%02x", info.mType);
MY_LOGV(" reserved = %u", br->getBits(3));
@@ -545,6 +571,10 @@
info.mAudioPresentations.clear();
bool hasStreamCA = false;
while (ES_info_length > 2 && infoBytesRemaining >= 0) {
+ if (br->numBitsLeft() < 16) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned descriptor_tag = br->getBits(8);
ALOGV(" tag = 0x%02x", descriptor_tag);
@@ -562,21 +592,39 @@
if (descriptor_tag == DESCRIPTOR_DTS) {
info.mType = STREAMTYPE_DTS;
ES_info_length -= descriptor_length;
- br->skipBits(descriptor_length * 8);
+ if (!br->skipBits(descriptor_length * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
} else if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
hasStreamCA = true;
+ if (br->numBitsLeft() < 32) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
streamCA.mSystemID = br->getBits(16);
streamCA.mPID = br->getBits(16) & 0x1fff;
ES_info_length -= descriptor_length;
descriptor_length -= 4;
streamCA.mPrivateData.assign(br->data(), br->data() + descriptor_length);
- br->skipBits(descriptor_length * 8);
+ if (!br->skipBits(descriptor_length * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
} else if (info.mType == STREAMTYPE_PES_PRIVATE_DATA &&
descriptor_tag == DESCRIPTOR_DVB_EXTENSION && descriptor_length >= 1) {
+ if (br->numBitsLeft() < 8) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned descTagExt = br->getBits(8);
ALOGV(" tag_ext = 0x%02x", descTagExt);
ES_info_length -= descriptor_length;
descriptor_length--;
+ if (br->numBitsLeft() < (descriptor_length * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
// The AC4 descriptor is used in the PSI PMT to identify streams which carry AC4
// audio.
if (descTagExt == EXT_DESCRIPTOR_DVB_AC4) {
@@ -594,6 +642,10 @@
br->skipBits(descriptor_length * 8);
} else if (descTagExt == EXT_DESCRIPTOR_DVB_AUDIO_PRESELECTION &&
descriptor_length >= 1) {
+ if (br->numBitsLeft() < 8) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
// DVB BlueBook A038 Table 110
unsigned num_preselections = br->getBits(5);
br->skipBits(3); // reserved
@@ -671,11 +723,17 @@
info.mAudioPresentations.push_back(std::move(ap));
}
} else {
- br->skipBits(descriptor_length * 8);
+ if (!br->skipBits(descriptor_length * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
}
} else {
ES_info_length -= descriptor_length;
- br->skipBits(descriptor_length * 8);
+ if (!br->skipBits(descriptor_length * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
}
}
if (hasStreamCA && !mParser->mCasManager->addStream(
@@ -694,6 +752,10 @@
if (infoBytesRemaining != 0) {
ALOGW("Section data remains unconsumed");
}
+ if (br->numBitsLeft() < 32) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned crc = br->getBits(32);
if (crc != mPMT_CRC) {
audioPresentationsChanged = true;
@@ -1261,6 +1323,10 @@
status_t ATSParser::Stream::parsePES(ABitReader *br, SyncEvent *event) {
const uint8_t *basePtr = br->data();
+ if (br->numBitsLeft() < 48) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned packet_startcode_prefix = br->getBits(24);
ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
@@ -1286,10 +1352,14 @@
&& stream_id != 0xff // program_stream_directory
&& stream_id != 0xf2 // DSMCC
&& stream_id != 0xf8) { // H.222.1 type E
- if (br->getBits(2) != 2u) {
+ if (br->numBitsLeft() < 2 || br->getBits(2) != 2u) {
return ERROR_MALFORMED;
}
+ if (br->numBitsLeft() < 22) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned PES_scrambling_control = br->getBits(2);
ALOGV("PES_scrambling_control = %u", PES_scrambling_control);
@@ -1328,19 +1398,19 @@
return ERROR_MALFORMED;
}
- if (br->getBits(4) != PTS_DTS_flags) {
+ if (br->numBitsLeft() < 7 || br->getBits(4) != PTS_DTS_flags) {
return ERROR_MALFORMED;
}
PTS = ((uint64_t)br->getBits(3)) << 30;
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
PTS |= ((uint64_t)br->getBits(15)) << 15;
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
PTS |= br->getBits(15);
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
@@ -1353,20 +1423,20 @@
return ERROR_MALFORMED;
}
- if (br->getBits(4) != 1u) {
+ if (br->numBitsLeft() < 7 || br->getBits(4) != 1u) {
return ERROR_MALFORMED;
}
DTS = ((uint64_t)br->getBits(3)) << 30;
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
DTS |= ((uint64_t)br->getBits(15)) << 15;
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
DTS |= br->getBits(15);
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
@@ -1381,22 +1451,30 @@
return ERROR_MALFORMED;
}
+ if (br->numBitsLeft() < 5) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
br->getBits(2);
uint64_t ESCR = ((uint64_t)br->getBits(3)) << 30;
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
ESCR |= ((uint64_t)br->getBits(15)) << 15;
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
ESCR |= br->getBits(15);
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
ALOGV("ESCR = %" PRIu64, ESCR);
+ if (br->numBitsLeft() < 10) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
MY_LOGV("ESCR_extension = %u", br->getBits(9));
if (br->getBits(1) != 1u) {
@@ -1411,18 +1489,25 @@
return ERROR_MALFORMED;
}
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
+ return ERROR_MALFORMED;
+ }
+ if (br->numBitsLeft() < 22) {
+ ALOGE("Not enough data left in bitreader!");
return ERROR_MALFORMED;
}
MY_LOGV("ES_rate = %u", br->getBits(22));
- if (br->getBits(1) != 1u) {
+ if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
return ERROR_MALFORMED;
}
optional_bytes_remaining -= 3;
}
- br->skipBits(optional_bytes_remaining * 8);
+ if (!br->skipBits(optional_bytes_remaining * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
// ES data follows.
int32_t pesOffset = br->data() - basePtr;
@@ -1450,7 +1535,10 @@
PTS_DTS_flags, PTS, DTS, PES_scrambling_control,
br->data(), dataLength, pesOffset, event);
- br->skipBits(dataLength * 8);
+ if (!br->skipBits(dataLength * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
} else {
onPayloadData(
PTS_DTS_flags, PTS, DTS, PES_scrambling_control,
@@ -1465,15 +1553,13 @@
payloadSizeBits / 8, pesOffset);
}
} else if (stream_id == 0xbe) { // padding_stream
- if (PES_packet_length == 0u) {
+ if (PES_packet_length == 0u || !br->skipBits(PES_packet_length * 8)) {
return ERROR_MALFORMED;
}
- br->skipBits(PES_packet_length * 8);
} else {
- if (PES_packet_length == 0u) {
+ if (PES_packet_length == 0u || !br->skipBits(PES_packet_length * 8)) {
return ERROR_MALFORMED;
}
- br->skipBits(PES_packet_length * 8);
}
return OK;
@@ -1481,6 +1567,10 @@
uint32_t ATSParser::Stream::getPesScramblingControl(
ABitReader *br, int32_t *pesOffset) {
+ if (br->numBitsLeft() < 24) {
+ ALOGE("Not enough data left in bitreader!");
+ return 0;
+ }
unsigned packet_startcode_prefix = br->getBits(24);
ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
@@ -1491,6 +1581,7 @@
}
if (br->numBitsLeft() < 48) {
+ ALOGE("Not enough data left in bitreader!");
return 0;
}
@@ -1987,12 +2078,20 @@
}
void ATSParser::parseProgramAssociationTable(ABitReader *br) {
+ if (br->numBitsLeft() < 8) {
+ ALOGE("Not enough data left in bitreader!");
+ return;
+ }
unsigned table_id = br->getBits(8);
ALOGV(" table_id = %u", table_id);
if (table_id != 0x00u) {
ALOGE("PAT data error!");
return ;
}
+ if (br->numBitsLeft() < 56) {
+ ALOGE("Not enough data left in bitreader!");
+ return;
+ }
unsigned section_syntax_indictor = br->getBits(1);
ALOGV(" section_syntax_indictor = %u", section_syntax_indictor);
@@ -2009,9 +2108,17 @@
MY_LOGV(" section_number = %u", br->getBits(8));
MY_LOGV(" last_section_number = %u", br->getBits(8));
+ // check for unsigned integer overflow before assigning it to numProgramBytes
+ if (section_length < 9) {
+ return;
+ }
size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
for (size_t i = 0; i < numProgramBytes / 4; ++i) {
+ if (br->numBitsLeft() < 32) {
+ ALOGE("Not enough data left in bitreader!");
+ return;
+ }
unsigned program_number = br->getBits(16);
ALOGV(" program_number = %u", program_number);
@@ -2049,6 +2156,10 @@
}
}
+ if (br->numBitsLeft() < 32) {
+ ALOGE("Not enough data left in bitreader!");
+ return;
+ }
MY_LOGV(" CRC = 0x%08x", br->getBits(32));
}
@@ -2070,9 +2181,16 @@
section->clear();
}
+ if (br->numBitsLeft() < 8) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned skip = br->getBits(8);
section->setSkipBytes(skip + 1); // skip filler bytes + pointer field itself
- br->skipBits(skip * 8);
+ if (!br->skipBits(skip * 8)) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
}
if (br->numBitsLeft() % 8 != 0) {
@@ -2157,6 +2275,10 @@
status_t ATSParser::parseAdaptationField(
ABitReader *br, unsigned PID, unsigned *random_access_indicator) {
*random_access_indicator = 0;
+ if (br->numBitsLeft() < 8) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned adaptation_field_length = br->getBits(8);
if (adaptation_field_length > 0) {
@@ -2227,6 +2349,10 @@
status_t ATSParser::parseTS(ABitReader *br, SyncEvent *event) {
ALOGV("---");
+ if (br->numBitsLeft() < 32) {
+ ALOGE("Not enough data left in bitreader!");
+ return ERROR_MALFORMED;
+ }
unsigned sync_byte = br->getBits(8);
if (sync_byte != 0x47u) {
ALOGE("[error] parseTS: return error as sync_byte=0x%x", sync_byte);
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 2946398..c4f2808 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -27,7 +27,6 @@
#include <media/AidlConversionUtil.h>
#include <android/content/AttributionSourceState.h>
-#include <com_android_media_audio.h>
#include <iterator>
#include <algorithm>
#include <pwd.h>
@@ -388,10 +387,6 @@
*/
bool mustAnonymizeBluetoothAddress(
const AttributionSourceState& attributionSource, const String16& caller) {
- if (!com::android::media::audio::bluetooth_mac_address_anonymization()) {
- return false;
- }
-
uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
if (isAudioServerOrSystemServerUid(uid)) {
return false;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bdbd4d6..fcf02d9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -4784,7 +4784,7 @@
case TransactionCode::GET_AUDIO_POLICY_CONFIG:
case TransactionCode::GET_AUDIO_MIX_PORT:
ALOGW("%s: transaction %d received from PID %d",
- __func__, code, IPCThreadState::self()->getCallingPid());
+ __func__, static_cast<int>(code), IPCThreadState::self()->getCallingPid());
// return status only for non void methods
switch (code) {
case TransactionCode::SET_RECORD_SILENCED:
@@ -4817,7 +4817,8 @@
case TransactionCode::SUPPORTS_BLUETOOTH_VARIABLE_LATENCY: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
- __func__, code, IPCThreadState::self()->getCallingPid(),
+ __func__, static_cast<int>(code),
+ IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
// return status only for non-void methods
switch (code) {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3fdd5cb..767c502 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -223,6 +223,8 @@
static const int kPriorityAudioApp = 2;
static const int kPriorityFastMixer = 3;
static const int kPriorityFastCapture = 3;
+// Request real-time priority for PlaybackThread in ARC
+static const int kPriorityPlaybackThreadArc = 1;
// IAudioFlinger::createTrack() has an in/out parameter 'pFrameCount' for the total size of the
// track buffer in shared memory. Zero on input means to use a default value. For fast tracks,
@@ -3954,6 +3956,27 @@
stream()->setHalThreadPriority(priorityBoost);
}
}
+ } else if (property_get_bool("ro.boot.container", false /* default_value */)) {
+ // In ARC experiments (b/73091832), the latency under using CFS scheduler with any priority
+ // is not enough for PlaybackThread to process audio data in time. We request the lowest
+ // real-time priority, SCHED_FIFO=1, for PlaybackThread in ARC. ro.boot.container is true
+ // only on ARC.
+ const pid_t tid = getTid();
+ if (tid == -1) {
+ ALOGW("%s: Cannot update PlaybackThread priority for ARC, no tid", __func__);
+ } else {
+ const status_t status = requestPriority(getpid(),
+ tid,
+ kPriorityPlaybackThreadArc,
+ false /* isForApp */,
+ true /* asynchronous */);
+ if (status != OK) {
+ ALOGW("%s: Cannot update PlaybackThread priority for ARC, status %d", __func__,
+ status);
+ } else {
+ stream()->setHalThreadPriority(kPriorityPlaybackThreadArc);
+ }
+ }
}
Vector<sp<IAfTrack>> tracksToRemove;
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 6797e3d..8d40b63 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -282,7 +282,7 @@
auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
if (id == AUDIO_PORT_HANDLE_NONE) {
ALOGI("%s: no mapped id for audio device with type %d and address %s",
- __func__, in_audioDevice.type.type,
+ __func__, static_cast<int>(in_audioDevice.type.type),
in_audioDevice.address.toString().c_str());
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
@@ -315,7 +315,7 @@
auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
if (id == AUDIO_PORT_HANDLE_NONE) {
ALOGI("%s: no mapped id for audio device with type %d and address %s",
- __func__, in_audioDevice.type.type,
+ __func__, static_cast<int>(in_audioDevice.type.type),
in_audioDevice.address.toString().c_str());
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
diff --git a/services/audioparameterparser/Android.bp b/services/audioparameterparser/Android.bp
new file mode 100644
index 0000000..18205bd
--- /dev/null
+++ b/services/audioparameterparser/Android.bp
@@ -0,0 +1,70 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: [
+ "frameworks_av_services_audioparameterparser_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_av_services_audioparameterparser_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
+cc_defaults {
+ name: "android.hardware.audio.parameter_parser.example_defaults",
+ defaults: [
+ "latest_android_hardware_audio_core_ndk_shared",
+ ],
+
+ shared_libs: [
+ "av-audio-types-aidl-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.audio.parameter_parser.example_service",
+ system_ext_specific: true,
+ relative_install_path: "hw",
+
+ init_rc: ["android.hardware.audio.parameter_parser.example_service.rc"],
+ vintf_fragments: ["android.hardware.audio.parameter_parser.example_service.xml"],
+
+ defaults: [
+ "android.hardware.audio.parameter_parser.example_defaults",
+ ],
+
+ srcs: [
+ "ParameterParser.cpp",
+ "main.cpp",
+ ],
+}
diff --git a/services/audioparameterparser/NOTICE b/services/audioparameterparser/NOTICE
new file mode 100644
index 0000000..44158cb
--- /dev/null
+++ b/services/audioparameterparser/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2024, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/services/audioparameterparser/ParameterParser.cpp b/services/audioparameterparser/ParameterParser.cpp
new file mode 100644
index 0000000..8d6a64f
--- /dev/null
+++ b/services/audioparameterparser/ParameterParser.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 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 "ParameterParser.h"
+
+#define LOG_TAG "Audio_ParameterParser"
+#include <android-base/logging.h>
+
+namespace vendor::audio::parserservice {
+
+using ::aidl::android::hardware::audio::core::VendorParameter;
+using ParameterScope = ::aidl::android::media::audio::IHalAdapterVendorExtension::ParameterScope;
+
+::ndk::ScopedAStatus ParameterParser::parseVendorParameterIds(ParameterScope in_scope,
+ const std::string& in_rawKeys,
+ std::vector<std::string>*) {
+ LOG(DEBUG) << __func__ << ": scope: " << toString(in_scope) << ", keys: " << in_rawKeys;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ParameterParser::parseVendorParameters(ParameterScope in_scope,
+ const std::string& in_rawKeysAndValues,
+ std::vector<VendorParameter>*,
+ std::vector<VendorParameter>*) {
+ LOG(DEBUG) << __func__ << ": scope: " << toString(in_scope)
+ << ", keys/values: " << in_rawKeysAndValues;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ParameterParser::parseBluetoothA2dpReconfigureOffload(
+ const std::string& in_rawValue, std::vector<VendorParameter>*) {
+ LOG(DEBUG) << __func__ << ": value: " << in_rawValue;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ParameterParser::parseBluetoothLeReconfigureOffload(
+ const std::string& in_rawValue, std::vector<VendorParameter>*) {
+ LOG(DEBUG) << __func__ << ": value: " << in_rawValue;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ParameterParser::processVendorParameters(
+ ParameterScope in_scope, const std::vector<VendorParameter>& in_parameters, std::string*) {
+ LOG(DEBUG) << __func__ << ": scope: " << toString(in_scope)
+ << ", parameters: " << ::android::internal::ToString(in_parameters);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace vendor::audio::parserservice
diff --git a/services/audioparameterparser/ParameterParser.h b/services/audioparameterparser/ParameterParser.h
new file mode 100644
index 0000000..1e0e333
--- /dev/null
+++ b/services/audioparameterparser/ParameterParser.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
+
+namespace vendor::audio::parserservice {
+
+class ParameterParser : public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
+ public:
+ ParameterParser() = default;
+
+ private:
+ ::ndk::ScopedAStatus parseVendorParameterIds(
+ ::aidl::android::media::audio::IHalAdapterVendorExtension::ParameterScope in_scope,
+ const std::string& in_rawKeys, std::vector<std::string>* _aidl_return) override;
+
+ ::ndk::ScopedAStatus parseVendorParameters(
+ ::aidl::android::media::audio::IHalAdapterVendorExtension::ParameterScope in_scope,
+ const std::string& in_rawKeysAndValues,
+ std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
+ out_syncParameters,
+ std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
+ out_asyncParameters) override;
+
+ ::ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
+ const std::string& in_rawValue,
+ std::vector<::aidl::android::hardware::audio::core::VendorParameter>* _aidl_return)
+ override;
+
+ ::ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(
+ const std::string& in_rawValue,
+ std::vector<::aidl::android::hardware::audio::core::VendorParameter>* _aidl_return)
+ override;
+
+ ::ndk::ScopedAStatus processVendorParameters(
+ ::aidl::android::media::audio::IHalAdapterVendorExtension::ParameterScope in_scope,
+ const std::vector<::aidl::android::hardware::audio::core::VendorParameter>&
+ in_parameters,
+ std::string* _aidl_return) override;
+};
+
+} // namespace vendor::audio::parserservice
diff --git a/services/audioparameterparser/android.hardware.audio.parameter_parser.example_service.rc b/services/audioparameterparser/android.hardware.audio.parameter_parser.example_service.rc
new file mode 100644
index 0000000..b6aca5c
--- /dev/null
+++ b/services/audioparameterparser/android.hardware.audio.parameter_parser.example_service.rc
@@ -0,0 +1,6 @@
+service audio_parameter_parser_service /system_ext/bin/hw/android.hardware.audio.parameter_parser.example_service
+ class core
+ user audioserver
+ group media
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh HighPerformance
diff --git a/services/audioparameterparser/android.hardware.audio.parameter_parser.example_service.xml b/services/audioparameterparser/android.hardware.audio.parameter_parser.example_service.xml
new file mode 100644
index 0000000..91addaa
--- /dev/null
+++ b/services/audioparameterparser/android.hardware.audio.parameter_parser.example_service.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="framework">
+ <hal format="aidl">
+ <name>android.media.audio</name>
+ <version>1</version>
+ <fqname>IHalAdapterVendorExtension/default</fqname>
+ </hal>
+</manifest>
diff --git a/services/audioparameterparser/main.cpp b/services/audioparameterparser/main.cpp
new file mode 100644
index 0000000..d22eb55
--- /dev/null
+++ b/services/audioparameterparser/main.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 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_TAG "Audio_ParameterParser"
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "ParameterParser.h"
+
+using vendor::audio::parserservice::ParameterParser;
+
+int main() {
+ // This is a debug implementation, always enable debug logging.
+ android::base::SetMinimumLogSeverity(::android::base::DEBUG);
+
+ auto parser = ndk::SharedRefBase::make<ParameterParser>();
+ const std::string parserFqn =
+ std::string().append(ParameterParser::descriptor).append("/default");
+ binder_status_t status =
+ AServiceManager_addService(parser->asBinder().get(), parserFqn.c_str());
+ if (status != STATUS_OK) {
+ LOG(ERROR) << "failed to register service for \"" << parserFqn << "\"";
+ }
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 9ececea..bfc3132 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -269,6 +269,7 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes) = 0;
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
+ virtual status_t getRegisteredPolicyMixes(std::vector<AudioMix>& mixes) = 0;
virtual status_t updatePolicyMix(
const AudioMix& mix,
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index f3a9518..688772c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -70,10 +70,17 @@
return mMixerBehaviors;
}
+ enum CompatibilityScore{
+ NO_MATCH = 0,
+ PARTIAL_MATCH = 1,
+ EXACT_MATCH = 2
+ };
+
/**
- * @brief isCompatibleProfile: This method is used for input and direct output,
+ * @brief compatibilityScore: This method is used for input and direct output,
* and is not used for other output.
- * Checks if the IO profile is compatible with specified parameters.
+ * Return the compatibility score to measure how much the IO profile is compatible
+ * with specified parameters.
* For input, flags is interpreted as audio_input_flags_t.
* TODO: merge audio_output_flags_t and audio_input_flags_t.
*
@@ -86,18 +93,18 @@
* @param updatedChannelMask if non-NULL, it is assigned the actual channel mask
* @param flags to be checked for compatibility
* @param exactMatchRequiredForInputFlags true if exact match is required on flags
- * @return true if the profile is compatible, false otherwise.
+ * @return how the IO profile is compatible with the given parameters.
*/
- bool isCompatibleProfile(const DeviceVector &devices,
- uint32_t samplingRate,
- uint32_t *updatedSamplingRate,
- audio_format_t format,
- audio_format_t *updatedFormat,
- audio_channel_mask_t channelMask,
- audio_channel_mask_t *updatedChannelMask,
- // FIXME parameter type
- uint32_t flags,
- bool exactMatchRequiredForInputFlags = false) const;
+ CompatibilityScore getCompatibilityScore(const DeviceVector &devices,
+ uint32_t samplingRate,
+ uint32_t *updatedSamplingRate,
+ audio_format_t format,
+ audio_format_t *updatedFormat,
+ audio_channel_mask_t channelMask,
+ audio_channel_mask_t *updatedChannelMask,
+ // FIXME parameter type
+ uint32_t flags,
+ bool exactMatchRequiredForInputFlags = false) const;
/**
* @brief areAllDevicesSupported: Checks if the given devices are supported by the IO profile.
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index dd222de..d9fbd89 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -33,17 +33,17 @@
}
}
-bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
- uint32_t samplingRate,
- uint32_t *updatedSamplingRate,
- audio_format_t format,
- audio_format_t *updatedFormat,
- audio_channel_mask_t channelMask,
- audio_channel_mask_t *updatedChannelMask,
- // FIXME type punning here
- uint32_t flags,
- bool exactMatchRequiredForInputFlags) const
-{
+IOProfile::CompatibilityScore IOProfile::getCompatibilityScore(
+ const android::DeviceVector &devices,
+ uint32_t samplingRate,
+ uint32_t *updatedSamplingRate,
+ audio_format_t format,
+ audio_format_t *updatedFormat,
+ audio_channel_mask_t channelMask,
+ audio_channel_mask_t *updatedChannelMask,
+ // FIXME type punning here
+ uint32_t flags,
+ bool exactMatchRequiredForInputFlags) const {
const bool isPlaybackThread =
getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
const bool isRecordThread =
@@ -51,13 +51,13 @@
ALOG_ASSERT(isPlaybackThread != isRecordThread);
if (!areAllDevicesSupported(devices) ||
!isCompatibleProfileForFlags(flags, exactMatchRequiredForInputFlags)) {
- return false;
+ return NO_MATCH;
}
if (!audio_is_valid_format(format) ||
(isPlaybackThread && (samplingRate == 0 || !audio_is_output_channel(channelMask))) ||
(isRecordThread && (!audio_is_input_channel(channelMask)))) {
- return false;
+ return NO_MATCH;
}
audio_format_t myUpdatedFormat = format;
@@ -69,32 +69,40 @@
.channel_mask = channelMask,
.format = format,
};
+ auto result = NO_MATCH;
if (isRecordThread)
{
if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
if (checkExactAudioProfile(&config) != NO_ERROR) {
- return false;
+ return result;
}
- } else if (checkExactAudioProfile(&config) != NO_ERROR && checkCompatibleAudioProfile(
- myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) != NO_ERROR) {
- return false;
+ result = EXACT_MATCH;
+ } else if (checkExactAudioProfile(&config) == NO_ERROR) {
+ result = EXACT_MATCH;
+ } else if (checkCompatibleAudioProfile(
+ myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) == NO_ERROR) {
+ result = PARTIAL_MATCH;
+ } else {
+ return result;
}
} else {
- if (checkExactAudioProfile(&config) != NO_ERROR) {
- return false;
+ if (checkExactAudioProfile(&config) == NO_ERROR) {
+ result = EXACT_MATCH;
+ } else {
+ return result;
}
}
- if (updatedSamplingRate != NULL) {
+ if (updatedSamplingRate != nullptr) {
*updatedSamplingRate = myUpdatedSamplingRate;
}
- if (updatedFormat != NULL) {
+ if (updatedFormat != nullptr) {
*updatedFormat = myUpdatedFormat;
}
- if (updatedChannelMask != NULL) {
+ if (updatedChannelMask != nullptr) {
*updatedChannelMask = myUpdatedChannelMask;
}
- return true;
+ return result;
}
bool IOProfile::areAllDevicesSupported(const DeviceVector &devices) const {
@@ -156,9 +164,9 @@
for (const auto sampleRate : profile->getSampleRates()) {
for (const auto channelMask : profile->getChannels()) {
const audio_config_base_t config = {
- .format = profile->getFormat(),
.sample_rate = sampleRate,
- .channel_mask = channelMask
+ .channel_mask = channelMask,
+ .format = profile->getFormat(),
};
for (const auto mixerBehavior : mMixerBehaviors) {
mixerAttributes->push_back({
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 8b2f9ea..2f46d48 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -45,6 +45,7 @@
"libaudioclient_aidl_conversion",
"audioclient-types-aidl-cpp",
// Flag support
+ "android.media.audiopolicy-aconfig-cc",
"com.android.media.audioserver-aconfig-cc",
],
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index cce2e93..2761480 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -42,6 +42,7 @@
#include <Serializer.h>
#include <android/media/audio/common/AudioPort.h>
#include <com_android_media_audio.h>
+#include <android_media_audiopolicy.h>
#include <com_android_media_audioserver.h>
#include <cutils/bitops.h>
#include <cutils/properties.h>
@@ -58,6 +59,9 @@
namespace android {
+
+namespace audio_flags = android::media::audiopolicy;
+
using android::media::audio::common::AudioDevice;
using android::media::audio::common::AudioDeviceAddress;
using android::media::audio::common::AudioPortDeviceExt;
@@ -125,7 +129,8 @@
device->toAudioPort(&devicePort);
if (status_t status = mpClientInterface->setDeviceConnectedState(&devicePort, state);
status != OK) {
- ALOGE("Error %d while setting connected state for device %s", state,
+ ALOGE("Error %d while setting connected state for device %s",
+ static_cast<int>(state),
device->getDeviceTypeAddr().toString(false).c_str());
}
}
@@ -1050,11 +1055,11 @@
sp<IOProfile> profile;
for (const auto& hwModule : hwModules) {
for (const auto& curProfile : hwModule->getOutputProfiles()) {
- if (!curProfile->isCompatibleProfile(devices,
+ if (curProfile->getCompatibilityScore(devices,
samplingRate, NULL /*updatedSamplingRate*/,
format, NULL /*updatedFormat*/,
channelMask, NULL /*updatedChannelMask*/,
- flags)) {
+ flags) == IOProfile::NO_MATCH) {
continue;
}
// reject profiles not corresponding to a device currently available
@@ -3865,6 +3870,24 @@
return res;
}
+status_t AudioPolicyManager::getRegisteredPolicyMixes(std::vector<AudioMix>& _aidl_return) {
+ if (!audio_flags::audio_mix_test_api()) {
+ return INVALID_OPERATION;
+ }
+
+ _aidl_return.clear();
+ _aidl_return.reserve(mPolicyMixes.size());
+ for (const auto &policyMix: mPolicyMixes) {
+ _aidl_return.emplace_back(policyMix->mCriteria, policyMix->mMixType,
+ policyMix->mFormat, policyMix->mRouteFlags, policyMix->mDeviceAddress,
+ policyMix->mCbFlags);
+ _aidl_return.back().mDeviceType = policyMix->mDeviceType;
+ }
+
+ ALOGVV("%s() returning %zu registered mixes", __func__, _aidl_return->size());
+ return OK;
+}
+
status_t AudioPolicyManager::updatePolicyMix(
const AudioMix& mix,
const std::vector<AudioMixMatchCriterion>& updatedCriteria) {
@@ -4486,11 +4509,11 @@
outputDevices = getMsdAudioOutDevices();
}
for (const auto& curProfile : hwModule->getOutputProfiles()) {
- if (!curProfile->isCompatibleProfile(outputDevices,
+ if (curProfile->getCompatibilityScore(outputDevices,
config->sample_rate, nullptr /*updatedSamplingRate*/,
config->format, nullptr /*updatedFormat*/,
config->channel_mask, nullptr /*updatedChannelMask*/,
- flags)) {
+ flags) == IOProfile::NO_MATCH) {
continue;
}
// reject profiles not corresponding to a device currently available
@@ -4596,15 +4619,17 @@
for (const auto& hwModule : mHwModules) {
for (const auto& curProfile : hwModule->getOutputProfiles()) {
if (curProfile->hasDynamicAudioProfile()
- && curProfile->isCompatibleProfile(devices,
- mixerAttributes->config.sample_rate,
- nullptr /*updatedSamplingRate*/,
- mixerAttributes->config.format,
- nullptr /*updatedFormat*/,
- mixerAttributes->config.channel_mask,
- nullptr /*updatedChannelMask*/,
- flags,
- false /*exactMatchRequiredForInputFlags*/)) {
+ && curProfile->getCompatibilityScore(
+ devices,
+ mixerAttributes->config.sample_rate,
+ nullptr /*updatedSamplingRate*/,
+ mixerAttributes->config.format,
+ nullptr /*updatedFormat*/,
+ mixerAttributes->config.channel_mask,
+ nullptr /*updatedChannelMask*/,
+ flags,
+ false /*exactMatchRequiredForInputFlags*/)
+ != IOProfile::NO_MATCH) {
profile = curProfile;
break;
}
@@ -5009,14 +5034,15 @@
return BAD_VALUE;
}
- if (!outputDesc->mProfile->isCompatibleProfile(DeviceVector(devDesc),
- patch->sources[0].sample_rate,
- NULL, // updatedSamplingRate
- patch->sources[0].format,
- NULL, // updatedFormat
- patch->sources[0].channel_mask,
- NULL, // updatedChannelMask
- AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
+ if (outputDesc->mProfile->getCompatibilityScore(
+ DeviceVector(devDesc),
+ patch->sources[0].sample_rate,
+ nullptr, // updatedSamplingRate
+ patch->sources[0].format,
+ nullptr, // updatedFormat
+ patch->sources[0].channel_mask,
+ nullptr, // updatedChannelMask
+ AUDIO_OUTPUT_FLAG_NONE /*FIXME*/) == IOProfile::NO_MATCH) {
ALOGV("%s profile not supported for device %08x", __func__, devDesc->type());
return INVALID_OPERATION;
}
@@ -5064,17 +5090,18 @@
return BAD_VALUE;
}
- if (!inputDesc->mProfile->isCompatibleProfile(DeviceVector(device),
- patch->sinks[0].sample_rate,
- NULL, /*updatedSampleRate*/
- patch->sinks[0].format,
- NULL, /*updatedFormat*/
- patch->sinks[0].channel_mask,
- NULL, /*updatedChannelMask*/
- // FIXME for the parameter type,
- // and the NONE
- (audio_output_flags_t)
- AUDIO_INPUT_FLAG_NONE)) {
+ if (inputDesc->mProfile->getCompatibilityScore(
+ DeviceVector(device),
+ patch->sinks[0].sample_rate,
+ nullptr, /*updatedSampleRate*/
+ patch->sinks[0].format,
+ nullptr, /*updatedFormat*/
+ patch->sinks[0].channel_mask,
+ nullptr, /*updatedChannelMask*/
+ // FIXME for the parameter type,
+ // and the NONE
+ (audio_output_flags_t)
+ AUDIO_INPUT_FLAG_NONE) == IOProfile::NO_MATCH) {
return INVALID_OPERATION;
}
// TODO: reconfigure output format and channels here
@@ -7696,9 +7723,6 @@
// Choose an input profile based on the requested capture parameters: select the first available
// profile supporting all requested parameters.
// The flags can be ignored if it doesn't contain a much match flag.
- //
- // TODO: perhaps isCompatibleProfile should return a "matching" score so we can return
- // the best matching profile, not the first one.
using underlying_input_flag_t = std::underlying_type_t<audio_input_flags_t>;
const underlying_input_flag_t mustMatchFlag = AUDIO_INPUT_FLAG_MMAP_NOIRQ |
@@ -7715,27 +7739,35 @@
for (const auto& profile : hwModule->getInputProfiles()) {
// profile->log();
//updatedFormat = format;
- if (profile->isCompatibleProfile(DeviceVector(device), samplingRate,
- &samplingRate /*updatedSamplingRate*/,
- format,
- &format, /*updatedFormat*/
- channelMask,
- &channelMask /*updatedChannelMask*/,
- // FIXME ugly cast
- (audio_output_flags_t) flags,
- true /*exactMatchRequiredForInputFlags*/)) {
+ if (profile->getCompatibilityScore(
+ DeviceVector(device),
+ samplingRate,
+ &updatedSamplingRate,
+ format,
+ &updatedFormat,
+ channelMask,
+ &updatedChannelMask,
+ // FIXME ugly cast
+ (audio_output_flags_t) flags,
+ true /*exactMatchRequiredForInputFlags*/) == IOProfile::EXACT_MATCH) {
+ samplingRate = updatedSamplingRate;
+ format = updatedFormat;
+ channelMask = updatedChannelMask;
return profile;
}
- if (firstInexact == nullptr && profile->isCompatibleProfile(DeviceVector(device),
- samplingRate,
- &updatedSamplingRate,
- format,
- &updatedFormat,
- channelMask,
- &updatedChannelMask,
- // FIXME ugly cast
- (audio_output_flags_t) flags,
- false /*exactMatchRequiredForInputFlags*/)) {
+ if (firstInexact == nullptr
+ && profile->getCompatibilityScore(
+ DeviceVector(device),
+ samplingRate,
+ &updatedSamplingRate,
+ format,
+ &updatedFormat,
+ channelMask,
+ &updatedChannelMask,
+ // FIXME ugly cast
+ (audio_output_flags_t) flags,
+ false /*exactMatchRequiredForInputFlags*/)
+ != IOProfile::NO_MATCH) {
firstInexact = profile;
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index ea60c2b..a3232a2 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -292,6 +292,7 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes);
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
+ virtual status_t getRegisteredPolicyMixes(std::vector<AudioMix>& mixes) override;
virtual status_t updatePolicyMix(
const AudioMix& mix,
const std::vector<AudioMixMatchCriterion>& updatedCriteria) override;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 6e1ecec..2a4c069 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1810,6 +1810,23 @@
}
}
+Status
+AudioPolicyService::getRegisteredPolicyMixes(std::vector<::android::media::AudioMix>* mixesAidl) {
+ if (mAudioPolicyManager == nullptr) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+
+ std::vector<AudioMix> mixes;
+ int status = mAudioPolicyManager->getRegisteredPolicyMixes(mixes);
+
+ for (const auto& mix : mixes) {
+ media::AudioMix aidlMix = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_AudioMix(mix));
+ mixesAidl->push_back(aidlMix);
+ }
+
+ return binderStatusFromStatusT(status);
+}
+
Status AudioPolicyService::updatePolicyMixes(
const ::std::vector<::android::media::AudioMixUpdate>& updates) {
audio_utils::lock_guard _l(mMutex);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index aed6458..bc6498a 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -166,7 +166,8 @@
BINDER_METHOD_ENTRY(setPreferredMixerAttributes) \
BINDER_METHOD_ENTRY(getPreferredMixerAttributes) \
BINDER_METHOD_ENTRY(clearPreferredMixerAttributes) \
-
+BINDER_METHOD_ENTRY(getRegisteredPolicyMixes) \
+ \
// singleton for Binder Method Statistics for IAudioPolicyService
static auto& getIAudioPolicyServiceStatistics() {
using Code = int;
@@ -1348,7 +1349,8 @@
case TRANSACTION_getDevicesForRoleAndCapturePreset:
case TRANSACTION_getSpatializer:
case TRANSACTION_setPreferredMixerAttributes:
- case TRANSACTION_clearPreferredMixerAttributes: {
+ case TRANSACTION_clearPreferredMixerAttributes:
+ case TRANSACTION_getRegisteredPolicyMixes: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 9a8a056..101b90c 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -311,6 +311,8 @@
binder::Status clearPreferredMixerAttributes(const media::audio::common::AudioAttributes& attr,
int32_t portId,
int32_t uid) override;
+ binder::Status getRegisteredPolicyMixes(
+ std::vector <::android::media::AudioMix>* mixes) override;
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index d85ac57..dbc48ae 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -887,7 +887,7 @@
spatializerMode = HeadTracking::Mode::RELATIVE_SCREEN;
break;
default:
- LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
+ LOG_ALWAYS_FATAL("Unknown mode: %d", static_cast<int>(mode));
}
}
mActualHeadTrackingMode = spatializerMode;
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 32c7db6..34bd3b4 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -34,11 +34,14 @@
"libutils",
"libcutils",
"libxml2",
+ "server_configurable_flags",
],
static_libs: [
+ "android.media.audiopolicy-aconfig-cc",
"audioclient-types-aidl-cpp",
"libaudiopolicycomponents",
+ "libflagtest",
"libgmock",
],
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 31ee252..aa7c9cd 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -31,6 +31,7 @@
using AudioPolicyManager::getConfig;
using AudioPolicyManager::initialize;
using AudioPolicyManager::getOutputs;
+ using AudioPolicyManager::getInputs;
using AudioPolicyManager::getAvailableOutputDevices;
using AudioPolicyManager::getAvailableInputDevices;
using AudioPolicyManager::setSurroundFormatEnabled;
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 74d3474..e883e10 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -28,6 +28,8 @@
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android/content/AttributionSourceState.h>
+#include <android_media_audiopolicy.h>
+#include <flag_macros.h>
#include <hardware/audio_effect.h>
#include <media/AudioPolicy.h>
#include <media/PatchBuilder.h>
@@ -43,6 +45,7 @@
using namespace android;
using testing::UnorderedElementsAre;
+using testing::IsEmpty;
using android::content::AttributionSourceState;
namespace {
@@ -92,6 +95,12 @@
return attributionSourceState;
}
+bool equals(const audio_config_base_t& config1, const audio_config_base_t& config2) {
+ return config1.format == config2.format
+ && config1.sample_rate == config2.sample_rate
+ && config1.channel_mask == config2.channel_mask;
+}
+
} // namespace
TEST(AudioPolicyConfigTest, DefaultConfigForTestsIsEmpty) {
@@ -1266,6 +1275,53 @@
"", "", AUDIO_FORMAT_LDAC));
}
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, PreferExactConfigForInput) {
+ const audio_channel_mask_t deviceChannelMask = AUDIO_CHANNEL_IN_3POINT1;
+ mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT);
+ mClient->addSupportedChannelMask(deviceChannelMask);
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "", "", AUDIO_FORMAT_DEFAULT));
+
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_VOICE_COMMUNICATION,AUDIO_FLAG_NONE, ""};
+ AudioPolicyInterface::input_type_t inputType;
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ AttributionSourceState attributionSource = createAttributionSourceState(/*uid=*/ 0);
+ audio_config_base_t requestedConfig = {
+ .channel_mask = AUDIO_CHANNEL_IN_STEREO,
+ .format = AUDIO_FORMAT_PCM_16_BIT,
+ .sample_rate = 48000
+ };
+ audio_config_base_t config = requestedConfig;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_EQ(OK, mManager->getInputForAttr(
+ &attr, &input, 1 /*riid*/, AUDIO_SESSION_NONE, attributionSource, &config,
+ AUDIO_INPUT_FLAG_NONE,
+ &selectedDeviceId, &inputType, &portId));
+ ASSERT_NE(AUDIO_PORT_HANDLE_NONE, portId);
+ ASSERT_TRUE(equals(requestedConfig, config));
+
+ attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_FLAG_NONE, ""};
+ requestedConfig.channel_mask = deviceChannelMask;
+ config = requestedConfig;
+ selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ input = AUDIO_PORT_HANDLE_NONE;
+ portId = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_EQ(OK, mManager->getInputForAttr(
+ &attr, &input, 1 /*riid*/, AUDIO_SESSION_NONE, attributionSource, &config,
+ AUDIO_INPUT_FLAG_NONE,
+ &selectedDeviceId, &inputType, &portId));
+ ASSERT_NE(AUDIO_PORT_HANDLE_NONE, portId);
+ ASSERT_TRUE(equals(requestedConfig, config));
+
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "", "", AUDIO_FORMAT_DEFAULT));
+}
+
class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
void TearDown() override;
@@ -1273,6 +1329,8 @@
status_t addPolicyMix(int mixType, int mixFlag, audio_devices_t deviceType,
std::string mixAddress, const audio_config_t& audioConfig,
const std::vector<AudioMixMatchCriterion>& matchCriteria);
+
+ std::vector<AudioMix> getRegisteredPolicyMixes();
void clearPolicyMix();
void addPolicyMixAndStartInputForLoopback(
int mixType, int mixFlag, audio_devices_t deviceType, std::string mixAddress,
@@ -1317,6 +1375,15 @@
return ret;
}
+std::vector<AudioMix> AudioPolicyManagerTestDynamicPolicy::getRegisteredPolicyMixes() {
+ std::vector<AudioMix> audioMixes;
+ if (mManager != nullptr) {
+ status_t ret = mManager->getRegisteredPolicyMixes(audioMixes);
+ EXPECT_EQ(NO_ERROR, ret);
+ }
+ return audioMixes;
+}
+
void AudioPolicyManagerTestDynamicPolicy::clearPolicyMix() {
if (mManager != nullptr) {
mManager->stopInput(mLoopbackInputPortId);
@@ -1470,6 +1537,50 @@
ASSERT_EQ(INVALID_OPERATION, ret);
}
+TEST_F_WITH_FLAGS(
+ AudioPolicyManagerTestDynamicPolicy,
+ GetRegisteredPolicyMixes,
+ REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(android::media::audiopolicy, audio_mix_test_api))
+) {
+ std::vector<AudioMix> mixes = getRegisteredPolicyMixes();
+ EXPECT_THAT(mixes, IsEmpty());
+}
+
+TEST_F_WITH_FLAGS(AudioPolicyManagerTestDynamicPolicy,
+ AddPolicyMixAndVerifyGetRegisteredPolicyMixes,
+ REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(android::media::audiopolicy, audio_mix_test_api))
+) {
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+
+ std::vector<AudioMixMatchCriterion> mixMatchCriteria = {
+ createUidCriterion(/*uid=*/42),
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+ status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+ mixMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ std::vector<AudioMix> mixes = getRegisteredPolicyMixes();
+ ASSERT_EQ(mixes.size(), 1);
+
+ const AudioMix& mix = mixes[0];
+ ASSERT_EQ(mix.mCriteria.size(), mixMatchCriteria.size());
+ for (uint32_t i = 0; i < mixMatchCriteria.size(); i++) {
+ EXPECT_EQ(mix.mCriteria[i].mRule, mixMatchCriteria[i].mRule);
+ EXPECT_EQ(mix.mCriteria[i].mValue.mUsage, mixMatchCriteria[i].mValue.mUsage);
+ }
+ EXPECT_EQ(mix.mDeviceType, AUDIO_DEVICE_OUT_REMOTE_SUBMIX);
+ EXPECT_EQ(mix.mRouteFlags, MIX_ROUTE_FLAG_LOOP_BACK);
+ EXPECT_EQ(mix.mMixType, MIX_TYPE_PLAYERS);
+ EXPECT_EQ(mix.mFormat.channel_mask, audioConfig.channel_mask);
+ EXPECT_EQ(mix.mFormat.format, audioConfig.format);
+ EXPECT_EQ(mix.mFormat.sample_rate, audioConfig.sample_rate);
+ EXPECT_EQ(mix.mFormat.frame_count, audioConfig.frame_count);
+}
+
class AudioPolicyManagerTestForHdmi
: public AudioPolicyManagerTestWithConfigurationFile,
public testing::WithParamInterface<audio_format_t> {
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 4efdf8a..1a299c6 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -65,6 +65,7 @@
samplingRates="48000"
channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>
+ <mixPort name="hifi_input" role="sink" />
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
@@ -111,6 +112,8 @@
sources="primary output,hifi_output,mmap_no_irq_out"/>
<route type="mix" sink="mixport_bus_input"
sources="BUS Device In"/>
+ <route type="mix" sink="hifi_input"
+ sources="USB Device In" />
</routes>
</module>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 3f43af5..76f65c0 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2556,39 +2556,65 @@
// Enable/disable camera service watchdog
client->setCameraServiceWatchdog(mCameraServiceWatchdogEnabled);
- // Set rotate-and-crop override behavior
- if (mOverrideRotateAndCropMode != ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
- client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
- } else if (overrideToPortrait && portraitRotation != 0) {
- uint8_t rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_AUTO;
- switch (portraitRotation) {
- case 90:
- rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_90;
- break;
- case 180:
- rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_180;
- break;
- case 270:
- rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_270;
- break;
- default:
- ALOGE("Unexpected portrait rotation: %d", portraitRotation);
- break;
+ CameraMetadata chars;
+ bool rotateAndCropSupported = true;
+ err = mCameraProviderManager->getCameraCharacteristics(cameraId, overrideForPerfClass,
+ &chars, overrideToPortrait);
+ if (err == OK) {
+ auto availableRotateCropEntry = chars.find(
+ ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES);
+ if (availableRotateCropEntry.count <= 1) {
+ rotateAndCropSupported = false;
}
- client->setRotateAndCropOverride(rotateAndCropMode);
} else {
- client->setRotateAndCropOverride(
- mCameraServiceProxyWrapper->getRotateAndCropOverride(
- clientPackageName, facing, multiuser_get_user_id(clientUid)));
+ ALOGE("%s: Unable to query static metadata for camera %s: %s (%d)", __FUNCTION__,
+ cameraId.c_str(), strerror(-err), err);
}
- // Set autoframing override behaviour
- if (mOverrideAutoframingMode != ANDROID_CONTROL_AUTOFRAMING_AUTO) {
- client->setAutoframingOverride(mOverrideAutoframingMode);
- } else {
- client->setAutoframingOverride(
- mCameraServiceProxyWrapper->getAutoframingOverride(
- clientPackageName));
+ if (rotateAndCropSupported) {
+ // Set rotate-and-crop override behavior
+ if (mOverrideRotateAndCropMode != ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
+ client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
+ } else if (overrideToPortrait && portraitRotation != 0) {
+ uint8_t rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_AUTO;
+ switch (portraitRotation) {
+ case 90:
+ rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_90;
+ break;
+ case 180:
+ rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_180;
+ break;
+ case 270:
+ rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_270;
+ break;
+ default:
+ ALOGE("Unexpected portrait rotation: %d", portraitRotation);
+ break;
+ }
+ client->setRotateAndCropOverride(rotateAndCropMode);
+ } else {
+ client->setRotateAndCropOverride(
+ mCameraServiceProxyWrapper->getRotateAndCropOverride(
+ clientPackageName, facing, multiuser_get_user_id(clientUid)));
+ }
+ }
+
+ bool autoframingSupported = true;
+ auto availableAutoframingEntry = chars.find(ANDROID_CONTROL_AUTOFRAMING_AVAILABLE);
+ if ((availableAutoframingEntry.count == 1) && (availableAutoframingEntry.data.u8[0] ==
+ ANDROID_CONTROL_AUTOFRAMING_AVAILABLE_FALSE)) {
+ autoframingSupported = false;
+ }
+
+ if (autoframingSupported) {
+ // Set autoframing override behaviour
+ if (mOverrideAutoframingMode != ANDROID_CONTROL_AUTOFRAMING_AUTO) {
+ client->setAutoframingOverride(mOverrideAutoframingMode);
+ } else {
+ client->setAutoframingOverride(
+ mCameraServiceProxyWrapper->getAutoframingOverride(
+ clientPackageName));
+ }
}
// Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.cc b/services/camera/virtualcamera/VirtualCameraDevice.cc
index 5a824cc..fccbbc9 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.cc
+++ b/services/camera/virtualcamera/VirtualCameraDevice.cc
@@ -23,8 +23,10 @@
#include <chrono>
#include <cstdint>
#include <iterator>
+#include <numeric>
#include <optional>
#include <string>
+#include <vector>
#include "VirtualCameraSession.h"
#include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
@@ -81,6 +83,17 @@
kOutputFormats.end();
}
+std::vector<MetadataBuilder::FpsRange> fpsRangesForInputConfig(
+ const std::vector<SupportedStreamConfiguration>& configs) {
+ std::set<MetadataBuilder::FpsRange> availableRanges;
+ for (const SupportedStreamConfiguration& config : configs) {
+ availableRanges.insert({.minFps = config.maxFps, .maxFps = config.maxFps});
+ }
+
+ return std::vector<MetadataBuilder::FpsRange>(availableRanges.begin(),
+ availableRanges.end());
+}
+
std::optional<Resolution> getMaxResolution(
const std::vector<SupportedStreamConfiguration>& configs) {
auto itMax = std::max_element(configs.begin(), configs.end(),
@@ -139,7 +152,7 @@
.setFlashAvailable(false)
.setLensFacing(
static_cast<camera_metadata_enum_android_lens_facing>(lensFacing))
- .setFocalLength(43.0)
+ .setAvailableFocalLengths({VirtualCameraDevice::kFocalLength})
.setSensorOrientation(static_cast<int32_t>(sensorOrientation))
.setSensorReadoutTimestamp(
ANDROID_SENSOR_READOUT_TIMESTAMP_NOT_SUPPORTED)
@@ -151,12 +164,16 @@
.setControlAfAvailableModes({ANDROID_CONTROL_AF_MODE_OFF})
.setControlAvailableSceneModes({ANDROID_CONTROL_SCENE_MODE_DISABLED})
.setControlAvailableEffects({ANDROID_CONTROL_EFFECT_MODE_OFF})
- .setControlAeAvailableFpsRange(10, 30)
+ .setControlAeAvailableModes({ANDROID_CONTROL_AE_MODE_ON})
+ .setControlAeAvailableAntibandingModes(
+ {ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO})
+ .setControlAeAvailableFpsRanges(
+ fpsRangesForInputConfig(supportedInputConfig))
.setControlMaxRegions(0, 0, 0)
.setControlAfRegions({kDefaultEmptyControlRegion})
.setControlAeRegions({kDefaultEmptyControlRegion})
.setControlAwbRegions({kDefaultEmptyControlRegion})
- .setControlAeCompensationRange(0, 1)
+ .setControlAeCompensationRange(0, 0)
.setControlAeCompensationStep(camera_metadata_rational_t{0, 1})
.setControlAwbLockAvailable(false)
.setControlAeLockAvailable(false)
@@ -170,9 +187,19 @@
VirtualCameraDevice::kMaxNumberOfProcessedStreams,
VirtualCameraDevice::kMaxNumberOfStallStreams)
.setSyncMaxLatency(ANDROID_SYNC_MAX_LATENCY_UNKNOWN)
- .setAvailableRequestKeys({})
- .setAvailableRequestKeys({ANDROID_CONTROL_AF_MODE})
- .setAvailableResultKeys({ANDROID_CONTROL_AF_MODE})
+ .setAvailableRequestKeys(
+ {ANDROID_CONTROL_CAPTURE_INTENT, ANDROID_CONTROL_AE_MODE,
+ ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+ ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, ANDROID_CONTROL_AF_TRIGGER,
+ ANDROID_CONTROL_AF_MODE, ANDROID_CONTROL_AWB_MODE,
+ ANDROID_STATISTICS_FACE_DETECT_MODE, ANDROID_FLASH_MODE})
+ .setAvailableResultKeys(
+ {ANDROID_CONTROL_AE_MODE, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+ ANDROID_CONTROL_AF_MODE, ANDROID_CONTROL_AWB_MODE,
+ ANDROID_FLASH_STATE, ANDROID_SENSOR_TIMESTAMP,
+ ANDROID_LENS_FOCAL_LENGTH})
.setAvailableCapabilities(
{ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE});
@@ -394,6 +421,11 @@
return std::string(kDevicePathPrefix) + std::to_string(mCameraId);
}
+const std::vector<SupportedStreamConfiguration>&
+VirtualCameraDevice::getInputConfigs() const {
+ return mSupportedInputConfigurations;
+}
+
std::shared_ptr<VirtualCameraDevice> VirtualCameraDevice::sharedFromThis() {
// SharedRefBase which BnCameraDevice inherits from breaks
// std::enable_shared_from_this. This is recommended replacement for
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.h b/services/camera/virtualcamera/VirtualCameraDevice.h
index 3700625..fbd9095 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.h
+++ b/services/camera/virtualcamera/VirtualCameraDevice.h
@@ -94,6 +94,10 @@
uint32_t getCameraId() const { return mCameraId; }
+ const std::vector<
+ aidl::android::companion::virtualcamera::SupportedStreamConfiguration>&
+ getInputConfigs() const;
+
// Maximal number of RAW streams - virtual camera doesn't support RAW streams.
static const int32_t kMaxNumberOfRawStreams = 0;
@@ -107,6 +111,9 @@
// load.
static const int32_t kMaxNumberOfStallStreams = 1;
+ // Focal length for full frame sensor.
+ constexpr static const float kFocalLength = 43.0;
+
private:
std::shared_ptr<VirtualCameraDevice> sharedFromThis();
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
index 25fe61b..cd36c6d 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
@@ -26,6 +26,7 @@
#include <thread>
#include "GLES/gl.h"
+#include "VirtualCameraDevice.h"
#include "VirtualCameraSessionContext.h"
#include "aidl/android/hardware/camera/common/Status.h"
#include "aidl/android/hardware/camera/device/BufferStatus.h"
@@ -74,7 +75,16 @@
CameraMetadata createCaptureResultMetadata(
const std::chrono::nanoseconds timestamp) {
std::unique_ptr<CameraMetadata> metadata =
- MetadataBuilder().setSensorTimestamp(timestamp).build();
+ MetadataBuilder()
+ .setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
+ .setControlAePrecaptureTrigger(
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
+ .setControlAfMode(ANDROID_CONTROL_AF_MODE_AUTO)
+ .setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO)
+ .setFlashState(ANDROID_FLASH_STATE_UNAVAILABLE)
+ .setFocalLength(VirtualCameraDevice::kFocalLength)
+ .setSensorTimestamp(timestamp)
+ .build();
if (metadata == nullptr) {
ALOGE("%s: Failed to build capture result metadata", __func__);
return CameraMetadata();
diff --git a/services/camera/virtualcamera/VirtualCameraSession.cc b/services/camera/virtualcamera/VirtualCameraSession.cc
index 03d63b8..8449f41 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.cc
+++ b/services/camera/virtualcamera/VirtualCameraSession.cc
@@ -27,6 +27,7 @@
#include <map>
#include <memory>
#include <mutex>
+#include <numeric>
#include <optional>
#include <tuple>
#include <unordered_set>
@@ -44,6 +45,7 @@
#include "aidl/android/hardware/camera/device/CaptureRequest.h"
#include "aidl/android/hardware/camera/device/HalStream.h"
#include "aidl/android/hardware/camera/device/NotifyMsg.h"
+#include "aidl/android/hardware/camera/device/RequestTemplate.h"
#include "aidl/android/hardware/camera/device/ShutterMsg.h"
#include "aidl/android/hardware/camera/device/StreamBuffer.h"
#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
@@ -69,6 +71,7 @@
using ::aidl::android::companion::virtualcamera::Format;
using ::aidl::android::companion::virtualcamera::IVirtualCameraCallback;
+using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
using ::aidl::android::hardware::camera::common::Status;
using ::aidl::android::hardware::camera::device::BufferCache;
using ::aidl::android::hardware::camera::device::CameraMetadata;
@@ -102,31 +105,59 @@
// Maximum number of buffers to use per single stream.
static constexpr size_t kMaxStreamBuffers = 2;
-CameraMetadata createDefaultRequestSettings(RequestTemplate type) {
- hardware::camera::common::V1_0::helper::CameraMetadata metadataHelper;
-
- camera_metadata_enum_android_control_capture_intent_t intent =
- ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+camera_metadata_enum_android_control_capture_intent_t requestTemplateToIntent(
+ const RequestTemplate type) {
switch (type) {
case RequestTemplate::PREVIEW:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
- break;
+ return ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
case RequestTemplate::STILL_CAPTURE:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
- break;
+ return ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
case RequestTemplate::VIDEO_RECORD:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
- break;
+ return ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
case RequestTemplate::VIDEO_SNAPSHOT:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
- break;
+ return ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
default:
- // Leave default.
- break;
+ // Return PREVIEW by default
+ return ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
}
+}
- auto metadata = MetadataBuilder().setControlCaptureIntent(intent).build();
- return (metadata != nullptr) ? std::move(*metadata) : CameraMetadata();
+int getMaxFps(const std::vector<SupportedStreamConfiguration>& configs) {
+ return std::transform_reduce(
+ configs.begin(), configs.end(), 0,
+ [](const int a, const int b) { return std::max(a, b); },
+ [](const SupportedStreamConfiguration& config) { return config.maxFps; });
+}
+
+CameraMetadata createDefaultRequestSettings(
+ const RequestTemplate type,
+ const std::vector<SupportedStreamConfiguration>& inputConfigs) {
+ int maxFps = getMaxFps(inputConfigs);
+ auto metadata =
+ MetadataBuilder()
+ .setControlCaptureIntent(requestTemplateToIntent(type))
+ .setControlMode(ANDROID_CONTROL_MODE_AUTO)
+ .setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
+ .setControlAeExposureCompensation(0)
+ .setControlAeTargetFpsRange(maxFps, maxFps)
+ .setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO)
+ .setControlAePrecaptureTrigger(
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
+ .setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE)
+ .setControlAfMode(ANDROID_CONTROL_AF_MODE_AUTO)
+ .setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO)
+ .setFaceDetectMode(ANDROID_STATISTICS_FACE_DETECT_MODE_OFF)
+ .setFlashMode(ANDROID_FLASH_MODE_OFF)
+ .build();
+ if (metadata == nullptr) {
+ ALOGE("%s: Failed to construct metadata for default request type %s",
+ __func__, toString(type).c_str());
+ return CameraMetadata();
+ } else {
+ ALOGV("%s: Successfully created metadata for request type %s", __func__,
+ toString(type).c_str());
+ }
+ return *metadata;
}
HalStream getHalStream(const Stream& stream) {
@@ -272,12 +303,22 @@
RequestTemplate in_type, CameraMetadata* _aidl_return) {
ALOGV("%s: type %d", __func__, static_cast<int32_t>(in_type));
+ std::shared_ptr<VirtualCameraDevice> camera = mCameraDevice.lock();
+ if (camera == nullptr) {
+ ALOGW(
+ "%s: constructDefaultRequestSettings called on already unregistered "
+ "camera",
+ __func__);
+ return cameraStatus(Status::CAMERA_DISCONNECTED);
+ }
+
switch (in_type) {
case RequestTemplate::PREVIEW:
case RequestTemplate::STILL_CAPTURE:
case RequestTemplate::VIDEO_RECORD:
case RequestTemplate::VIDEO_SNAPSHOT: {
- *_aidl_return = createDefaultRequestSettings(in_type);
+ *_aidl_return =
+ createDefaultRequestSettings(in_type, camera->getInputConfigs());
return ndk::ScopedAStatus::ok();
}
case RequestTemplate::MANUAL:
diff --git a/services/camera/virtualcamera/util/MetadataBuilder.cc b/services/camera/virtualcamera/util/MetadataBuilder.cc
index b30f2b5..db5a5dd 100644
--- a/services/camera/virtualcamera/util/MetadataBuilder.cc
+++ b/services/camera/virtualcamera/util/MetadataBuilder.cc
@@ -51,12 +51,17 @@
return to;
}
+template <typename To, typename From>
+std::vector<To> asVectorOf(const From from) {
+ return std::vector<To>({static_cast<To>(from)});
+}
+
} // namespace
MetadataBuilder& MetadataBuilder::setSupportedHardwareLevel(
camera_metadata_enum_android_info_supported_hardware_level_t hwLevel) {
mEntryMap[ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL] =
- std::vector<uint8_t>({static_cast<uint8_t>(hwLevel)});
+ asVectorOf<uint8_t>(hwLevel);
return *this;
}
@@ -64,14 +69,25 @@
const uint8_t metadataVal = flashAvailable
? ANDROID_FLASH_INFO_AVAILABLE_TRUE
: ANDROID_FLASH_INFO_AVAILABLE_FALSE;
- mEntryMap[ANDROID_FLASH_INFO_AVAILABLE] = std::vector<uint8_t>({metadataVal});
+ mEntryMap[ANDROID_FLASH_INFO_AVAILABLE] = asVectorOf<uint8_t>(metadataVal);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setFlashState(
+ const camera_metadata_enum_android_flash_state_t flashState) {
+ mEntryMap[ANDROID_FLASH_STATE] = asVectorOf<uint8_t>(flashState);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setFlashMode(
+ const camera_metadata_enum_android_flash_mode_t flashMode) {
+ mEntryMap[ANDROID_FLASH_MODE] = asVectorOf<uint8_t>(flashMode);
return *this;
}
MetadataBuilder& MetadataBuilder::setLensFacing(
camera_metadata_enum_android_lens_facing lensFacing) {
- mEntryMap[ANDROID_LENS_FACING] =
- std::vector<uint8_t>({static_cast<uint8_t>(lensFacing)});
+ mEntryMap[ANDROID_LENS_FACING] = asVectorOf<uint8_t>(lensFacing);
return *this;
}
@@ -79,20 +95,23 @@
const camera_metadata_enum_android_sensor_readout_timestamp_t
sensorReadoutTimestamp) {
mEntryMap[ANDROID_SENSOR_READOUT_TIMESTAMP] =
- std::vector<uint8_t>({static_cast<uint8_t>(sensorReadoutTimestamp)});
+ asVectorOf<uint8_t>(sensorReadoutTimestamp);
return *this;
}
-MetadataBuilder& MetadataBuilder::setFocalLength(float focalLength) {
- std::vector<float> focalLengths({focalLength});
- mEntryMap[ANDROID_LENS_FOCAL_LENGTH] = focalLengths;
+MetadataBuilder& MetadataBuilder::setAvailableFocalLengths(
+ const std::vector<float>& focalLengths) {
mEntryMap[ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS] = focalLengths;
return *this;
}
+MetadataBuilder& MetadataBuilder::setFocalLength(float focalLength) {
+ mEntryMap[ANDROID_LENS_FOCAL_LENGTH] = asVectorOf<float>(focalLength);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setSensorOrientation(int32_t sensorOrientation) {
- mEntryMap[ANDROID_SENSOR_ORIENTATION] =
- std::vector<int32_t>({sensorOrientation});
+ mEntryMap[ANDROID_SENSOR_ORIENTATION] = asVectorOf<int32_t>(sensorOrientation);
return *this;
}
@@ -100,14 +119,13 @@
const camera_metadata_enum_android_sensor_info_timestamp_source_t
timestampSource) {
mEntryMap[ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE] =
- std::vector<uint8_t>({static_cast<uint8_t>(timestampSource)});
+ asVectorOf<uint8_t>(timestampSource);
return *this;
}
MetadataBuilder& MetadataBuilder::setSensorTimestamp(
std::chrono::nanoseconds timestamp) {
- mEntryMap[ANDROID_SENSOR_TIMESTAMP] =
- std::vector<int64_t>({timestamp.count()});
+ mEntryMap[ANDROID_SENSOR_TIMESTAMP] = asVectorOf<int64_t>(timestamp.count());
return *this;
}
@@ -119,6 +137,14 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setFaceDetectMode(
+ const camera_metadata_enum_android_statistics_face_detect_mode_t
+ faceDetectMode) {
+ mEntryMap[ANDROID_STATISTICS_FACE_DETECT_MODE] =
+ asVectorOf<uint8_t>(faceDetectMode);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAvailableModes(
const std::vector<camera_metadata_enum_android_control_mode_t>&
availableModes) {
@@ -127,6 +153,12 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlMode(
+ const camera_metadata_enum_android_control_mode_t mode) {
+ mEntryMap[ANDROID_CONTROL_MODE] = asVectorOf<uint8_t>(mode);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAvailableSceneModes(
const std::vector<camera_metadata_enum_android_control_scene_mode>&
availableSceneModes) {
@@ -153,18 +185,55 @@
MetadataBuilder& MetadataBuilder::setControlAfMode(
const camera_metadata_enum_android_control_af_mode_t mode) {
- mEntryMap[ANDROID_CONTROL_AF_MODE] =
- std::vector<uint8_t>({static_cast<uint8_t>(mode)});
+ mEntryMap[ANDROID_CONTROL_AF_MODE] = asVectorOf<uint8_t>(mode);
return *this;
}
-MetadataBuilder& MetadataBuilder::setControlAeAvailableFpsRange(
+// See ANDROID_CONTROL_AF_TRIGGER_MODE in CameraMetadataTag.aidl.
+MetadataBuilder& MetadataBuilder::setControlAfTrigger(
+ const camera_metadata_enum_android_control_af_trigger_t trigger) {
+ mEntryMap[ANDROID_CONTROL_AF_TRIGGER] = asVectorOf<uint8_t>(trigger);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setControlAeAvailableFpsRanges(
+ const std::vector<FpsRange>& fpsRanges) {
+ std::vector<int32_t> ranges;
+ ranges.resize(2 * fpsRanges.size());
+ for (const FpsRange fpsRange : fpsRanges) {
+ ranges.push_back(fpsRange.minFps);
+ ranges.push_back(fpsRange.maxFps);
+ }
+ mEntryMap[ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES] = std::move(ranges);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setControlAeTargetFpsRange(
const int32_t minFps, const int32_t maxFps) {
- mEntryMap[ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES] =
+ mEntryMap[ANDROID_CONTROL_AE_TARGET_FPS_RANGE] =
std::vector<int32_t>({minFps, maxFps});
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAeMode(
+ camera_metadata_enum_android_control_ae_mode_t mode) {
+ mEntryMap[ANDROID_CONTROL_AE_MODE] = asVectorOf<uint8_t>(mode);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setControlAeAvailableModes(
+ const std::vector<camera_metadata_enum_android_control_ae_mode_t>& modes) {
+ mEntryMap[ANDROID_CONTROL_AE_AVAILABLE_MODES] = convertTo<uint8_t>(modes);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setControlAePrecaptureTrigger(
+ const camera_metadata_enum_android_control_ae_precapture_trigger_t trigger) {
+ mEntryMap[ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER] =
+ asVectorOf<uint8_t>(trigger);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlMaxRegions(int32_t maxAeRegions,
int32_t maxAwbRegions,
int32_t maxAfRegions) {
@@ -179,6 +248,12 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAwbMode(
+ const camera_metadata_enum_android_control_awb_mode awbMode) {
+ mEntryMap[ANDROID_CONTROL_AWB_MODE] = asVectorOf<uint8_t>(awbMode);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAwbLockAvailable(
const bool awbLockAvailable) {
const uint8_t lockAvailable = awbLockAvailable
@@ -189,13 +264,29 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAeAvailableAntibandingModes(
+ const std::vector<camera_metadata_enum_android_control_ae_antibanding_mode_t>&
+ antibandingModes) {
+ mEntryMap[ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES] =
+ convertTo<uint8_t>(antibandingModes);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setControlAeAntibandingMode(
+ const camera_metadata_enum_android_control_ae_antibanding_mode_t
+ antibandingMode) {
+ mEntryMap[ANDROID_CONTROL_AE_ANTIBANDING_MODE] =
+ asVectorOf<uint8_t>(antibandingMode);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAeLockAvailable(
const bool aeLockAvailable) {
const uint8_t lockAvailable = aeLockAvailable
? ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE
: ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
mEntryMap[ANDROID_CONTROL_AE_LOCK_AVAILABLE] =
- std::vector<uint8_t>({lockAvailable});
+ asVectorOf<uint8_t>(lockAvailable);
return *this;
}
@@ -246,13 +337,12 @@
MetadataBuilder& MetadataBuilder::setControlCaptureIntent(
const camera_metadata_enum_android_control_capture_intent_t intent) {
- mEntryMap[ANDROID_CONTROL_CAPTURE_INTENT] =
- std::vector<uint8_t>({static_cast<uint8_t>(intent)});
+ mEntryMap[ANDROID_CONTROL_CAPTURE_INTENT] = asVectorOf<uint8_t>(intent);
return *this;
}
MetadataBuilder& MetadataBuilder::setMaxJpegSize(const int32_t size) {
- mEntryMap[ANDROID_JPEG_MAX_SIZE] = std::vector<int32_t>({size});
+ mEntryMap[ANDROID_JPEG_MAX_SIZE] = asVectorOf<int32_t>(size);
return *this;
}
@@ -264,7 +354,7 @@
sizes.push_back(resolution.width);
sizes.push_back(resolution.height);
}
- mEntryMap[ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES] = sizes;
+ mEntryMap[ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES] = std::move(sizes);
return *this;
}
@@ -278,8 +368,7 @@
MetadataBuilder& MetadataBuilder::setSyncMaxLatency(
camera_metadata_enum_android_sync_max_latency latency) {
- mEntryMap[ANDROID_SYNC_MAX_LATENCY] =
- std::vector<int32_t>({static_cast<int32_t>(latency)});
+ mEntryMap[ANDROID_SYNC_MAX_LATENCY] = asVectorOf<int32_t>(latency);
return *this;
}
@@ -319,17 +408,18 @@
}
mEntryMap[ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS] =
- metadataStreamConfigs;
+ std::move(metadataStreamConfigs);
mEntryMap[ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS] =
- metadataMinFrameDurations;
- mEntryMap[ANDROID_SCALER_AVAILABLE_STALL_DURATIONS] = metadataStallDurations;
+ std::move(metadataMinFrameDurations);
+ mEntryMap[ANDROID_SCALER_AVAILABLE_STALL_DURATIONS] =
+ std::move(metadataStallDurations);
return *this;
}
MetadataBuilder& MetadataBuilder::setAvailableMaxDigitalZoom(const float maxZoom) {
mEntryMap[ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM] =
- std::vector<float>({maxZoom});
+ asVectorOf<float>(maxZoom);
return *this;
}
@@ -370,7 +460,14 @@
MetadataBuilder& MetadataBuilder::setControlAeCompensationStep(
const camera_metadata_rational step) {
mEntryMap[ANDROID_CONTROL_AE_COMPENSATION_STEP] =
- std::vector<camera_metadata_rational>({step});
+ asVectorOf<camera_metadata_rational>(step);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setControlAeExposureCompensation(
+ const int32_t exposureCompensation) {
+ mEntryMap[ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION] =
+ asVectorOf<int32_t>(exposureCompensation);
return *this;
}
diff --git a/services/camera/virtualcamera/util/MetadataBuilder.h b/services/camera/virtualcamera/util/MetadataBuilder.h
index 71832d9..fdc35fd 100644
--- a/services/camera/virtualcamera/util/MetadataBuilder.h
+++ b/services/camera/virtualcamera/util/MetadataBuilder.h
@@ -59,6 +59,15 @@
int32_t weight = 0;
};
+ struct FpsRange {
+ int32_t minFps;
+ int32_t maxFps;
+
+ bool operator<(const FpsRange& other) const {
+ return std::tuple(minFps, maxFps) < std::tuple(other.minFps, other.maxFps);
+ }
+ };
+
MetadataBuilder() = default;
~MetadataBuilder() = default;
@@ -70,6 +79,14 @@
// See ANDROID_FLASH_INFO_AVAILABLE in CameraMetadataTag.aidl.
MetadataBuilder& setFlashAvailable(bool flashAvailable);
+ // See FLASH_STATE in CaptureResult.java.
+ MetadataBuilder& setFlashState(
+ camera_metadata_enum_android_flash_state_t flashState);
+
+ // See FLASH_MODE in CaptureRequest.java.
+ MetadataBuilder& setFlashMode(
+ camera_metadata_enum_android_flash_mode_t flashMode);
+
// See ANDROID_LENS_FACING in CameraMetadataTag.aidl.
MetadataBuilder& setLensFacing(
camera_metadata_enum_android_lens_facing lensFacing);
@@ -79,8 +96,10 @@
camera_metadata_enum_android_sensor_readout_timestamp_t
sensorReadoutTimestamp);
- // See ANDROID_LENS_FOCAL_LENGTH and ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS
- // in CameraMetadataTag.aidl.
+ // See ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS in CameraMetadataTag.aidl.
+ MetadataBuilder& setAvailableFocalLengths(const std::vector<float>& focalLengths);
+
+ // See ANDROID_LENS_FOCAL_LENGTH in CameraMetadataTag.aidl.
MetadataBuilder& setFocalLength(float focalLength);
// See ANDROID_SENSOR_ORIENTATION in CameraMetadataTag.aidl.
@@ -110,6 +129,10 @@
const std::vector<camera_metadata_enum_android_statistics_face_detect_mode_t>&
faceDetectMode);
+ // See ANDROID_STATISTICS_FACE_DETECT_MODE in CaptureRequest.java.
+ MetadataBuilder& setFaceDetectMode(
+ camera_metadata_enum_android_statistics_face_detect_mode_t faceDetectMode);
+
// Sets available stream configurations along with corresponding minimal frame
// durations (corresponding to max fps) and stall durations.
//
@@ -124,6 +147,10 @@
const std::vector<camera_metadata_enum_android_control_mode_t>&
availableModes);
+ // See ANDROID_CONTROL_MODE in CaptureRequest.java.
+ MetadataBuilder& setControlMode(
+ camera_metadata_enum_android_control_mode_t mode);
+
// See ANDROID_CONTROL_AVAILABLE_SCENE_MODES in CameraMetadataTag.aidl.
MetadataBuilder& setControlAvailableSceneModes(
const std::vector<camera_metadata_enum_android_control_scene_mode>&
@@ -134,12 +161,36 @@
const std::vector<camera_metadata_enum_android_control_effect_mode>&
availableEffects);
+ // See CONTROL_AE_AVAILABLE_ANTIBANDING_MODES in CameraCharacteristics.java.
+ MetadataBuilder& setControlAeAvailableAntibandingModes(
+ const std::vector<camera_metadata_enum_android_control_ae_antibanding_mode_t>&
+ antibandingModes);
+
+ // See CONTROL_AE_ANTIBANDING_MODE in CaptureRequest.java.
+ MetadataBuilder& setControlAeAntibandingMode(
+ camera_metadata_enum_android_control_ae_antibanding_mode_t antibandingMode);
+
// See ANDROID_CONTROL_AE_COMPENSATION_RANGE in CameraMetadataTag.aidl.
MetadataBuilder& setControlAeCompensationRange(int32_t min, int32_t max);
// See ANDROID_CONTROL_AE_COMPENSATION_STEP in CameraMetadataTag.aidl.
MetadataBuilder& setControlAeCompensationStep(camera_metadata_rational step);
+ // See ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION in CameraMetadataTag.aidl.
+ MetadataBuilder& setControlAeExposureCompensation(int32_t exposureCompensation);
+
+ // See ANDROID_CONTROL_AE_AVAILABLE_MODES in CameraCharacteristics.java.
+ MetadataBuilder& setControlAeAvailableModes(
+ const std::vector<camera_metadata_enum_android_control_ae_mode_t>& modes);
+
+ // See ANDROID_CONTROL_AE_MODE in CaptureRequest.java.
+ MetadataBuilder& setControlAeMode(
+ camera_metadata_enum_android_control_ae_mode_t step);
+
+ // See ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER in CaptureRequest.java.
+ MetadataBuilder& setControlAePrecaptureTrigger(
+ camera_metadata_enum_android_control_ae_precapture_trigger_t trigger);
+
// See ANDROID_CONTROL_AF_AVAILABLE_MODES in CameraMetadataTag.aidl.
MetadataBuilder& setControlAfAvailableModes(
const std::vector<camera_metadata_enum_android_control_af_mode_t>&
@@ -149,8 +200,16 @@
MetadataBuilder& setControlAfMode(
const camera_metadata_enum_android_control_af_mode_t mode);
+ // See ANDROID_CONTROL_AF_TRIGGER_MODE in CameraMetadataTag.aidl.
+ MetadataBuilder& setControlAfTrigger(
+ const camera_metadata_enum_android_control_af_trigger_t trigger);
+
// See ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES in CameraMetadataTag.aidl.
- MetadataBuilder& setControlAeAvailableFpsRange(int32_t min, int32_t max);
+ MetadataBuilder& setControlAeAvailableFpsRanges(
+ const std::vector<FpsRange>& fpsRanges);
+
+ // See ANDROID_CONTROL_AE_TARGET_FPS_RANGE in CaptureRequest.java.
+ MetadataBuilder& setControlAeTargetFpsRange(int32_t min, int32_t max);
// See ANDROID_CONTROL_CAPTURE_INTENT in CameraMetadataTag.aidl.
MetadataBuilder& setControlCaptureIntent(
@@ -165,6 +224,10 @@
MetadataBuilder& setControlAvailableAwbModes(
const std::vector<camera_metadata_enum_android_control_awb_mode>& awbModes);
+ // See ANDROID_CONTROL_AWB_AVAILABLE_MODE in CaptureRequest.java.
+ MetadataBuilder& setControlAwbMode(
+ camera_metadata_enum_android_control_awb_mode awb);
+
// See CONTROL_AWB_LOCK_AVAILABLE in CameraMetadataTag.aidl.
MetadataBuilder& setControlAwbLockAvailable(bool awbLockAvailable);
diff --git a/services/mediaresourcemanager/ResourceManagerMetrics.cpp b/services/mediaresourcemanager/ResourceManagerMetrics.cpp
index af85772..d24a3c9 100644
--- a/services/mediaresourcemanager/ResourceManagerMetrics.cpp
+++ b/services/mediaresourcemanager/ResourceManagerMetrics.cpp
@@ -43,6 +43,28 @@
MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
using stats::media_metrics::\
MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
+using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_UNSPECIFIED;
+using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_AUDIO;
+using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_VIDEO;
+using stats::media_metrics::MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_IMAGE;
+
+// Map MediaResourceSubType to stats::media_metrics::CodecType
+inline int32_t getMetricsCodecType(MediaResourceSubType codecType) {
+ switch (codecType) {
+ case MediaResourceSubType::kHwAudioCodec:
+ case MediaResourceSubType::kSwAudioCodec:
+ return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_AUDIO;
+ case MediaResourceSubType::kHwVideoCodec:
+ case MediaResourceSubType::kSwVideoCodec:
+ return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_VIDEO;
+ case MediaResourceSubType::kHwImageCodec:
+ case MediaResourceSubType::kSwImageCodec:
+ return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_IMAGE;
+ case MediaResourceSubType::kUnspecifiedSubType:
+ return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_UNSPECIFIED;
+ }
+ return MEDIA_CODEC_STARTED__CODEC_TYPE__CODEC_TYPE_UNSPECIFIED;
+}
inline const char* getCodecType(MediaResourceSubType codecType) {
switch (codecType) {
@@ -229,7 +251,7 @@
clientConfig.clientInfo.uid,
clientConfig.id,
clientConfig.clientInfo.name.c_str(),
- static_cast<int32_t>(clientConfig.codecType),
+ getMetricsCodecType(clientConfig.codecType),
clientConfig.isEncoder,
isHardwareCodec(clientConfig.codecType),
clientConfig.width, clientConfig.height,
@@ -311,7 +333,7 @@
clientConfig.clientInfo.uid,
clientConfig.id,
clientConfig.clientInfo.name.c_str(),
- static_cast<int32_t>(clientConfig.codecType),
+ getMetricsCodecType(clientConfig.codecType),
clientConfig.isEncoder,
isHardwareCodec(clientConfig.codecType),
clientConfig.width, clientConfig.height,
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 6b48075..5b4fca9 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -37,6 +37,8 @@
#include "AAudioServiceEndpointPlay.h"
#include "AAudioServiceEndpointMMAP.h"
+#include <com_android_media_aaudio.h>
+
#define AAUDIO_BUFFER_CAPACITY_MIN (4 * 512)
#define AAUDIO_SAMPLE_RATE_DEFAULT 48000
@@ -148,9 +150,15 @@
// Try other formats if the config from APM is the same as our current config.
// Some HALs may report its format support incorrectly.
- if ((previousConfig.format == config.format) &&
- (previousConfig.sample_rate == config.sample_rate)) {
- config.format = getNextFormatToTry(config.format);
+ if (previousConfig.format == config.format) {
+ if (previousConfig.sample_rate == config.sample_rate) {
+ config.format = getNextFormatToTry(config.format);
+ } else if (!com::android::media::aaudio::sample_rate_conversion()) {
+ ALOGI("%s() - AAudio SRC feature not enabled, different rates! %d != %d",
+ __func__, previousConfig.sample_rate, config.sample_rate);
+ result = AAUDIO_ERROR_INVALID_RATE;
+ break;
+ }
}
ALOGD("%s() %#x %d failed, perhaps due to format or sample rate. Try again with %#x %d",
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 79d0c90..dc70c79 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -640,7 +640,7 @@
int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
if (count != 1) {
ALOGW("%s(): Queue full. Did client stop? Suspending stream. what = %u, %s",
- __func__, command->what, getTypeText());
+ __func__, static_cast<unsigned>(command->what), getTypeText());
setSuspended(true);
return AAUDIO_ERROR_WOULD_BLOCK;
} else {
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 9fe06b7..12ce17f 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -97,6 +97,7 @@
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
"packagemanager_aidl-cpp",
+ "com.android.media.aaudio-aconfig-cc",
],
static_libs: [
diff --git a/services/oboeservice/fuzzer/Android.bp b/services/oboeservice/fuzzer/Android.bp
index 0230935..c130b12 100644
--- a/services/oboeservice/fuzzer/Android.bp
+++ b/services/oboeservice/fuzzer/Android.bp
@@ -51,6 +51,7 @@
"aaudio-aidl-cpp",
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "com.android.media.aaudio-aconfig-cc",
],
static_libs: [
"libaaudioservice",