diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index c6f5beed3e..ab96c8ee6b 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -2287,12 +2287,11 @@ typedef enum acamera_metadata_tag { *

When low light boost is enabled by setting the AE mode to * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY', it can dynamically apply a low light * boost when the light level threshold is exceeded.

- *

This field is present in the CaptureResult when the AE mode is set to - * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY'. Otherwise, the field is not present.

*

This state indicates when low light boost is 'ACTIVE' and applied. Similarly, it can * indicate when it is not being applied by returning 'INACTIVE'.

*

This key will be absent from the CaptureResult if AE mode is not set to * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY.

+ *

The default value will always be 'INACTIVE'.

*/ ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE = // byte (acamera_metadata_enum_android_control_low_light_boost_state_t) ACAMERA_CONTROL_START + 59, @@ -8311,11 +8310,8 @@ typedef enum acamera_metadata_enum_acamera_control_ae_mode { *

If the session configuration is not supported, the AE mode reported in the * CaptureResult will be 'ON' instead of 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY'.

*

When this AE mode is enabled, the CaptureResult field - * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE will be present and not null. Otherwise, the - * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE field will not be present in the CaptureResult.

- *

The application can observe the CaptureResult field - * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE to determine when low light boost is 'ACTIVE' or - * 'INACTIVE'.

+ * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE will indicate when low light boost is 'ACTIVE' + * or 'INACTIVE'. By default ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE will be 'INACTIVE'.

*

The low light boost is 'ACTIVE' once the scene lighting condition is less than the * upper bound lux value defined by ACAMERA_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE. * This mode will be 'INACTIVE' once the scene lighting condition is greater than the diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h index e26290fc94..5a2ab27118 100644 --- a/include/media/Interpolator.h +++ b/include/media/Interpolator.h @@ -289,7 +289,7 @@ class Interpolator : public std::map { std::string toString() const { std::stringstream ss; - ss << "Interpolator{mInterpolatorType=" << static_cast(mInterpolatorType); + ss << "Interpolator{mInterpolatorType=" << media::toString(mInterpolatorType); ss << ", mFirstSlope=" << mFirstSlope; ss << ", mLastSlope=" << mLastSlope; ss << ", {"; diff --git a/include/media/VolumeShaper.h b/include/media/VolumeShaper.h index 6208db313e..26da3634c8 100644 --- a/include/media/VolumeShaper.h +++ b/include/media/VolumeShaper.h @@ -116,6 +116,16 @@ class VolumeShaper { TYPE_SCALE, }; + static std::string toString(Type type) { + switch (type) { + case TYPE_ID: return "TYPE_ID"; + case TYPE_SCALE: return "TYPE_SCALE"; + default: + return std::string("Unknown Type: ") + .append(std::to_string(static_cast(type))); + } + } + // Must match with VolumeShaper.java in frameworks/base. enum OptionFlag : int32_t { OPTION_FLAG_NONE = 0, @@ -125,6 +135,22 @@ class VolumeShaper { OPTION_FLAG_ALL = (OPTION_FLAG_VOLUME_IN_DBFS | OPTION_FLAG_CLOCK_TIME), }; + static std::string toString(OptionFlag flag) { + std::string s; + for (const auto& flagPair : std::initializer_list>{ + {OPTION_FLAG_VOLUME_IN_DBFS, "OPTION_FLAG_VOLUME_IN_DBFS"}, + {OPTION_FLAG_CLOCK_TIME, "OPTION_FLAG_CLOCK_TIME"}, + }) { + if (flag & flagPair.first) { + if (!s.empty()) { + s.append("|"); + } + s.append(flagPair.second); + } + } + return s; + } + // Bring from base class; must match with VolumeShaper.java in frameworks/base. using InterpolatorType = Interpolator::InterpolatorType; @@ -329,10 +355,10 @@ class VolumeShaper { // Returns a string for debug printing. std::string toString() const { std::stringstream ss; - ss << "VolumeShaper::Configuration{mType=" << static_cast(mType); + ss << "VolumeShaper::Configuration{mType=" << toString(mType); ss << ", mId=" << mId; if (mType != TYPE_ID) { - ss << ", mOptionFlags=" << static_cast(mOptionFlags); + ss << ", mOptionFlags=" << toString(mOptionFlags); ss << ", mDurationMs=" << mDurationMs; ss << ", " << Interpolator::toString().c_str(); } @@ -414,6 +440,25 @@ class VolumeShaper { | FLAG_CREATE_IF_NECESSARY), }; + static std::string toString(Flag flag) { + std::string s; + for (const auto& flagPair : std::initializer_list>{ + {FLAG_REVERSE, "FLAG_REVERSE"}, + {FLAG_TERMINATE, "FLAG_TERMINATE"}, + {FLAG_JOIN, "FLAG_JOIN"}, + {FLAG_DELAY, "FLAG_DELAY"}, + {FLAG_CREATE_IF_NECESSARY, "FLAG_CREATE_IF_NECESSARY"}, + }) { + if (flag & flagPair.first) { + if (!s.empty()) { + s.append("|"); + } + s.append(flagPair.second); + } + } + return s; + } + Operation() : Operation(FLAG_NONE, -1 /* replaceId */) { } @@ -508,7 +553,7 @@ class VolumeShaper { std::string toString() const { std::stringstream ss; - ss << "VolumeShaper::Operation{mFlags=" << static_cast(mFlags) ; + ss << "VolumeShaper::Operation{mFlags=" << toString(mFlags); ss << ", mReplaceId=" << mReplaceId; ss << ", mXOffset=" << mXOffset; ss << "}"; diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig index 4c3e25a428..c3ae59c880 100644 --- a/media/audio/aconfig/audio.aconfig +++ b/media/audio/aconfig/audio.aconfig @@ -59,6 +59,13 @@ flag { bug: "307588546" } +flag { + name: "music_fx_edge_to_edge" + namespace: "media_audio" + description: "Enable Edge-to-edge feature for MusicFx and handle insets" + bug: "336204940" +} + flag { name: "port_to_piid_simplification" namespace: "media_audio" diff --git a/media/audio/aconfig/audioserver.aconfig b/media/audio/aconfig/audioserver.aconfig index 94b60e2034..5e701688b6 100644 --- a/media/audio/aconfig/audioserver.aconfig +++ b/media/audio/aconfig/audioserver.aconfig @@ -14,6 +14,13 @@ flag { bug: "294525897" } +flag { + name: "effect_chain_callback_improve" + namespace: "media_audio" + description: "Improve effect chain callback mutex logic." + bug: "342413767" +} + flag { name: "fdtostring_timeout_fix" namespace: "media_audio" diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp index 9a92f773d9..694be5ab7d 100644 --- a/media/audioaidlconversion/AidlConversionCppNdk.cpp +++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp @@ -1069,13 +1069,6 @@ ::android::status_t aidl2legacy_AudioDevice_audio_device( if (mac.size() != 6) return BAD_VALUE; snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - // special case for anonymized mac address: - // change anonymized bytes back from FD:FF:FF:FF to XX:XX:XX:XX - std::string address(addressBuffer); - if (address.compare(0, strlen("FD:FF:FF:FF"), "FD:FF:FF:FF") == 0) { - address.replace(0, strlen("FD:FF:FF:FF"), "XX:XX:XX:XX"); - } - strcpy(addressBuffer, address.c_str()); } break; case Tag::ipv4: { const std::vector& ipv4 = aidl.address.get(); @@ -1136,20 +1129,11 @@ legacy2aidl_audio_device_AudioDevice( if (!legacyAddress.empty()) { switch (suggestDeviceAddressTag(aidl.type)) { case Tag::mac: { - // special case for anonymized mac address: - // change anonymized bytes so that they can be scanned as HEX bytes - // Use '01' for LSB bits 0 and 1 as Bluetooth MAC addresses are never multicast - // and universaly administered - std::string address = legacyAddress; - if (address.compare(0, strlen("XX:XX:XX:XX"), "XX:XX:XX:XX") == 0) { - address.replace(0, strlen("XX:XX:XX:XX"), "FD:FF:FF:FF"); - } - std::vector mac(6); - int status = sscanf(address.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", + int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); if (status != mac.size()) { - ALOGE("%s: malformed MAC address: \"%s\"", __func__, address.c_str()); + ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str()); return unexpected(BAD_VALUE); } aidl.address = AudioDeviceAddress::make(std::move(mac)); diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp index ef4930842c..659ad83dc7 100644 --- a/media/codec2/hal/aidl/ComponentStore.cpp +++ b/media/codec2/hal/aidl/ComponentStore.cpp @@ -36,7 +36,7 @@ #include #include -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules #include #include #include @@ -51,7 +51,7 @@ namespace media { namespace c2 { namespace utils { -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules using ::android::DefaultFilterPlugin; using ::android::FilterWrapper; #endif @@ -144,7 +144,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) ::android::SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -173,8 +181,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -189,7 +196,7 @@ std::shared_ptr ComponentStore::getParameterCache() const { return mParameterCache; } -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules // static std::shared_ptr ComponentStore::GetFilterWrapper() { constexpr const char kPluginPath[] = "libc2filterplugin.so"; @@ -220,7 +227,7 @@ ScopedAStatus ComponentStore::createComponent( mStore->createComponent(name, &c2component); if (status == C2_OK) { -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules c2component = GetFilterWrapper()->maybeWrapComponent(c2component); #endif onInterfaceLoaded(c2component->intf()); @@ -254,7 +261,7 @@ ScopedAStatus ComponentStore::createInterface( std::shared_ptr c2interface; c2_status_t res = mStore->createInterface(name, &c2interface); if (res == C2_OK) { -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface); #endif onInterfaceLoaded(c2interface); @@ -314,8 +321,7 @@ ScopedAStatus ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -368,6 +374,16 @@ ScopedAStatus ComponentStore::getConfigurable( return ScopedAStatus::ok(); } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h index 0698b0f85c..077ebc6316 100644 --- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h +++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h @@ -115,7 +115,7 @@ struct ComponentStore : public BnComponentStore { c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; @@ -132,6 +132,9 @@ struct ComponentStore : public BnComponentStore { mutable std::mutex mComponentRosterMutex; std::map mComponentRoster; + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + // Called whenever Component is created. void reportComponentBirth(Component* component); // Called only from the destructor of Component. diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp index 1c0d5b0b98..77230de3da 100644 --- a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp @@ -139,7 +139,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -168,8 +176,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -307,8 +314,7 @@ Return ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -354,6 +360,16 @@ Return> ComponentStore::getConfigurable() { return mConfigurable; } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h index 27e2a05f3a..56f1faa9fe 100644 --- a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h +++ b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h @@ -114,9 +114,12 @@ struct ComponentStore : public IComponentStore { // Does bookkeeping for an interface that has been loaded. void onInterfaceLoaded(const std::shared_ptr &intf); + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; diff --git a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp index d47abdd040..e672eea38a 100644 --- a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp @@ -139,7 +139,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -168,8 +176,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -306,8 +313,7 @@ Return ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -389,6 +395,16 @@ Return ComponentStore::createComponent_1_1( return Void(); } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h index f6daee74b5..cde7b4e00f 100644 --- a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h +++ b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h @@ -122,9 +122,12 @@ struct ComponentStore : public IComponentStore { // Does bookkeeping for an interface that has been loaded. void onInterfaceLoaded(const std::shared_ptr &intf); + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; diff --git a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp index 9fac5d5268..f918808b41 100644 --- a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp @@ -139,7 +139,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -168,8 +176,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -306,8 +313,7 @@ Return ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -425,6 +431,16 @@ Return ComponentStore::createComponent_1_2( return Void(); } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h index e95a651756..4cd42d10b8 100644 --- a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h +++ b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h @@ -129,9 +129,12 @@ struct ComponentStore : public IComponentStore { // Does bookkeeping for an interface that has been loaded. void onInterfaceLoaded(const std::shared_ptr &intf); + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; diff --git a/media/codec2/hal/plugin/FilterWrapper.cpp b/media/codec2/hal/plugin/FilterWrapper.cpp index b92615034a..ab6e3eb43f 100644 --- a/media/codec2/hal/plugin/FilterWrapper.cpp +++ b/media/codec2/hal/plugin/FilterWrapper.cpp @@ -1012,4 +1012,11 @@ c2_status_t FilterWrapper::queryParamsForPreviousComponent( return mPlugin->queryParamsForPreviousComponent(intf, params); } +std::shared_ptr FilterWrapper::getParamReflector() { + if (mInit != OK) { + return nullptr; + } + return mStore->getParamReflector(); +} + } // namespace android diff --git a/media/codec2/hal/plugin/FilterWrapperStub.cpp b/media/codec2/hal/plugin/FilterWrapperStub.cpp index 3fd54095ae..a21f6d0735 100644 --- a/media/codec2/hal/plugin/FilterWrapperStub.cpp +++ b/media/codec2/hal/plugin/FilterWrapperStub.cpp @@ -57,4 +57,8 @@ c2_status_t FilterWrapper::createBlockPool( return CreateCodec2BlockPool(allocatorParam, component, pool); } +std::shared_ptr FilterWrapper::getParamReflector() { + return nullptr; +} + } // namespace android diff --git a/media/codec2/hal/plugin/internal/FilterWrapper.h b/media/codec2/hal/plugin/internal/FilterWrapper.h index dcffb5cd30..c27901e4ff 100644 --- a/media/codec2/hal/plugin/internal/FilterWrapper.h +++ b/media/codec2/hal/plugin/internal/FilterWrapper.h @@ -104,6 +104,10 @@ class FilterWrapper : public std::enable_shared_from_this { const std::shared_ptr &intf, std::vector> *params); + /** + * Return the param reflector of the filter plugin store. + */ + std::shared_ptr getParamReflector(); private: status_t mInit; std::unique_ptr mPlugin; diff --git a/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp b/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp index b5383ad584..47412b7868 100644 --- a/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp +++ b/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp @@ -37,6 +37,19 @@ typedef C2StreamParam C2StreamColorAspectsRequestInfo; +// In practice the vendor parameters will be defined in a separate header file, +// but for the purpose of this sample, we just define it here. + +// Vendor-specific type index for filters start from this value. 0x7000 is added to +// avoid conflict with existing vendor type indices. +constexpr uint32_t kTypeIndexFilterStart = C2Param::TYPE_INDEX_VENDOR_START + 0x7000; +// Answer to the Ultimate Question of Life, the Universe, and Everything +// (Reference to The Hitchhiker's Guide to the Galaxy by Douglas Adams) +constexpr uint32_t kParamIndexVendorUltimateAnswer = kTypeIndexFilterStart + 0; +typedef C2StreamParam + C2StreamVendorUltimateAnswerInfo; +constexpr char C2_PARAMKEY_VENDOR_ULTIMATE_ANSWER[] = "ultimate-answer"; + namespace android { using namespace std::literals::chrono_literals; @@ -49,10 +62,9 @@ class SampleToneMappingFilter static const std::string NAME; static const FilterPlugin_V1::Descriptor DESCRIPTOR; - explicit Interface(c2_node_id_t id) + Interface(c2_node_id_t id, const std::shared_ptr &reflector) : mId(id), - mReflector(std::make_shared()), - mHelper(mReflector) { + mHelper(reflector) { } ~Interface() override = default; C2String getName() const override { return NAME; } @@ -126,7 +138,6 @@ class SampleToneMappingFilter } private: const c2_node_id_t mId; - std::shared_ptr mReflector; struct Helper : public C2InterfaceHelper { explicit Helper(std::shared_ptr reflector) : C2InterfaceHelper(reflector) { @@ -265,6 +276,15 @@ class SampleToneMappingFilter .withSetter(ColorAspectsRequestSetter) .build()); + addParameter( + DefineParam(mVendorUltimateAnswerInfo, C2_PARAMKEY_VENDOR_ULTIMATE_ANSWER) + .withDefault(new C2StreamVendorUltimateAnswerInfo::input(0u)) + .withFields({ + C2F(mVendorUltimateAnswerInfo, value).any(), + }) + .withSetter(VendorUltimateAnswerSetter) + .build()); + addParameter( DefineParam(mOutputColorAspectInfo, C2_PARAMKEY_COLOR_ASPECTS) .withDefault(new C2StreamColorAspectsInfo::output(0u)) @@ -336,6 +356,15 @@ class SampleToneMappingFilter return C2R::Ok(); } + static C2R VendorUltimateAnswerSetter( + bool mayBlock, + C2P &me) { + (void)mayBlock; + ALOGI("Answer to the Ultimate Question of Life, the Universe, and Everything " + "set to %d", me.v.value); + return C2R::Ok(); + } + std::shared_ptr mApiFeatures; std::shared_ptr mName; @@ -362,11 +391,13 @@ class SampleToneMappingFilter std::shared_ptr mInputColorAspectInfo; std::shared_ptr mOutputColorAspectInfo; std::shared_ptr mColorAspectRequestInfo; + + std::shared_ptr mVendorUltimateAnswerInfo; } mHelper; }; - explicit SampleToneMappingFilter(c2_node_id_t id) - : mIntf(std::make_shared(id)) { + SampleToneMappingFilter(c2_node_id_t id, const std::shared_ptr &reflector) + : mIntf(std::make_shared(id, reflector)) { } ~SampleToneMappingFilter() override { if (mProcessingThread.joinable()) { @@ -802,7 +833,10 @@ const std::string SampleToneMappingFilter::Interface::NAME = "c2.sample.tone-map // static const FilterPlugin_V1::Descriptor SampleToneMappingFilter::Interface::DESCRIPTOR = { // controlParams - { C2StreamColorAspectsRequestInfo::output::PARAM_TYPE }, + { + C2StreamColorAspectsRequestInfo::output::PARAM_TYPE, + C2StreamVendorUltimateAnswerInfo::input::PARAM_TYPE, + }, // affectedParams { C2StreamHdrStaticInfo::output::PARAM_TYPE, @@ -815,7 +849,7 @@ class SampleC2ComponentStore : public C2ComponentStore { SampleC2ComponentStore() : mReflector(std::make_shared()), mIntf(mReflector), - mFactories(CreateFactories()) { + mFactories(CreateFactories(mReflector)) { } ~SampleC2ComponentStore() = default; @@ -892,36 +926,46 @@ class SampleC2ComponentStore : public C2ComponentStore { template struct ComponentFactoryImpl : public ComponentFactory { public: - ComponentFactoryImpl(const std::shared_ptr &traits) - : ComponentFactory(traits) { + ComponentFactoryImpl( + const std::shared_ptr &traits, + const std::shared_ptr &reflector) + : ComponentFactory(traits), + mReflector(reflector) { } ~ComponentFactoryImpl() override = default; c2_status_t createComponent( c2_node_id_t id, std::shared_ptr* const component) const override { - *component = std::make_shared(id); + *component = std::make_shared(id, mReflector); return C2_OK; } c2_status_t createInterface( c2_node_id_t id, std::shared_ptr* const interface) const override { - *interface = std::make_shared(id); + *interface = std::make_shared(id, mReflector); return C2_OK; } + private: + std::shared_ptr mReflector; }; template - static void AddFactory(std::map> *factories) { - std::shared_ptr intf{new typename T::Interface(0)}; + static void AddFactory( + std::map> *factories, + const std::shared_ptr &reflector) { + std::shared_ptr intf{new typename T::Interface(0, reflector)}; std::shared_ptr traits(new (std::nothrow) C2Component::Traits); CHECK(C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) << "Failed to fill traits from interface"; - factories->emplace(traits->name, new ComponentFactoryImpl(traits)); + factories->emplace( + traits->name, + new ComponentFactoryImpl(traits, reflector)); } - static std::map> CreateFactories() { + static std::map> CreateFactories( + const std::shared_ptr &reflector) { std::map> factories; - AddFactory(&factories); + AddFactory(&factories, reflector); return factories; } diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp index 4ce95d80ea..33588257c4 100644 --- a/media/libaudioclient/AudioTrack.cpp +++ b/media/libaudioclient/AudioTrack.cpp @@ -3136,6 +3136,7 @@ VolumeShaper::Status AudioTrack::applyVolumeShaper( const sp& configuration, const sp& operation) { + const int64_t beginNs = systemTime(); AutoMutex lock(mLock); mVolumeHandler->setIdIfNecessary(configuration); media::VolumeShaperConfiguration config; @@ -3143,6 +3144,18 @@ VolumeShaper::Status AudioTrack::applyVolumeShaper( media::VolumeShaperOperation op; operation->writeToParcelable(&op); VolumeShaper::Status status; + + mediametrics::Defer defer([&] { + mediametrics::LogItem(mMetricsId) + .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_APPLYVOLUMESHAPER) + .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs)) + .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState)) + .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status) + .set(AMEDIAMETRICS_PROP_TOSTRING, configuration->toString() + .append(" ") + .append(operation->toString())) + .record(); }); + mAudioTrack->applyVolumeShaper(config, op, &status); if (status == DEAD_OBJECT) { diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp index 0be1d7e25c..7f55e48b21 100644 --- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp +++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp @@ -483,28 +483,8 @@ INSTANTIATE_TEST_SUITE_P( AudioDeviceAddress::make( std::vector{1, 2})))); -TEST(AnonymizedBluetoothAddressRoundTripTest, Legacy2Aidl2Legacy) { - const std::vector sAnonymizedAidlAddress = - std::vector{0xFD, 0xFF, 0xFF, 0xFF, 0xAB, 0xCD}; - const std::string sAnonymizedLegacyAddress = std::string("XX:XX:XX:XX:AB:CD"); - auto device = legacy2aidl_audio_device_AudioDevice(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, - sAnonymizedLegacyAddress); - ASSERT_TRUE(device.ok()); - ASSERT_EQ(AudioDeviceAddress::Tag::mac, device.value().address.getTag()); - ASSERT_EQ(sAnonymizedAidlAddress, device.value().address.get()); - - audio_devices_t legacyType; - std::string legacyAddress; - status_t status = - aidl2legacy_AudioDevice_audio_device(device.value(), &legacyType, &legacyAddress); - ASSERT_EQ(OK, status); - EXPECT_EQ(legacyType, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP); - EXPECT_EQ(sAnonymizedLegacyAddress, legacyAddress); -} - class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam { }; - TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) { const auto initial = GetParam(); auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial); diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h index 426ad15c86..e5373f36ba 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h +++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h @@ -65,10 +65,9 @@ constexpr inline std::array, MAX_NUM_PRESETS> {5, 3, -1, 3, 5}}}; /* Rock Preset */ static const std::vector kEqPresets = { - {-1, "Custom"}, {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, - {3, "Flat"}, {4, "Folk"}, {5, "Heavy Metal"}, {6, "Hip Hop"}, - {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}}; - + {-1, "Custom"}, {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, + {3, "Flat"}, {4, "Folk"}, {5, "Heavy Metal"}, {6, "Hip Hop"}, + {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}}; const std::vector kEqRanges = { MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1), diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp index 53cb1d254c..974ccf39d3 100644 --- a/media/libmediahelper/Android.bp +++ b/media/libmediahelper/Android.bp @@ -68,9 +68,6 @@ cc_defaults { cc_library { name: "libmedia_helper", vendor_available: true, - vndk: { - enabled: true, - }, defaults: ["libmedia_helper_defaults"], min_sdk_version: "29", } @@ -78,10 +75,6 @@ cc_library { cc_library { name: "libmedia_helper_ext", vendor: true, - vndk: { - enabled: true, - extends: "libmedia_helper", - }, defaults: ["libmedia_helper_defaults"], host_supported: false, cflags: [ diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h index 26aa3755d9..e60a6784eb 100644 --- a/media/libmediametrics/include/MediaMetricsConstants.h +++ b/media/libmediametrics/include/MediaMetricsConstants.h @@ -213,6 +213,7 @@ // format to transport packets. // Raw byte streams are used if this // is false. +#define AMEDIAMETRICS_PROP_TOSTRING "toString" // string #define AMEDIAMETRICS_PROP_TOTALINPUTBYTES "totalInputBytes" // int32 (MIDI) #define AMEDIAMETRICS_PROP_TOTALOUTPUTBYTES "totalOutputBytes" // int32 (MIDI) #define AMEDIAMETRICS_PROP_THREADID "threadId" // int32 value io handle @@ -243,6 +244,7 @@ // Values are strings accepted for a given property. // An event is a general description, which often is a function name. +#define AMEDIAMETRICS_PROP_EVENT_VALUE_APPLYVOLUMESHAPER "applyVolumeShaper" #define AMEDIAMETRICS_PROP_EVENT_VALUE_BEGINAUDIOINTERVALGROUP "beginAudioIntervalGroup" #define AMEDIAMETRICS_PROP_EVENT_VALUE_CLOSE "close" #define AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE "create" diff --git a/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp index 652b1eed3b..15265bffb1 100644 --- a/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp +++ b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp @@ -51,6 +51,69 @@ const char dumpFile[] = "OutputDumpFile"; enum DataSourceType { HTTP, FD, STREAM, FILETYPE, SOCKET, kMaxValue = SOCKET }; +constexpr audio_flags_mask_t kAudioFlagsMasks[] = {AUDIO_FLAG_NONE, + AUDIO_FLAG_AUDIBILITY_ENFORCED, + AUDIO_FLAG_SECURE, + AUDIO_FLAG_SCO, + AUDIO_FLAG_BEACON, + AUDIO_FLAG_HW_AV_SYNC, + AUDIO_FLAG_HW_HOTWORD, + AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY, + AUDIO_FLAG_BYPASS_MUTE, + AUDIO_FLAG_LOW_LATENCY, + AUDIO_FLAG_DEEP_BUFFER, + AUDIO_FLAG_NO_MEDIA_PROJECTION, + AUDIO_FLAG_MUTE_HAPTIC, + AUDIO_FLAG_NO_SYSTEM_CAPTURE, + AUDIO_FLAG_CAPTURE_PRIVATE, + AUDIO_FLAG_CONTENT_SPATIALIZED, + AUDIO_FLAG_NEVER_SPATIALIZE, + AUDIO_FLAG_CALL_REDIRECTION}; + +constexpr audio_content_type_t kAudioContentTypes[] = { + AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_CONTENT_TYPE_SPEECH, AUDIO_CONTENT_TYPE_MUSIC, + AUDIO_CONTENT_TYPE_MOVIE, AUDIO_CONTENT_TYPE_SONIFICATION, AUDIO_CONTENT_TYPE_ULTRASOUND}; + +constexpr audio_source_t kAudioSources[] = {AUDIO_SOURCE_INVALID, + AUDIO_SOURCE_DEFAULT, + AUDIO_SOURCE_MIC, + AUDIO_SOURCE_VOICE_UPLINK, + AUDIO_SOURCE_VOICE_DOWNLINK, + AUDIO_SOURCE_VOICE_CALL, + AUDIO_SOURCE_CAMCORDER, + AUDIO_SOURCE_VOICE_RECOGNITION, + AUDIO_SOURCE_VOICE_COMMUNICATION, + AUDIO_SOURCE_REMOTE_SUBMIX, + AUDIO_SOURCE_UNPROCESSED, + AUDIO_SOURCE_VOICE_PERFORMANCE, + AUDIO_SOURCE_ECHO_REFERENCE, + AUDIO_SOURCE_FM_TUNER, + AUDIO_SOURCE_HOTWORD, + AUDIO_SOURCE_ULTRASOUND}; + +constexpr audio_usage_t kAudioUsages[] = {AUDIO_USAGE_UNKNOWN, + AUDIO_USAGE_MEDIA, + AUDIO_USAGE_VOICE_COMMUNICATION, + AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING, + AUDIO_USAGE_ALARM, + AUDIO_USAGE_NOTIFICATION, + AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED, + AUDIO_USAGE_NOTIFICATION_EVENT, + AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY, + AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, + AUDIO_USAGE_ASSISTANCE_SONIFICATION, + AUDIO_USAGE_GAME, + AUDIO_USAGE_VIRTUAL_SOURCE, + AUDIO_USAGE_ASSISTANT, + AUDIO_USAGE_CALL_ASSISTANT, + AUDIO_USAGE_EMERGENCY, + AUDIO_USAGE_SAFETY, + AUDIO_USAGE_VEHICLE_STATUS, + AUDIO_USAGE_ANNOUNCEMENT}; + constexpr PixelFormat kPixelFormat[] = { PIXEL_FORMAT_UNKNOWN, PIXEL_FORMAT_NONE, PIXEL_FORMAT_CUSTOM, PIXEL_FORMAT_TRANSLUCENT, PIXEL_FORMAT_TRANSPARENT, PIXEL_FORMAT_OPAQUE, @@ -354,7 +417,18 @@ void MediaPlayerServiceFuzzer::invokeMediaPlayer() { [&]() { mMediaPlayer->attachAuxEffect(mFdp.ConsumeIntegral()); }, [&]() { int32_t key = mFdp.PickValueInArray(kMediaParamKeys); - request.writeInt32(mFdp.ConsumeIntegral()); + request.writeInt32((audio_usage_t)mFdp.ConsumeIntegralInRange( + AUDIO_USAGE_UNKNOWN, AUDIO_USAGE_ANNOUNCEMENT) /* usage */); + request.writeInt32((audio_content_type_t)mFdp.ConsumeIntegralInRange( + AUDIO_CONTENT_TYPE_UNKNOWN, + AUDIO_CONTENT_TYPE_ULTRASOUND) /* content_type */); + request.writeInt32((audio_source_t)mFdp.ConsumeIntegralInRange( + AUDIO_SOURCE_INVALID, AUDIO_SOURCE_ULTRASOUND) /* source */); + request.writeInt32((audio_flags_mask_t)mFdp.ConsumeIntegralInRange( + AUDIO_FLAG_NONE, AUDIO_FLAG_CALL_REDIRECTION) /* flags */); + request.writeInt32(mFdp.ConsumeBool() /* hasFlattenedTag */); + request.writeString16( + String16((mFdp.ConsumeRandomLengthString()).c_str()) /* tags */); request.setDataPosition(0); mMediaPlayer->setParameter(key, request); key = mFdp.PickValueInArray(kMediaParamKeys); diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp index e01af70984..f562445a61 100644 --- a/media/libstagefright/omx/Android.bp +++ b/media/libstagefright/omx/Android.bp @@ -16,6 +16,7 @@ license { "NOTICE", ], } + cc_defaults { name: "libstagefright_omx_defaults", double_loadable: true, @@ -61,9 +62,6 @@ cc_defaults { cc_library_shared { name: "libstagefright_omx", vendor_available: true, - vndk: { - enabled: true, - }, export_shared_lib_headers: [ "libmedia_omx", @@ -106,57 +104,6 @@ cc_library_shared { }, } -cc_library_shared { - name: "libstagefright_omx_ext", - vendor: true, - vndk: { - enabled: true, - extends: "libstagefright_omx", - }, - defaults: ["libstagefright_omx_defaults"], - - export_shared_lib_headers: [ - "libmedia_omx", - "libstagefright_foundation_ext", - "libstagefright_xmlparser", - "libutils", - ], - - shared_libs: [ - "libbase", - "libbinder", - "libmedia_omx", - "libutils", - "liblog", - "libui", - "libcutils", - "libstagefright_foundation_ext", - "libstagefright_bufferqueue_helper", - "libstagefright_xmlparser", - "libdl", - "libhidlbase", - "libhidlmemory", - "libvndksupport", - "android.hardware.media.omx@1.0", - "android.hardware.graphics.bufferqueue@1.0", - ], - cflags: [ - "-Werror", - "-Wall", - "-Wno-unused-parameter", - "-Wno-documentation", - "-D__ANDROID_VNDK_EXT__", - ], - sanitize: { - misc_undefined: [ - "signed-integer-overflow", - "unsigned-integer-overflow", - ], - cfi: true, - }, - -} - cc_library_shared { name: "libstagefright_softomx", vendor_available: true, diff --git a/media/module/bufferpool/2.0/AccessorImpl.cpp b/media/module/bufferpool/2.0/AccessorImpl.cpp index 202d8030a7..b9483bfc19 100644 --- a/media/module/bufferpool/2.0/AccessorImpl.cpp +++ b/media/module/bufferpool/2.0/AccessorImpl.cpp @@ -17,6 +17,8 @@ #define LOG_TAG "BufferPoolAccessor2.0" //#define LOG_NDEBUG 0 +#include + #include #include #include @@ -147,7 +149,25 @@ static constexpr uint32_t kSeqIdVndkBit = 0; #endif static constexpr uint32_t kSeqIdMax = 0x7fffffff; -uint32_t Accessor::Impl::sSeqId = time(nullptr) & kSeqIdMax; + +Accessor::Impl::ConnectionIdGenerator::ConnectionIdGenerator() { + mSeqId = static_cast(time(nullptr) & kSeqIdMax); + mPid = static_cast(getpid()); +} + +ConnectionId Accessor::Impl::ConnectionIdGenerator::getConnectionId() { + uint32_t seq; + { + std::lock_guard l(mLock); + seq = mSeqId; + if (mSeqId == kSeqIdMax) { + mSeqId = 0; + } else { + ++mSeqId; + } + } + return (int64_t)mPid << 32 | seq | kSeqIdVndkBit; +} Accessor::Impl::Impl( const std::shared_ptr &allocator) @@ -163,13 +183,14 @@ ResultStatus Accessor::Impl::connect( uint32_t *pMsgId, const StatusDescriptor** statusDescPtr, const InvalidationDescriptor** invDescPtr) { + static ::android::base::NoDestructor sConIdGenerator; sp newConnection = new Connection(); ResultStatus status = ResultStatus::CRITICAL_ERROR; { std::lock_guard lock(mBufferPool.mMutex); if (newConnection) { int32_t pid = getpid(); - ConnectionId id = (int64_t)pid << 32 | sSeqId | kSeqIdVndkBit; + ConnectionId id = sConIdGenerator->getConnectionId(); status = mBufferPool.mObserver.open(id, statusDescPtr); if (status == ResultStatus::OK) { newConnection->initialize(accessor, id); @@ -179,11 +200,6 @@ ResultStatus Accessor::Impl::connect( mBufferPool.mConnectionIds.insert(id); mBufferPool.mInvalidationChannel.getDesc(invDescPtr); mBufferPool.mInvalidation.onConnect(id, observer); - if (sSeqId == kSeqIdMax) { - sSeqId = 0; - } else { - ++sSeqId; - } } } diff --git a/media/module/bufferpool/2.0/AccessorImpl.h b/media/module/bufferpool/2.0/AccessorImpl.h index 3d39941337..2366177135 100644 --- a/media/module/bufferpool/2.0/AccessorImpl.h +++ b/media/module/bufferpool/2.0/AccessorImpl.h @@ -77,7 +77,14 @@ class Accessor::Impl private: // ConnectionId = pid : (timestamp_created + seqId) // in order to guarantee uniqueness for each connection - static uint32_t sSeqId; + struct ConnectionIdGenerator { + int32_t mPid; + uint32_t mSeqId; + std::mutex mLock; + + ConnectionIdGenerator(); + ConnectionId getConnectionId(); + }; const std::shared_ptr mAllocator; diff --git a/media/module/bufferpool/2.0/Android.bp b/media/module/bufferpool/2.0/Android.bp index bdab103311..c40603c0e2 100644 --- a/media/module/bufferpool/2.0/Android.bp +++ b/media/module/bufferpool/2.0/Android.bp @@ -21,6 +21,9 @@ cc_defaults { export_include_dirs: [ "include", ], + header_libs: [ + "libbase_headers", + ], shared_libs: [ "libcutils", "libfmq", diff --git a/media/module/foundation/Android.bp b/media/module/foundation/Android.bp index de670c8c5f..c5526dd34e 100644 --- a/media/module/foundation/Android.bp +++ b/media/module/foundation/Android.bp @@ -126,9 +126,6 @@ cc_defaults { cc_library { name: "libstagefright_foundation", vendor_available: true, - vndk: { - enabled: true, - }, defaults: ["libstagefright_foundation_defaults"], min_sdk_version: "29", apex_available: [ @@ -152,10 +149,6 @@ cc_library { cc_library { name: "libstagefright_foundation_ext", vendor: true, - vndk: { - enabled: true, - extends: "libstagefright_foundation", - }, defaults: ["libstagefright_foundation_defaults"], host_supported: false, min_sdk_version: "29", diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp index 4b0192a22b..7bec8cf616 100644 --- a/media/utils/ServiceUtilities.cpp +++ b/media/utils/ServiceUtilities.cpp @@ -47,7 +47,6 @@ static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_A static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE"); static const String16 sModifyAudioRouting("android.permission.MODIFY_AUDIO_ROUTING"); static const String16 sCallAudioInterception("android.permission.CALL_AUDIO_INTERCEPTION"); -static const String16 sAndroidPermissionBluetoothConnect("android.permission.BLUETOOTH_CONNECT"); static String16 resolveCallingPackage(PermissionController& permissionController, const std::optional opPackageName, uid_t uid) { @@ -393,48 +392,6 @@ status_t checkIMemory(const sp& iMemory) return NO_ERROR; } -/** - * Determines if the MAC address in Bluetooth device descriptors returned by APIs of - * a native audio service (audio flinger, audio policy) must be anonymized. - * MAC addresses returned to system server or apps with BLUETOOTH_CONNECT permission - * are not anonymized. - * - * @param attributionSource The attribution source of the calling app. - * @param caller string identifying the caller for logging. - * @return true if the MAC addresses must be anonymized, false otherwise. - */ -bool mustAnonymizeBluetoothAddress( - const AttributionSourceState& attributionSource, const String16& caller) { - uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); - if (isAudioServerOrSystemServerUid(uid)) { - return false; - } - const std::optional resolvedAttributionSource = - resolveAttributionSource(attributionSource, DEVICE_ID_DEFAULT); - if (!resolvedAttributionSource.has_value()) { - return true; - } - permission::PermissionChecker permissionChecker; - return permissionChecker.checkPermissionForPreflightFromDatasource( - sAndroidPermissionBluetoothConnect, resolvedAttributionSource.value(), caller, - AppOpsManager::OP_BLUETOOTH_CONNECT) - != permission::PermissionChecker::PERMISSION_GRANTED; -} - -/** - * Modifies the passed MAC address string in place for consumption by unprivileged clients. - * the string is assumed to have a valid MAC address format. - * the anonymzation must be kept in sync with toAnonymizedAddress() in BluetoothUtils.java - * - * @param address input/output the char string contining the MAC address to anonymize. - */ -void anonymizeBluetoothAddress(char *address) { - if (address == nullptr || strlen(address) != strlen("AA:BB:CC:DD:EE:FF")) { - return; - } - memcpy(address, "XX:XX:XX:XX", strlen("XX:XX:XX:XX")); -} - sp MediaPackageManager::retrievePackageManager() { const sp sm = defaultServiceManager(); if (sm == nullptr) { diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h index 9c02cd41f5..e0fabfdb22 100644 --- a/media/utils/include/mediautils/ServiceUtilities.h +++ b/media/utils/include/mediautils/ServiceUtilities.h @@ -113,10 +113,6 @@ bool modifyPhoneStateAllowed(const AttributionSourceState& attributionSource); bool bypassInterruptionPolicyAllowed(const AttributionSourceState& attributionSource); bool callAudioInterceptionAllowed(const AttributionSourceState& attributionSource); void purgePermissionCache(); -bool mustAnonymizeBluetoothAddress( - const AttributionSourceState& attributionSource, const String16& caller); -void anonymizeBluetoothAddress(char *address); - int32_t getOpForSource(audio_source_t source); AttributionSourceState getCallingAttributionSource(); diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 82a43d2668..5985252b51 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -1596,19 +1596,6 @@ Status AudioPolicyService::isDirectOutputSupported( return Status::ok(); } -template -void anonymizePortBluetoothAddress(Port *port) { - if (port->type != AUDIO_PORT_TYPE_DEVICE) { - return; - } - if (!(audio_is_a2dp_device(port->ext.device.type) - || audio_is_ble_device(port->ext.device.type) - || audio_is_bluetooth_sco_device(port->ext.device.type) - || audio_is_hearing_aid_out_device(port->ext.device.type))) { - return; - } - anonymizeBluetoothAddress(port->ext.device.address); -} Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl, media::AudioPortType typeAidl, Int* count, @@ -1627,27 +1614,14 @@ Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl, std::unique_ptr ports(new audio_port_v7[num_ports]); unsigned int generation; - const AttributionSourceState attributionSource = getCallingAttributionSource(); - AutoCallerClear acc; - { - audio_utils::lock_guard _l(mMutex); - if (mAudioPolicyManager == NULL) { - return binderStatusFromStatusT(NO_INIT); - } - // AudioPolicyManager->listAudioPorts makes a deep copy of port structs into ports - // so it is safe to access after releasing the mutex - RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( - mAudioPolicyManager->listAudioPorts( - role, type, &num_ports, ports.get(), &generation))); - numPortsReq = std::min(numPortsReq, num_ports); - } - - if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { - for (size_t i = 0; i < numPortsReq; ++i) { - anonymizePortBluetoothAddress(&ports[i]); - } + audio_utils::lock_guard _l(mMutex); + if (mAudioPolicyManager == NULL) { + return binderStatusFromStatusT(NO_INIT); } - + AutoCallerClear acc; + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( + mAudioPolicyManager->listAudioPorts(role, type, &num_ports, ports.get(), &generation))); + numPortsReq = std::min(numPortsReq, num_ports); RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl), legacy2aidl_audio_port_v7_AudioPortFw))); @@ -1670,24 +1644,12 @@ Status AudioPolicyService::listDeclaredDevicePorts(media::AudioPortRole role, Status AudioPolicyService::getAudioPort(int portId, media::AudioPortFw* _aidl_return) { audio_port_v7 port{ .id = portId }; - - const AttributionSourceState attributionSource = getCallingAttributionSource(); - AutoCallerClear acc; - - { - audio_utils::lock_guard _l(mMutex); - if (mAudioPolicyManager == NULL) { - return binderStatusFromStatusT(NO_INIT); - } - // AudioPolicyManager->getAudioPort makes a deep copy of the port struct into port - // so it is safe to access after releasing the mutex - RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port))); - } - - if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { - anonymizePortBluetoothAddress(&port); + audio_utils::lock_guard _l(mMutex); + if (mAudioPolicyManager == NULL) { + return binderStatusFromStatusT(NO_INIT); } - + AutoCallerClear acc; + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port))); *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port)); return Status::ok(); } @@ -1745,32 +1707,14 @@ Status AudioPolicyService::listAudioPatches(Int* count, std::unique_ptr patches(new audio_patch[num_patches]); unsigned int generation; - const AttributionSourceState attributionSource = getCallingAttributionSource(); - AutoCallerClear acc; - - { - audio_utils::lock_guard _l(mMutex); - if (mAudioPolicyManager == NULL) { - return binderStatusFromStatusT(NO_INIT); - } - // AudioPolicyManager->listAudioPatches makes a deep copy of patches structs into patches - // so it is safe to access after releasing the mutex - RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( - mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation))); - numPatchesReq = std::min(numPatchesReq, num_patches); - } - - if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { - for (size_t i = 0; i < numPatchesReq; ++i) { - for (size_t j = 0; j < patches[i].num_sources; ++j) { - anonymizePortBluetoothAddress(&patches[i].sources[j]); - } - for (size_t j = 0; j < patches[i].num_sinks; ++j) { - anonymizePortBluetoothAddress(&patches[i].sinks[j]); - } - } + audio_utils::lock_guard _l(mMutex); + if (mAudioPolicyManager == NULL) { + return binderStatusFromStatusT(NO_INIT); } - + AutoCallerClear acc; + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( + mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation))); + numPatchesReq = std::min(numPatchesReq, num_patches); RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( convertRange(patches.get(), patches.get() + numPatchesReq, std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatchFw))); diff --git a/services/camera/virtualcamera/Android.bp b/services/camera/virtualcamera/Android.bp index fc186fba9e..41a3dbe7f1 100644 --- a/services/camera/virtualcamera/Android.bp +++ b/services/camera/virtualcamera/Android.bp @@ -95,4 +95,5 @@ cc_binary { "libvirtualcamera_utils", ], init_rc: ["virtual_camera.hal.rc"], + sdclang: false, } diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc index 9a5bd1e5f0..cd17517d2c 100644 --- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc +++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "Exif.h" @@ -78,6 +79,15 @@ using ::android::hardware::camera::common::helper::ExifUtils; namespace { +// helper type for the visitor +template +struct overloaded : Ts... { + using Ts::operator()...; +}; +// explicit deduction guide (not needed as of C++20) +template +overloaded(Ts...) -> overloaded; + using namespace std::chrono_literals; static constexpr std::chrono::milliseconds kAcquireFenceTimeout = 500ms; @@ -89,6 +99,8 @@ static constexpr uint8_t kPipelineDepth = 2; static constexpr size_t kJpegThumbnailBufferSize = 32 * 1024; // 32 KiB +static constexpr UpdateTextureTask kUpdateTextureTask; + CameraMetadata createCaptureResultMetadata( const std::chrono::nanoseconds timestamp, const RequestSettings& requestSettings, @@ -287,6 +299,21 @@ std::chrono::nanoseconds getMaxFrameDuration( static_cast(1e9 / VirtualCameraDevice::kMinFps)); } +class FrameAvailableListenerProxy : public ConsumerBase::FrameAvailableListener { + public: + FrameAvailableListenerProxy(std::function callback) + : mOnFrameAvailableCallback(callback) { + } + + virtual void onFrameAvailable(const BufferItem&) override { + ALOGV("%s: onFrameAvailable", __func__); + mOnFrameAvailableCallback(); + } + + private: + std::function mOnFrameAvailableCallback; +}; + } // namespace CaptureRequestBuffer::CaptureRequestBuffer(int streamId, int bufferId, @@ -345,9 +372,25 @@ const RequestSettings& ProcessCaptureRequestTask::getRequestSettings() const { return mRequestSettings; } +void VirtualCameraRenderThread::requestTextureUpdate() { + std::lock_guard lock(mLock); + // If queue is not empty, we don't need to set the mTextureUpdateRequested + // flag, since the texture will be updated during ProcessCaptureRequestTask + // processing anyway. + if (mQueue.empty()) { + mTextureUpdateRequested = true; + mCondVar.notify_one(); + } +} + void VirtualCameraRenderThread::enqueueTask( std::unique_ptr task) { std::lock_guard lock(mLock); + // When enqueving process capture request task, clear the + // mTextureUpdateRequested flag. If this flag is set, the texture was not yet + // updated and it will be updated when processing ProcessCaptureRequestTask + // anyway. + mTextureUpdateRequested = false; mQueue.emplace_back(std::move(task)); mCondVar.notify_one(); } @@ -377,8 +420,7 @@ sp VirtualCameraRenderThread::getInputSurface() { return mInputSurfaceFuture.get(); } -std::unique_ptr -VirtualCameraRenderThread::dequeueTask() { +RenderThreadTask VirtualCameraRenderThread::dequeueTask() { std::unique_lock lock(mLock); // Clang's thread safety analysis doesn't perform alias analysis, // so it doesn't support moveable std::unique_lock. @@ -389,12 +431,20 @@ VirtualCameraRenderThread::dequeueTask() { ScopedLockAssertion lockAssertion(mLock); mCondVar.wait(lock, [this]() REQUIRES(mLock) { - return mPendingExit || !mQueue.empty(); + return mPendingExit || mTextureUpdateRequested || !mQueue.empty(); }); if (mPendingExit) { - return nullptr; + // Render thread task with null task signals render thread to terminate. + return RenderThreadTask(nullptr); + } + if (mTextureUpdateRequested) { + // If mTextureUpdateRequested, it's guaranteed the queue is empty, return + // kUpdateTextureTask to signal we want render thread to update the texture + // (consume buffer from the queue). + mTextureUpdateRequested = false; + return RenderThreadTask(kUpdateTextureTask); } - std::unique_ptr task = std::move(mQueue.front()); + RenderThreadTask task(std::move(mQueue.front())); mQueue.pop_front(); return task; } @@ -409,11 +459,23 @@ void VirtualCameraRenderThread::threadLoop() { EglTextureProgram::TextureFormat::RGBA); mEglSurfaceTexture = std::make_unique( mInputSurfaceSize.width, mInputSurfaceSize.height); + sp frameAvailableListener = + sp::make( + [this]() { requestTextureUpdate(); }); + mEglSurfaceTexture->setFrameAvailableListener(frameAvailableListener); mInputSurfacePromise.set_value(mEglSurfaceTexture->getSurface()); - while (std::unique_ptr task = dequeueTask()) { - processCaptureRequest(*task); + while (RenderThreadTask task = dequeueTask()) { + std::visit( + overloaded{[this](const std::unique_ptr& t) { + processTask(*t); + }, + [this](const UpdateTextureTask&) { + ALOGV("Idle update of the texture"); + mEglSurfaceTexture->updateTexture(); + }}, + task); } // Destroy EGL utilities still on the render thread. @@ -425,7 +487,7 @@ void VirtualCameraRenderThread::threadLoop() { ALOGV("Render thread exiting"); } -void VirtualCameraRenderThread::processCaptureRequest( +void VirtualCameraRenderThread::processTask( const ProcessCaptureRequestTask& request) { std::chrono::nanoseconds timestamp = std::chrono::duration_cast( @@ -688,7 +750,7 @@ ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoBlobStreamBuffer( return status; } - PlanesLockGuard planesLock(hwBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, + PlanesLockGuard planesLock(hwBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, fence); if (planesLock.getStatus() != OK) { return cameraStatus(Status::INTERNAL_ERROR); @@ -771,8 +833,8 @@ ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoEglFramebuffer( Rect viewportRect = viewport.value_or(Rect(framebuffer.getWidth(), framebuffer.getHeight())); - glViewport(viewportRect.leftTop().x, viewportRect.leftTop().y, - viewportRect.getWidth(), viewportRect.getHeight()); + glViewport(viewportRect.left, viewportRect.top, viewportRect.getWidth(), + viewportRect.getHeight()); sp textureBuffer = mEglSurfaceTexture->getCurrentBuffer(); if (textureBuffer == nullptr) { diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h index b23c30c144..5a5966b635 100644 --- a/services/camera/virtualcamera/VirtualCameraRenderThread.h +++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "VirtualCameraDevice.h" @@ -34,7 +35,6 @@ #include "util/EglFramebuffer.h" #include "util/EglProgram.h" #include "util/EglSurfaceTexture.h" -#include "util/MetadataUtil.h" #include "util/Util.h" namespace android { @@ -94,6 +94,24 @@ class ProcessCaptureRequestTask { const RequestSettings mRequestSettings; }; +struct UpdateTextureTask {}; + +struct RenderThreadTask + : public std::variant, + UpdateTextureTask> { + // Allow implicit conversion to bool. + // + // Returns false, if the RenderThreadTask consist of null + // ProcessCaptureRequestTask, which signals that the thread should terminate. + operator bool() const { + const bool isExitSignal = + std::holds_alternative>( + *this) && + std::get>(*this) == nullptr; + return !isExitSignal; + } +}; + // Wraps dedicated rendering thread and rendering business with corresponding // input surface. class VirtualCameraRenderThread { @@ -120,6 +138,12 @@ class VirtualCameraRenderThread { // Stop rendering thread. void stop(); + // Send request to render thread to update the texture. + // Currently queued buffers in the input surface will be consumed and the most + // recent buffer in the input surface will be attached to the texture), all + // other buffers will be returned to the buffer queue. + void requestTextureUpdate() EXCLUDES(mLock); + // Equeue capture task for processing on render thread. void enqueueTask(std::unique_ptr task) EXCLUDES(mLock); @@ -131,13 +155,13 @@ class VirtualCameraRenderThread { sp getInputSurface(); private: - std::unique_ptr dequeueTask() EXCLUDES(mLock); + RenderThreadTask dequeueTask() EXCLUDES(mLock); // Rendering thread entry point. void threadLoop(); // Process single capture request task (always called on render thread). - void processCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask); + void processTask(const ProcessCaptureRequestTask& captureRequestTask); // Flush single capture request task returning the error status immediately. void flushCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask); @@ -192,6 +216,7 @@ class VirtualCameraRenderThread { std::mutex mLock; std::deque> mQueue GUARDED_BY(mLock); std::condition_variable mCondVar; + volatile bool mTextureUpdateRequested GUARDED_BY(mLock); volatile bool mPendingExit GUARDED_BY(mLock); // Acquisition timestamp of last frame. diff --git a/services/camera/virtualcamera/VirtualCameraService.cc b/services/camera/virtualcamera/VirtualCameraService.cc index 705af86ec0..7466089e89 100644 --- a/services/camera/virtualcamera/VirtualCameraService.cc +++ b/services/camera/virtualcamera/VirtualCameraService.cc @@ -76,6 +76,8 @@ Available commands: --camera_id=(ID) - override numerical ID for test camera instance --lens_facing=(front|back|external) - specifies lens facing for test camera instance --input_fps=(fps) - specify input fps for test camera, valid values are from 1 to 1000 + --sensor_orientation=(0|90|180|270) - Clockwise angle through which the output image + needs to be rotated to be upright on the device screen in its native orientation * disable_test_camera )"; constexpr char kCreateVirtualDevicePermission[] = @@ -439,6 +441,31 @@ binder_status_t VirtualCameraService::enableTestCameraCmd( } } + std::optional sensorOrientation; + std::optional sensorOrientationInt; + it = options.find("sensor_orientation"); + if (it != options.end()) { + sensorOrientationInt = parseInt(it->second); + switch (sensorOrientationInt.value_or(0)) { + case 0: + sensorOrientation = SensorOrientation::ORIENTATION_0; + break; + case 90: + sensorOrientation = SensorOrientation::ORIENTATION_90; + break; + case 180: + sensorOrientation = SensorOrientation::ORIENTATION_180; + break; + case 270: + sensorOrientation = SensorOrientation::ORIENTATION_270; + break; + default: + dprintf(err, "Invalid sensor rotation: %s\n, must be 0, 90, 180 or 270.", + it->second.c_str()); + return STATUS_BAD_VALUE; + } + } + sp token = sp::make(); mTestCameraToken.set(AIBinder_fromPlatformBinder(token)); @@ -449,6 +476,8 @@ binder_status_t VirtualCameraService::enableTestCameraCmd( Format::RGBA_8888, .maxFps = kMaxFps}); configuration.lensFacing = lensFacing.value_or(LensFacing::EXTERNAL); + configuration.sensorOrientation = + sensorOrientation.value_or(SensorOrientation::ORIENTATION_0); configuration.virtualCameraCallback = ndk::SharedRefBase::make( inputFps.value_or(kTestCameraDefaultInputFps)); diff --git a/services/camera/virtualcamera/VirtualCameraSessionContext.cc b/services/camera/virtualcamera/VirtualCameraSessionContext.cc index 284ad05b23..aab2d0dc88 100644 --- a/services/camera/virtualcamera/VirtualCameraSessionContext.cc +++ b/services/camera/virtualcamera/VirtualCameraSessionContext.cc @@ -129,7 +129,8 @@ std::optional VirtualCameraSessionContext::getStreamConfig( streamId); return std::optional(); } - return {it->second->getStreamConfig()}; + VirtualCameraStream& stream = *it->second; + return {stream.getStreamConfig()}; } std::shared_ptr VirtualCameraSessionContext::fetchHardwareBuffer( @@ -141,7 +142,8 @@ std::shared_ptr VirtualCameraSessionContext::fetchHardwareBuffe streamId); return nullptr; } - return it->second->getHardwareBuffer(bufferId); + VirtualCameraStream& stream = *it->second; + return stream.getHardwareBuffer(bufferId); } std::shared_ptr @@ -154,7 +156,8 @@ VirtualCameraSessionContext::fetchOrCreateEglFramebuffer( streamId); return nullptr; } - return it->second->getEglFrameBuffer(eglDisplay, bufferId); + VirtualCameraStream& stream = *it->second; + return stream.getEglFrameBuffer(eglDisplay, bufferId); } std::set VirtualCameraSessionContext::getStreamIds() const { diff --git a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc index 752d3908c4..719f64d53b 100644 --- a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc +++ b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "VirtualCameraService.h" @@ -191,6 +192,16 @@ class VirtualCameraServiceTest : public ::testing::Test { return getLensFacing(metadata); } + std::optional getCameraSensorOrienation(const std::string& id) { + std::shared_ptr camera = mCameraProvider->getCamera(id); + if (camera == nullptr) { + return std::nullopt; + } + CameraMetadata metadata; + camera->getCameraCharacteristics(&metadata); + return getSensorOrientation(metadata); + } + protected: std::shared_ptr mCameraService; std::shared_ptr mCameraProvider; @@ -506,6 +517,24 @@ TEST_F(VirtualCameraServiceTest, TestCameraShellCmdWithInvalidInputFps) { Eq(STATUS_BAD_VALUE)); } +TEST_F(VirtualCameraServiceTest, TestCameraShellCmdWithSensorOrientation90) { + EXPECT_THAT( + execute_shell_command("enable_test_camera --sensor_orientation=90"), + Eq(NO_ERROR)); + + std::vector cameraIds = getCameraIds(); + ASSERT_THAT(cameraIds, SizeIs(1)); + EXPECT_THAT(getCameraSensorOrienation(cameraIds[0]), Optional(Eq(90))); +} + +TEST_F(VirtualCameraServiceTest, TestCameraShellCmdWithSensorOrientationNoArgs) { + EXPECT_THAT(execute_shell_command("enable_test_camera"), Eq(NO_ERROR)); + + std::vector cameraIds = getCameraIds(); + ASSERT_THAT(cameraIds, SizeIs(1)); + EXPECT_THAT(getCameraSensorOrienation(cameraIds[0]), Optional(Eq(0))); +} + } // namespace } // namespace virtualcamera } // namespace companion diff --git a/services/camera/virtualcamera/util/EglSurfaceTexture.cc b/services/camera/virtualcamera/util/EglSurfaceTexture.cc index 7de5020f95..c81d36d2fb 100644 --- a/services/camera/virtualcamera/util/EglSurfaceTexture.cc +++ b/services/camera/virtualcamera/util/EglSurfaceTexture.cc @@ -64,6 +64,11 @@ sp EglSurfaceTexture::getCurrentBuffer() { return mGlConsumer->getCurrentBuffer(); } +void EglSurfaceTexture::setFrameAvailableListener( + const wp& listener) { + mGlConsumer->setFrameAvailableListener(listener); +} + bool EglSurfaceTexture::waitForNextFrame(const std::chrono::nanoseconds timeout) { return mSurface->waitForNextFrame(mGlConsumer->getFrameNumber(), static_cast(timeout.count())); diff --git a/services/camera/virtualcamera/util/EglSurfaceTexture.h b/services/camera/virtualcamera/util/EglSurfaceTexture.h index b9c5126851..ac3cf7d352 100644 --- a/services/camera/virtualcamera/util/EglSurfaceTexture.h +++ b/services/camera/virtualcamera/util/EglSurfaceTexture.h @@ -21,6 +21,7 @@ #include #include "GLES/gl.h" +#include "gui/ConsumerBase.h" #include "gui/Surface.h" #include "utils/RefBase.h" @@ -58,6 +59,9 @@ class EglSurfaceTexture { // Returns false on timeout, true if new frame was received before timeout. bool waitForNextFrame(std::chrono::nanoseconds timeout); + void setFrameAvailableListener( + const wp& listener); + // Update the texture with the most recent submitted buffer. // Most be called on thread with EGL context. // diff --git a/services/camera/virtualcamera/util/MetadataUtil.cc b/services/camera/virtualcamera/util/MetadataUtil.cc index 31a8776bfe..4889830a64 100644 --- a/services/camera/virtualcamera/util/MetadataUtil.cc +++ b/services/camera/virtualcamera/util/MetadataUtil.cc @@ -961,6 +961,20 @@ std::optional getDeviceId( return static_cast(entry.data.i32[0]); } +std::optional getSensorOrientation( + const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata) { + auto metadata = + reinterpret_cast(cameraMetadata.metadata.data()); + + camera_metadata_ro_entry_t entry; + if (find_camera_metadata_ro_entry(metadata, ANDROID_SENSOR_ORIENTATION, + &entry) != OK) { + return std::nullopt; + } + + return static_cast(entry.data.i32[0]); +} + } // namespace virtualcamera } // namespace companion } // namespace android diff --git a/services/camera/virtualcamera/util/MetadataUtil.h b/services/camera/virtualcamera/util/MetadataUtil.h index ca6f332cdb..22d3657a4a 100644 --- a/services/camera/virtualcamera/util/MetadataUtil.h +++ b/services/camera/virtualcamera/util/MetadataUtil.h @@ -488,6 +488,11 @@ getPrecaptureTrigger( std::optional getDeviceId( const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata); +// Return the value of ANDROID_SENSOR_ORIENTATION or nullopt if the key is not +// present (which is equivalent to a orientation of 0). +std::optional getSensorOrientation( + const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata); + } // namespace virtualcamera } // namespace companion } // namespace android diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp index 4ff0abccdd..19fab82723 100644 --- a/services/mediacodec/Android.bp +++ b/services/mediacodec/Android.bp @@ -89,7 +89,6 @@ cc_binary { "libavservices_minijail", "libcutils", "libhidlbase", - "libstagefright_omx_ext", "libstagefright_omx", "libstagefright_xmlparser", "android.hardware.media.omx@1.0",