Merge "Add crypto scheme check when create drm plugin" into main
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 6c58bcf..c97059d 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -40,6 +40,21 @@
__BEGIN_DECLS
+/*
+ * Note: The following enum values were incorrect and have been updated:
+ * enum old value updated value
+ * ACAMERA_CONTROL_SETTINGS_OVERRIDE ACAMERA_CONTROL_START + 49 ACAMERA_CONTROL_START + 52;
+ * ACAMERA_CONTROL_AVAILABLE_SETTINGS_OVERRIDES ACAMERA_CONTROL_START + 50 ACAMERA_CONTROL_START + 53;
+ * ACAMERA_CONTROL_AUTOFRAMING ACAMERA_CONTROL_START + 52 ACAMERA_CONTROL_START + 55;
+ * ACAMERA_CONTROL_AUTOFRAMING_AVAILABLE ACAMERA_CONTROL_START + 53 ACAMERA_CONTROL_START + 56;
+ * ACAMERA_CONTROL_AUTOFRAMING_STATE ACAMERA_CONTROL_START + 54 ACAMERA_CONTROL_START + 57;
+ * ACAMERA_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE ACAMERA_CONTROL_START + 55 ACAMERA_CONTROL_START + 58;
+ * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE ACAMERA_CONTROL_START + 56 ACAMERA_CONTROL_START + 59;
+
+ * ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES ACAMERA_SCALER_START + 25 ACAMERA_SCALER_START + 26;
+ * ACAMERA_SCALER_CROP_REGION ACAMERA_SCALER_START + 26 ACAMERA_SCALER_START + 27;
+ */
+
typedef enum acamera_metadata_section {
ACAMERA_COLOR_CORRECTION,
diff --git a/drm/libmediadrmrkp/Android.bp b/drm/libmediadrmrkp/Android.bp
index f13eb62..b1a01e4 100644
--- a/drm/libmediadrmrkp/Android.bp
+++ b/drm/libmediadrmrkp/Android.bp
@@ -5,7 +5,7 @@
"src/**/*.cpp",
],
export_include_dirs: [
- "include"
+ "include",
],
shared_libs: [
"libbinder_ndk",
@@ -17,7 +17,7 @@
"android.hardware.drm-V1-ndk",
"android.hardware.security.rkp-V3-ndk",
"libbase",
- "libcppbor_external",
+ "libcppbor",
],
defaults: [
"keymint_use_latest_hal_aidl_ndk_shared",
@@ -42,7 +42,7 @@
"android.hardware.drm-V1-ndk",
"android.hardware.security.rkp-V3-ndk",
"libbase",
- "libcppbor_external",
+ "libcppbor",
"libmediadrmrkp",
],
vendor: true,
@@ -50,4 +50,4 @@
"-Wall",
"-Werror",
],
-}
\ No newline at end of file
+}
diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig
index 277654d..17ce8df 100644
--- a/media/audio/aconfig/audio.aconfig
+++ b/media/audio/aconfig/audio.aconfig
@@ -88,7 +88,7 @@
description:
"When syncing the VGS to VSS we need to first adjust the"
"mute state before the index."
- bug: "329202581"
+ bug: "331849188"
}
flag {
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
index d1f0fb5..4c2ef9c 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
@@ -83,6 +83,7 @@
}
}
+// @VsrTest = 3.2-001.003
TEST_P(Codec2MasterHalTest, MustUseAidlBeyond202404) {
static int sVendorApiLevel = android::base::GetIntProperty("ro.vendor.api_level", 0);
if (sVendorApiLevel < 202404) {
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 37a7a4f..692f700 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -687,6 +687,11 @@
const MediaCodecsXmlParser::AttributeMap &attrMap = typeIt->second;
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
codecInfo->addMediaType(mediaType.c_str());
+
+ // we could detect tunneled playback via the playback interface, but we never did
+ // that for the advertised feature, so for now use only the advertised feature.
+ bool canDoTunneledPlayback = false;
+
for (const auto &v : attrMap) {
std::string key = v.first;
std::string value = v.second;
@@ -707,6 +712,11 @@
// Ignore trailing bad characters and default to 0.
(void)sscanf(value.c_str(), "%d", &intValue);
caps->addDetail(key.c_str(), intValue);
+
+ if (key.compare(
+ MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK) == 0) {
+ canDoTunneledPlayback = true;
+ }
} else {
caps->addDetail(key.c_str(), value.c_str());
}
@@ -774,6 +784,17 @@
}
}
}
+
+ if (android::media::codec::provider_->null_output_surface_support() &&
+ android::media::codec::provider_->null_output_surface()) {
+ // all non-tunneled video decoders support detached surface mode
+ if (trait.kind == C2Component::KIND_DECODER &&
+ trait.domain == C2Component::DOMAIN_VIDEO &&
+ !canDoTunneledPlayback) {
+ caps->addDetail(
+ MediaCodecInfo::Capabilities::FEATURE_DETACHED_SURFACE, 0);
+ }
+ }
}
}
}
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
index da28204..df1f9bd 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
@@ -175,17 +175,19 @@
if (!range) {
return BAD_VALUE;
}
+ std::vector<Spatialization::Level> levels;
for (const auto level : ::ndk::enum_range<Spatialization::Level>()) {
const auto spatializer =
Spatializer::make<Spatializer::spatializationLevel>(level);
if (spatializer >= range->min && spatializer <= range->max) {
- if (status_t status = param.writeToValue(&level); status != OK) {
- ALOGW("%s %d: write level %s to value failed %d", __func__, __LINE__,
- toString(level).c_str(), status);
- return status;
- }
+ levels.emplace_back(level);
}
}
+ const uint8_t num = levels.size();
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
+ for (const auto level : levels) {
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&level));
+ }
return OK;
}
case SPATIALIZER_PARAM_LEVEL: {
@@ -234,15 +236,14 @@
const auto& supportedLayouts = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
aidlParam, Spatializer, spatializer, Spatializer::supportedChannelLayout,
std::vector<AudioChannelLayout>));
+ // audio_channel_mask_t is uint32_t enum, write number in 32bit
+ const uint32_t num = supportedLayouts.size();
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
for (const auto& layout : supportedLayouts) {
audio_channel_mask_t mask = VALUE_OR_RETURN_STATUS(
::aidl::android::aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
layout, false /* isInput */));
- if (status_t status = param.writeToValue(&mask); status != OK) {
- ALOGW("%s %d: write mask %s to value failed %d", __func__, __LINE__,
- layout.toString().c_str(), status);
- return status;
- }
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&mask));
}
return OK;
}
@@ -252,17 +253,19 @@
if (!range) {
return BAD_VALUE;
}
+ std::vector<Spatialization::Mode> modes;
for (const auto mode : ::ndk::enum_range<Spatialization::Mode>()) {
if (const auto spatializer =
Spatializer::make<Spatializer::spatializationMode>(mode);
spatializer >= range->min && spatializer <= range->max) {
- if (status_t status = param.writeToValue(&mode); status != OK) {
- ALOGW("%s %d: write mode %s to value failed %d", __func__, __LINE__,
- toString(mode).c_str(), status);
- return status;
- }
+ modes.emplace_back(mode);
}
}
+ const uint8_t num = modes.size();
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
+ for (const auto mode : modes) {
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&mode));
+ }
return OK;
}
case SPATIALIZER_PARAM_SUPPORTED_HEADTRACKING_CONNECTION: {
@@ -271,17 +274,18 @@
if (!range) {
return BAD_VALUE;
}
+ std::vector<HeadTracking::ConnectionMode> modes;
for (const auto mode : ::ndk::enum_range<HeadTracking::ConnectionMode>()) {
if (const auto spatializer =
Spatializer::make<Spatializer::headTrackingConnectionMode>(mode);
spatializer < range->min || spatializer > range->max) {
- continue;
+ modes.emplace_back(mode);
}
- if (status_t status = param.writeToValue(&mode); status != OK) {
- ALOGW("%s %d: write mode %s to value failed %d", __func__, __LINE__,
- toString(mode).c_str(), status);
- return status;
- }
+ }
+ const uint8_t num = modes.size();
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
+ for (const auto mode : modes) {
+ RETURN_STATUS_IF_ERROR(param.writeToValue(&mode));
}
return OK;
}
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index 9c440df..ada301b 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -118,26 +118,21 @@
RetCode DynamicsProcessingContext::setPreEq(
const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
- return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.preEqStage.inUse,
- StageType::PREEQ);
+ return setDpChannels_l<dp_fx::DPEq>(channels, StageType::PREEQ);
}
RetCode DynamicsProcessingContext::setPostEq(
const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
- return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.postEqStage.inUse,
- StageType::POSTEQ);
+ return setDpChannels_l<dp_fx::DPEq>(channels, StageType::POSTEQ);
}
RetCode DynamicsProcessingContext::setMbc(
const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
- return setDpChannels_l<dp_fx::DPMbc>(channels, mEngineArchitecture.mbcStage.inUse,
- StageType::MBC);
+ return setDpChannels_l<dp_fx::DPMbc>(channels, StageType::MBC);
}
RetCode DynamicsProcessingContext::setPreEqBand(
const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
- RETURN_VALUE_IF(!mEngineArchitecture.preEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
- "preEqNotInUse");
RETURN_VALUE_IF(
!validateBandConfig(bands, mChannelCount, mEngineArchitecture.preEqStage.bandCount),
RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
@@ -146,8 +141,6 @@
RetCode DynamicsProcessingContext::setPostEqBand(
const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
- RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
- "postEqNotInUse");
RETURN_VALUE_IF(
!validateBandConfig(bands, mChannelCount, mEngineArchitecture.postEqStage.bandCount),
RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
@@ -156,8 +149,6 @@
RetCode DynamicsProcessingContext::setMbcBand(
const std::vector<DynamicsProcessing::MbcBandConfig>& bands) {
- RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
- "mbcNotInUse");
RETURN_VALUE_IF(
!validateBandConfig(bands, mChannelCount, mEngineArchitecture.mbcStage.bandCount),
RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
@@ -166,8 +157,6 @@
RetCode DynamicsProcessingContext::setLimiter(
const std::vector<DynamicsProcessing::LimiterConfig>& limiters) {
- RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
- "limiterNotInUse");
RETURN_VALUE_IF(!validateLimiterConfig(limiters, mChannelCount),
RetCode::ERROR_ILLEGAL_PARAMETER, "limiterConfigNotValid");
return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, StageType::LIMITER);
@@ -419,9 +408,7 @@
}
freqs[band.band] = band.cutoffFrequencyHz;
}
- return std::is_sorted(freqs.begin(), freqs.end(), [](const auto& a, const auto& b) {
- return a.second <= b.second; //index is already sorted as map key
- });
+ return true;
}
bool DynamicsProcessingContext::validateLimiterConfig(
@@ -442,17 +429,10 @@
template <typename D>
RetCode DynamicsProcessingContext::setDpChannels_l(
- const std::vector<DynamicsProcessing::ChannelConfig>& channels, bool stageInUse,
- StageType type) {
+ const std::vector<DynamicsProcessing::ChannelConfig>& channels, StageType type) {
RetCode ret = RetCode::SUCCESS;
std::unordered_set<int> channelSet;
- if (!stageInUse) {
- LOG(WARNING) << __func__ << " not in use " << ::android::internal::ToString(channels);
- return RetCode::ERROR_ILLEGAL_PARAMETER;
- }
-
- RETURN_VALUE_IF(!stageInUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
for (auto& it : channels) {
if (0 != channelSet.count(it.channel)) {
LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
index a059dd0..ce657db 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
@@ -99,7 +99,7 @@
dp_fx::DPEq* getEqWithType_l(StageType type, int ch);
template <typename D>
RetCode setDpChannels_l(const std::vector<DynamicsProcessing::ChannelConfig>& channels,
- bool stageInUse, StageType type);
+ StageType type);
template <typename T /* BandConfig */>
RetCode setBands_l(const std::vector<T>& bands, StageType type);
RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type,
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 590a7b7..840897f 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -223,7 +223,6 @@
"com.android.media",
],
-
srcs: ["MidiIoWrapper.cpp"],
static_libs: [
@@ -278,6 +277,10 @@
"libutils",
],
+ static_libs: [
+ "android.media.codec-aconfig-cc",
+ ],
+
include_dirs: [
"system/libhidl/transport/token/1.0/utils/include",
],
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index 86ad997..c45c5c3 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -36,6 +36,7 @@
constexpr char MediaCodecInfo::Capabilities::FEATURE_MULTIPLE_FRAMES[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_SECURE_PLAYBACK[];
constexpr char MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_DETACHED_SURFACE[];
void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
Vector<ProfileLevel> *profileLevels) const {
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index 54f565a..88a2dc4 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -69,6 +69,7 @@
constexpr static char FEATURE_MULTIPLE_FRAMES[] = "feature-multiple-frames";
constexpr static char FEATURE_SECURE_PLAYBACK[] = "feature-secure-playback";
constexpr static char FEATURE_TUNNELED_PLAYBACK[] = "feature-tunneled-playback";
+ constexpr static char FEATURE_DETACHED_SURFACE[] = "feature-detached-surface";
/**
* Returns the supported levels for each supported profile in a target array.
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index f9ceef2..1593aa0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -21,6 +21,8 @@
#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
#endif
+#include <android_media_codec.h>
+
#include <inttypes.h>
#include <utils/Trace.h>
@@ -9314,6 +9316,12 @@
// adaptive playback is not supported
caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK);
}
+
+ // all non-tunneled video decoders support detached surface mode
+ if (android::media::codec::provider_->null_output_surface_support() &&
+ android::media::codec::provider_->null_output_surface()) {
+ caps->addDetail(MediaCodecInfo::Capabilities::FEATURE_DETACHED_SURFACE, 0);
+ }
}
}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 896e021..886285e 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -319,6 +319,7 @@
],
static_libs: [
+ "android.media.codec-aconfig-cc",
"libstagefright_esds",
"libstagefright_color_conversion",
"libyuv_static",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e4f3b83..cc6f5e8 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -30,6 +30,8 @@
#include "include/SoftwareRenderer.h"
+#include <android_media_codec.h>
+
#include <android/api-level.h>
#include <android/content/pm/IPackageManagerNative.h>
#include <android/hardware/cas/native/1.0/IDescrambler.h>
@@ -3017,6 +3019,13 @@
return PostAndAwaitResponse(msg, &response);
}
+status_t MediaCodec::detachOutputSurface() {
+ sp<AMessage> msg = new AMessage(kWhatDetachSurface, this);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
status_t MediaCodec::setSurface(const sp<Surface> &surface) {
sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
msg->setObject("surface", surface);
@@ -4676,7 +4685,7 @@
}
mResourceManagerProxy->removeClient();
- mReleaseSurface.reset();
+ mDetachedSurface.reset();
if (mReplyID != nullptr) {
postPendingRepliesAndDeferredMessages("kWhatReleaseCompleted");
@@ -4849,6 +4858,23 @@
mFlags |= kFlagPushBlankBuffersOnShutdown;
}
+ uint32_t flags;
+ CHECK(msg->findInt32("flags", (int32_t *)&flags));
+
+ if (android::media::codec::provider_->null_output_surface_support()) {
+ if (obj == nullptr
+ && (flags & CONFIGURE_FLAG_DETACHED_SURFACE)
+ && !(flags & CONFIGURE_FLAG_ENCODE)) {
+ sp<Surface> surface = getOrCreateDetachedSurface();
+ if (surface == nullptr) {
+ mErrorLog.log(
+ LOG_TAG, "Detached surface mode is not supported by this codec");
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ }
+ obj = surface;
+ }
+ }
+
if (obj != NULL) {
if (!format->findInt32(KEY_ALLOW_FRAME_DROP, &mAllowFrameDroppingBySurface)) {
// allow frame dropping by surface by default
@@ -4872,8 +4898,6 @@
mApiUsageMetrics.isUsingOutputSurface = true;
- uint32_t flags;
- CHECK(msg->findInt32("flags", (int32_t *)&flags));
if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL ||
flags & CONFIGURE_FLAG_USE_CRYPTO_ASYNC) {
if (!(mFlags & kFlagIsAsync)) {
@@ -4994,6 +5018,23 @@
break;
}
+ case kWhatDetachSurface:
+ {
+ // detach surface is equivalent to setSurface(mDetachedSurface)
+ sp<Surface> surface = getOrCreateDetachedSurface();
+
+ if (surface == nullptr) {
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+ mErrorLog.log(LOG_TAG, "Detaching surface is not supported by the codec.");
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ break;
+ }
+
+ msg->setObject("surface", surface);
+ }
+ [[fallthrough]];
+
case kWhatSetSurface:
{
sp<AReplyToken> replyID;
@@ -5011,14 +5052,17 @@
sp<Surface> surface = static_cast<Surface *>(obj.get());
if (mSurface == NULL) {
// do not support setting surface if it was not set
- mErrorLog.log(LOG_TAG,
- "Cannot set surface if the codec is not configured with "
- "a surface already");
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Cannot %s surface if the codec is not configured with "
+ "a surface already",
+ msg->what() == kWhatDetachSurface ? "detach" : "set"));
err = INVALID_OPERATION;
} else if (obj == NULL) {
// do not support unsetting surface
mErrorLog.log(LOG_TAG, "Unsetting surface is not supported");
err = BAD_VALUE;
+ } else if (android::media::codec::provider_->null_output_surface_support()) {
+ err = handleSetSurface(surface, true /* callCodec */);
} else {
uint32_t generation;
err = connectToSurface(surface, &generation);
@@ -5052,7 +5096,8 @@
default:
mErrorLog.log(LOG_TAG, base::StringPrintf(
- "setSurface() is valid only at Executing states; currently %s",
+ "%sSurface() is valid only at Executing states; currently %s",
+ msg->what() == kWhatDetachSurface ? "detach" : "set",
apiStateString().c_str()));
err = INVALID_OPERATION;
break;
@@ -5273,30 +5318,40 @@
bool forceSync = false;
if (asyncNotify != nullptr && mSurface != NULL) {
- if (!mReleaseSurface) {
- uint64_t usage = 0;
- if (mSurface->getConsumerUsage(&usage) != OK) {
- usage = 0;
- }
- mReleaseSurface.reset(new ReleaseSurface(usage));
- }
- if (mSurface != mReleaseSurface->getSurface()) {
- uint32_t generation;
- status_t err = connectToSurface(mReleaseSurface->getSurface(), &generation);
- ALOGW_IF(err != OK, "error connecting to release surface: err = %d", err);
- if (err == OK && !(mFlags & kFlagUsesSoftwareRenderer)) {
- err = mCodec->setSurface(mReleaseSurface->getSurface(), generation);
- ALOGW_IF(err != OK, "error setting release surface: err = %d", err);
- }
- if (err == OK) {
- (void)disconnectFromSurface();
- mSurface = mReleaseSurface->getSurface();
- mSurfaceGeneration = generation;
- } else {
- // We were not able to switch the surface, so force
+ if (android::media::codec::provider_->null_output_surface_support()) {
+ if (handleSetSurface(getOrCreateDetachedSurface(), true /* callCodec */,
+ true /* onShutDown */) != OK) {
+ // We were not able to detach the surface, so force
// synchronous release.
forceSync = true;
}
+ } else {
+ if (!mDetachedSurface) {
+ uint64_t usage = 0;
+ if (mSurface->getConsumerUsage(&usage) != OK) {
+ usage = 0;
+ }
+ mDetachedSurface.reset(new ReleaseSurface(usage));
+ }
+ if (mSurface != mDetachedSurface->getSurface()) {
+ uint32_t generation;
+ status_t err =
+ connectToSurface(mDetachedSurface->getSurface(), &generation);
+ ALOGW_IF(err != OK, "error connecting to release surface: err = %d", err);
+ if (err == OK && !(mFlags & kFlagUsesSoftwareRenderer)) {
+ err = mCodec->setSurface(mDetachedSurface->getSurface(), generation);
+ ALOGW_IF(err != OK, "error setting release surface: err = %d", err);
+ }
+ if (err == OK) {
+ (void)disconnectFromSurface();
+ mSurface = mDetachedSurface->getSurface();
+ mSurfaceGeneration = generation;
+ } else {
+ // We were not able to switch the surface, so force
+ // synchronous release.
+ forceSync = true;
+ }
+ }
}
}
@@ -6612,6 +6667,23 @@
return index;
}
+sp<Surface> MediaCodec::getOrCreateDetachedSurface() {
+ if (mDomain != DOMAIN_VIDEO || (mFlags & kFlagIsEncoder)) {
+ return nullptr;
+ }
+
+ if (!mDetachedSurface) {
+ uint64_t usage = 0;
+ if (!mSurface || mSurface->getConsumerUsage(&usage) != OK) {
+ // TODO: should we use a/the default consumer usage?
+ usage = 0;
+ }
+ mDetachedSurface.reset(new ReleaseSurface(usage));
+ }
+
+ return mDetachedSurface->getSurface();
+}
+
status_t MediaCodec::connectToSurface(const sp<Surface> &surface, uint32_t *generation) {
status_t err = OK;
if (surface != NULL) {
@@ -6685,7 +6757,56 @@
return err;
}
+status_t MediaCodec::handleSetSurface(const sp<Surface> &surface, bool callCodec, bool onShutDown) {
+ uint32_t generation;
+ status_t err = OK;
+ if (surface != nullptr) {
+ err = connectToSurface(surface, &generation);
+ if (err == ALREADY_EXISTS) {
+ // reconnecting to same surface
+ return OK;
+ }
+
+ if (err == OK && callCodec) {
+ if (mFlags & kFlagUsesSoftwareRenderer) {
+ if (mSoftRenderer != NULL
+ && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
+ pushBlankBuffersToNativeWindow(mSurface.get());
+ }
+ // do not create a new software renderer on shutdown (release)
+ // as it will not be used anyway
+ if (!onShutDown) {
+ surface->setDequeueTimeout(-1);
+ mSoftRenderer = new SoftwareRenderer(surface);
+ // TODO: check if this was successful
+ }
+ } else {
+ err = mCodec->setSurface(surface, generation);
+ }
+
+ mReliabilityContextMetrics.setOutputSurfaceCount++;
+ }
+ }
+
+ if (err == OK) {
+ if (mSurface != NULL) {
+ (void)disconnectFromSurface();
+ }
+
+ if (surface != NULL) {
+ mSurface = surface;
+ mSurfaceGeneration = generation;
+ }
+ }
+
+ return err;
+}
+
status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
+ if (android::media::codec::provider_->null_output_surface_support()) {
+ return handleSetSurface(surface, false /* callCodec */);
+ }
+
status_t err = OK;
if (mSurface != NULL) {
(void)disconnectFromSurface();
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 9ecb12e..7169b1e 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -96,6 +96,7 @@
CONFIGURE_FLAG_ENCODE = 1,
CONFIGURE_FLAG_USE_BLOCK_MODEL = 2,
CONFIGURE_FLAG_USE_CRYPTO_ASYNC = 4,
+ CONFIGURE_FLAG_DETACHED_SURFACE = 8,
};
enum BufferFlags {
@@ -274,6 +275,8 @@
status_t setSurface(const sp<Surface> &nativeWindow);
+ status_t detachOutputSurface();
+
status_t requestIDRFrame();
// Notification will be posted once there "is something to do", i.e.
@@ -368,6 +371,7 @@
kWhatInit = 'init',
kWhatConfigure = 'conf',
kWhatSetSurface = 'sSur',
+ kWhatDetachSurface = 'dSur',
kWhatCreateInputSurface = 'cisf',
kWhatSetInputSurface = 'sisf',
kWhatStart = 'strt',
@@ -474,6 +478,10 @@
uint32_t mSurfaceGeneration = 0;
SoftwareRenderer *mSoftRenderer;
+ // Get the detached BufferQueue surface for a video decoder, and create it
+ // if it did not yet exist.
+ sp<Surface> getOrCreateDetachedSurface();
+
Mutex mMetricsLock;
mediametrics_handle_t mMetricsHandle = 0;
bool mMetricsToUpload = false;
@@ -642,6 +650,13 @@
status_t queueCSDInputBuffer(size_t bufferIndex);
status_t handleSetSurface(const sp<Surface> &surface);
+
+ // Common reimplementation of changing the output surface.
+ // Handles setting null surface, which is used during configure and init.
+ // Set |callCodec| to true if the codec needs to be notified (e.g. during executing state).
+ // Setting |onShutdown| to true will avoid extra work, if this is used for detaching on
+ // delayed release.
+ status_t handleSetSurface(const sp<Surface> &surface, bool callCodec, bool onShutdown = false);
status_t connectToSurface(const sp<Surface> &surface, uint32_t *generation);
status_t disconnectFromSurface();
@@ -714,7 +729,7 @@
sp<AMessage> mMsgPollForRenderedBuffers;
class ReleaseSurface;
- std::unique_ptr<ReleaseSurface> mReleaseSurface;
+ std::unique_ptr<ReleaseSurface> mDetachedSurface;
std::list<sp<AMessage>> mLeftover;
status_t handleLeftover(size_t index);
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 2341af1..6ea40e3 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -85,16 +85,7 @@
"-Wall",
],
- // AIDL is only used when release_aidl_use_unfrozen is true
- // because the swcodec mainline module is a prebuilt from an
- // Android U branch in that case.
- // TODO(b/327508501)
- vintf_fragments: ["manifest_media_c2_software_hidl.xml"],
- product_variables: {
- release_aidl_use_unfrozen: {
- vintf_fragments: ["manifest_media_c2_software_aidl.xml"],
- },
- },
+ vintf_fragments: ["manifest_media_c2_software.xml"],
soong_config_variables: {
TARGET_DYNAMIC_64_32_MEDIASERVER: {
diff --git a/media/mediaserver/manifest_media_c2_software_hidl.xml b/media/mediaserver/manifest_media_c2_software.xml
similarity index 68%
rename from media/mediaserver/manifest_media_c2_software_hidl.xml
rename to media/mediaserver/manifest_media_c2_software.xml
index 69a27be..31dfafb 100644
--- a/media/mediaserver/manifest_media_c2_software_hidl.xml
+++ b/media/mediaserver/manifest_media_c2_software.xml
@@ -8,4 +8,9 @@
<instance>software</instance>
</interface>
</hal>
+ <hal format="aidl">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
+ <fqname>IComponentStore/software</fqname>
+ </hal>
</manifest>
diff --git a/media/mediaserver/manifest_media_c2_software_aidl.xml b/media/mediaserver/manifest_media_c2_software_aidl.xml
deleted file mode 100644
index e6bcafa..0000000
--- a/media/mediaserver/manifest_media_c2_software_aidl.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<manifest version="1.0" type="framework">
- <hal format="aidl">
- <name>android.hardware.media.c2</name>
- <version>1</version>
- <fqname>IComponentStore/software</fqname>
- </hal>
-</manifest>
diff --git a/media/module/bufferpool/1.0/vts/multi.cpp b/media/module/bufferpool/1.0/vts/multi.cpp
index d8cc285..21f47d3 100644
--- a/media/module/bufferpool/1.0/vts/multi.cpp
+++ b/media/module/bufferpool/1.0/vts/multi.cpp
@@ -24,6 +24,7 @@
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/LegacySupport.h>
+#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
#include <signal.h>
#include <sys/types.h>
@@ -36,6 +37,7 @@
using android::hardware::configureRpcThreadpool;
using android::hardware::hidl_handle;
+using android::hardware::isHidlSupported;
using android::hardware::media::bufferpool::V1_0::IClientManager;
using android::hardware::media::bufferpool::V1_0::ResultStatus;
using android::hardware::media::bufferpool::V1_0::implementation::BufferId;
@@ -178,6 +180,7 @@
ResultStatus status;
PipeMessage message;
+ if (!isHidlSupported()) GTEST_SKIP() << "HIDL is not supported on this device";
ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
android::sp<IClientManager> receiver = IClientManager::getService();
diff --git a/media/module/esds/tests/ESDSTest.cpp b/media/module/esds/tests/ESDSTest.cpp
index 33bdcac..ba64f60 100644
--- a/media/module/esds/tests/ESDSTest.cpp
+++ b/media/module/esds/tests/ESDSTest.cpp
@@ -52,7 +52,7 @@
/* BitrateMax */ int32_t,
/* BitrateAvg */ int32_t>> {
public:
- ESDSUnitTest() : mESDSData(nullptr) {
+ ESDSUnitTest() {
mESDSParams.inputFile = get<0>(GetParam());
mESDSParams.objectTypeIndication = get<1>(GetParam());
mESDSParams.codecSpecificInfoData = get<2>(GetParam());
@@ -61,6 +61,13 @@
mESDSParams.bitrateAvg = get<5>(GetParam());
};
+ ~ESDSUnitTest() {
+ if (mESDSData != nullptr) {
+ free(mESDSData);
+ mESDSData = nullptr;
+ }
+ }
+
virtual void TearDown() override {
if (mDataSource) mDataSource.clear();
if (mInputFp) {
@@ -70,8 +77,8 @@
}
virtual void SetUp() override { ASSERT_NO_FATAL_FAILURE(readESDSData()); }
- const void *mESDSData;
- size_t mESDSSize;
+ void *mESDSData = nullptr;
+ size_t mESDSSize = 0;
ESDSParams mESDSParams;
private:
@@ -105,10 +112,19 @@
bool esdsDataPresent(size_t numTracks, sp<IMediaExtractor> extractor) {
bool foundESDS = false;
uint32_t type;
+ if (mESDSData != nullptr) {
+ free(mESDSData);
+ mESDSData = nullptr;
+ }
for (size_t i = 0; i < numTracks; ++i) {
sp<MetaData> trackMeta = extractor->getTrackMetaData(i);
+ const void *esdsData = nullptr;
+ size_t esdsSize = 0;
if (trackMeta != nullptr &&
- trackMeta->findData(kKeyESDS, &type, &mESDSData, &mESDSSize)) {
+ trackMeta->findData(kKeyESDS, &type, &esdsData, &esdsSize)) {
+ mESDSData = malloc(esdsSize);
+ mESDSSize = esdsSize;
+ memcpy(mESDSData, esdsData, esdsSize);
trackMeta->clear();
foundESDS = true;
break;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2dea379..3c3a43a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -7834,10 +7834,18 @@
float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
VolumeSource volumeSource,
int index,
- const DeviceTypeSet& deviceTypes)
+ const DeviceTypeSet& deviceTypes,
+ bool computeInternalInteraction)
{
float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(deviceTypes), index);
+ ALOGV("%s volume source %d, index %d, devices %s, compute internal %b ", __func__,
+ volumeSource, index, dumpDeviceTypes(deviceTypes).c_str(), computeInternalInteraction);
+
+ if (!computeInternalInteraction) {
+ return volumeDb;
+ }
+
// handle the case of accessibility active while a ringtone is playing: if the ringtone is much
// louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
// exploration of the dialer UI. In this situation, bring the accessibility volume closer to
@@ -7847,14 +7855,11 @@
const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC, false);
const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM, false);
const auto a11yVolumeSrc = toVolumeSource(AUDIO_STREAM_ACCESSIBILITY, false);
- // Verify that the current volume source is not the ringer volume to prevent recursively
- // calling to compute volume. This could happen in cases where a11y and ringer sounds belong
- // to the same volume group.
- if (volumeSource != ringVolumeSrc && volumeSource == a11yVolumeSrc
- && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
+ if (AUDIO_MODE_RINGTONE == mEngine->getPhoneState() &&
mOutputs.isActive(ringVolumeSrc, 0)) {
auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
- const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, deviceTypes);
+ const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, deviceTypes,
+ /* computeInternalInteraction= */ false);
return ringVolumeDb - 4 > volumeDb ? ringVolumeDb - 4 : volumeDb;
}
@@ -7871,7 +7876,8 @@
auto &voiceCurves = getVolumeCurves(callVolumeSrc);
int voiceVolumeIndex = voiceCurves.getVolumeIndex(deviceTypes);
const float maxVoiceVolDb =
- computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, deviceTypes)
+ computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, deviceTypes,
+ /* computeInternalInteraction= */ false)
+ IN_CALL_EARPIECE_HEADROOM_DB;
// FIXME: Workaround for call screening applications until a proper audio mode is defined
// to support this scenario : Exempt the RING stream from the audio cap if the audio was
@@ -7913,12 +7919,8 @@
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
// just stopped
- // Verify that the current volume source is not the music volume to prevent recursively
- // calling to compute volume. This could happen in cases where music and
- // (alarm, ring, notification, system, etc.) sounds belong to the same volume group.
- if (volumeSource != musicVolumeSrc &&
- (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)
- || mLimitRingtoneVolume)) {
+ if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)
+ || mLimitRingtoneVolume) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
DeviceTypeSet musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
@@ -7927,7 +7929,8 @@
float musicVolDb = computeVolume(musicCurves,
musicVolumeSrc,
musicCurves.getVolumeIndex(musicDevice),
- musicDevice);
+ musicDevice,
+ /* computeInternalInteraction= */ false);
float minVolDb = (musicVolDb > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
musicVolDb : SONIFICATION_HEADSET_VOLUME_MIN_DB;
if (volumeDb > minVolDb) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 0454e6e..50e8ed8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -565,12 +565,36 @@
status_t resetInputDevice(audio_io_handle_t input,
audio_patch_handle_t *patchHandle = NULL);
- // compute the actual volume for a given stream according to the requested index and a particular
- // device
- virtual float computeVolume(IVolumeCurves &curves,
- VolumeSource volumeSource,
- int index,
- const DeviceTypeSet& deviceTypes);
+ /**
+ * Compute volume in DB that should be applied for a volume source and device types for a
+ * particular volume index.
+ *
+ * <p><b>Note:</b>Internally the compute method recursively calls itself to accurately
+ * determine the volume given the currently active sources and devices. Some of the
+ * interaction that require recursive computation are:
+ * <ul>
+ * <li>Match accessibility volume if ringtone volume is much louder</li>
+ * <li>If voice call is active cap other volumes (except ringtone and accessibility)</li>
+ * <li>Attenuate notification if headset is connected to prevent burst in user's ear</li>
+ * <li>Attenuate ringtone if headset is connected and music is not playing and speaker is
+ * part of the devices to prevent burst in user's ear</li>
+ * <li>Limit music volume if headset is connected and notification is also active</li>
+ * </ul>
+ *
+ * @param curves volume curves to use for calculating volume value given the index
+ * @param volumeSource source (use case) of the volume
+ * @param index index to match in the volume curves for the calculation
+ * @param deviceTypes devices that should be considered in the volume curves for the
+ * calculation
+ * @param computeInternalInteraction boolean indicating whether recursive volume computation
+ * should continue within the volume computation. Defaults to {@code true} so the
+ * volume interactions can be computed. Calls within the method should always set the
+ * the value to {@code false} to prevent infinite recursion.
+ * @return computed volume in DB
+ */
+ virtual float computeVolume(IVolumeCurves &curves, VolumeSource volumeSource,
+ int index, const DeviceTypeSet& deviceTypes,
+ bool computeInternalInteraction = true);
// rescale volume index from srcStream within range of dstStream
int rescaleVolumeIndex(int srcIndex,
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 20ea5bb..d65fa8b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -991,12 +991,6 @@
/*out*/ CameraMetadata* outMetadata) {
ATRACE_CALL();
- if (!mInitialized) {
- ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
- logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
- return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
- }
-
if (outMetadata == nullptr) {
std::string msg =
fmt::sprintf("Camera %s: Invalid 'outMetadata' input!", unresolvedCameraId.c_str());
@@ -1004,26 +998,35 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
}
+ if (!mInitialized) {
+ ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
+ logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
+ return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
+ }
+
std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
- devicePolicy, getCallingUid());
+ devicePolicy, getCallingUid());
if (!cameraIdOptional.has_value()) {
std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
- unresolvedCameraId.c_str(), deviceId);
+ unresolvedCameraId.c_str(), deviceId);
ALOGE("%s: %s", __FUNCTION__, msg.c_str());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
}
std::string cameraId = cameraIdOptional.value();
+ if (shouldRejectSystemCameraConnection(cameraId)) {
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
+ "Unable to retrieve camera"
+ "characteristics for system only device %s: ",
+ cameraId.c_str());
+ }
+
bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
mPerfClassPrimaryCameraIds, cameraId, targetSdkVersion);
status_t ret = mCameraProviderManager->getSessionCharacteristics(
cameraId, sessionConfiguration, overrideForPerfClass, overrideToPortrait, outMetadata);
- // TODO(b/303645857): Remove fingerprintable metadata if the caller process does not have
- // camera access permission.
-
- Status res = Status::ok();
switch (ret) {
case OK:
// Expected, no handling needed.
@@ -1033,18 +1036,90 @@
"Camera %s: Session characteristics query not supported!",
cameraId.c_str());
ALOGD("%s: %s", __FUNCTION__, msg.c_str());
- res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
+ logServiceError(msg, CameraService::ERROR_INVALID_OPERATION);
+ outMetadata->clear();
+ return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
+ }
+ break;
+ case NAME_NOT_FOUND: {
+ std::string msg = fmt::sprintf(
+ "Camera %s: Unknown camera ID.",
+ cameraId.c_str());
+ ALOGD("%s: %s", __FUNCTION__, msg.c_str());
+ logServiceError(msg, CameraService::ERROR_ILLEGAL_ARGUMENT);
+ outMetadata->clear();
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
}
break;
default: {
- std::string msg = fmt::sprintf("Camera %s: Error: %s (%d)", cameraId.c_str(),
- strerror(-ret), ret);
+ std::string msg = fmt::sprintf(
+ "Unable to retrieve session characteristics for camera device %s: "
+ "Error: %s (%d)",
+ cameraId.c_str(), strerror(-ret), ret);
ALOGE("%s: %s", __FUNCTION__, msg.c_str());
- res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ logServiceError(msg, CameraService::ERROR_INVALID_OPERATION);
+ outMetadata->clear();
+ return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
}
}
- return res;
+ return filterSensitiveMetadataIfNeeded(cameraId, outMetadata);
+}
+
+Status CameraService::filterSensitiveMetadataIfNeeded(
+ const std::string& cameraId, CameraMetadata* metadata) {
+ int callingPid = getCallingPid();
+ int callingUid = getCallingUid();
+
+ if (callingPid == getpid()) {
+ // Caller is cameraserver; no need to remove keys
+ return Status::ok();
+ }
+
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+ ALOGE("%s: Couldn't get camera kind for camera id %s", __FUNCTION__, cameraId.c_str());
+ metadata->clear();
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
+ "Unable to retrieve camera kind for device %s", cameraId.c_str());
+ }
+ if (deviceKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+ // Attempting to query system only camera without system camera permission would have
+ // failed the shouldRejectSystemCameraConnection in the caller. So if we get here
+ // for a system only camera, then the caller has the required permission.
+ // No need to remove keys
+ return Status::ok();
+ }
+
+ std::vector<int32_t> tagsRemoved;
+ bool hasCameraPermission = hasPermissionsForCamera(cameraId, callingPid, callingUid);
+ if (hasCameraPermission) {
+ // Caller has camera permission; no need to remove keys
+ return Status::ok();
+ }
+
+ status_t ret = metadata->removePermissionEntries(
+ mCameraProviderManager->getProviderTagIdLocked(cameraId), &tagsRemoved);
+ if (ret != OK) {
+ metadata->clear();
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
+ "Failed to remove camera characteristics needing camera permission "
+ "for device %s:%s (%d)",
+ cameraId.c_str(), strerror(-ret), ret);
+ }
+
+ if (!tagsRemoved.empty()) {
+ ret = metadata->update(ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION,
+ tagsRemoved.data(), tagsRemoved.size());
+ if (ret != OK) {
+ metadata->clear();
+ return STATUS_ERROR_FMT(
+ ERROR_INVALID_OPERATION,
+ "Failed to insert camera keys needing permission for device %s: %s (%d)",
+ cameraId.c_str(), strerror(-ret), ret);
+ }
+ }
+ return Status::ok();
}
Status CameraService::parseCameraIdRemapping(
@@ -1381,8 +1456,6 @@
"characteristics for system only device %s: ", cameraId.c_str());
}
- Status ret{};
-
bool overrideForPerfClass =
SessionConfigurationUtils::targetPerfClassPrimaryCamera(mPerfClassPrimaryCameraIds,
cameraId, targetSdkVersion);
@@ -1401,45 +1474,8 @@
strerror(-res), res);
}
}
- SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
- if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
- ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.c_str());
- return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera kind "
- "for device %s", cameraId.c_str());
- }
- int callingPid = getCallingPid();
- int callingUid = getCallingUid();
- std::vector<int32_t> tagsRemoved;
- // If it's not calling from cameraserver, check the permission only if
- // android.permission.CAMERA is required. If android.permission.SYSTEM_CAMERA was needed,
- // it would've already been checked in shouldRejectSystemCameraConnection.
- bool checkPermissionForCamera = hasPermissionsForCamera(cameraId, callingPid, callingUid);
- if ((callingPid != getpid()) &&
- (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
- !checkPermissionForCamera) {
- res = cameraInfo->removePermissionEntries(
- mCameraProviderManager->getProviderTagIdLocked(cameraId),
- &tagsRemoved);
- if (res != OK) {
- cameraInfo->clear();
- return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to remove camera"
- " characteristics needing camera permission for device %s: %s (%d)",
- cameraId.c_str(), strerror(-res), res);
- }
- }
- if (!tagsRemoved.empty()) {
- res = cameraInfo->update(ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION,
- tagsRemoved.data(), tagsRemoved.size());
- if (res != OK) {
- cameraInfo->clear();
- return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to insert camera "
- "keys needing permission for device %s: %s (%d)", cameraId.c_str(),
- strerror(-res), res);
- }
- }
-
- return ret;
+ return filterSensitiveMetadataIfNeeded(cameraId, cameraInfo);
}
Status CameraService::getTorchStrengthLevel(const std::string& unresolvedCameraId, int32_t deviceId,
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index b4c2edd..e1bc726 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -1529,6 +1529,12 @@
// responsibility to acquire mLogLock before calling this functions.
bool isClientWatchedLocked(const BasicClient *client);
+ // Filters out fingerprintable keys if the calling process does not have CAMERA permission.
+ // Note: function caller should ensure that shouldRejectSystemCameraConnection is checked
+ // for the calling process before calling this function.
+ binder::Status filterSensitiveMetadataIfNeeded(const std::string& cameraId,
+ CameraMetadata* metadata);
+
/**
* Get the current system time as a formatted string.
*/
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.cpp b/services/camera/libcameraservice/aidl/AidlUtils.cpp
index 14e5fad..48d78e1 100644
--- a/services/camera/libcameraservice/aidl/AidlUtils.cpp
+++ b/services/camera/libcameraservice/aidl/AidlUtils.cpp
@@ -18,6 +18,7 @@
#include <aidl/AidlUtils.h>
#include <aidl/ExtensionMetadataTags.h>
+#include <aidl/SessionCharacteristicsTags.h>
#include <aidl/VndkVersionMetadataTags.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <camera/StringUtils.h>
@@ -334,6 +335,49 @@
return OK;
}
+status_t copySessionCharacteristics(const CameraMetadata& from, CameraMetadata* to,
+ int queryVersion) {
+ // Ensure the vendor ID are the same before attempting
+ // anything else. If vendor IDs differ we cannot safely copy the characteristics.
+ if (from.getVendorId() != to->getVendorId()) {
+ ALOGE("%s: Incompatible CameraMetadata objects. Vendor IDs differ. From: %lu; To: %lu",
+ __FUNCTION__, from.getVendorId(), to->getVendorId());
+ return BAD_VALUE;
+ }
+
+ // Allow public tags according to the queryVersion
+ std::unordered_set<uint32_t> validPublicTags;
+ auto last = api_level_to_session_characteristic_keys.upper_bound(queryVersion);
+ for (auto it = api_level_to_session_characteristic_keys.begin(); it != last; it++) {
+ validPublicTags.insert(it->second.cbegin(), it->second.cend());
+ }
+
+ const camera_metadata_t* src = from.getAndLock();
+ camera_metadata_ro_entry_t entry{};
+ for (size_t i = 0; i < get_camera_metadata_entry_count(src); i++) {
+ int ret = get_camera_metadata_ro_entry(src, i, &entry);
+ if (ret != OK) {
+ ALOGE("%s: Could not fetch entry at index %lu. Error: %d", __FUNCTION__, i, ret);
+ from.unlock(src);
+ return BAD_VALUE;
+ }
+
+ if (entry.tag < (uint32_t)VENDOR_SECTION_START &&
+ validPublicTags.find(entry.tag) == validPublicTags.end()) {
+ ALOGI("%s: Session Characteristics contains tag %s but not supported by query version "
+ "(%d)",
+ __FUNCTION__, get_camera_metadata_tag_name(entry.tag), queryVersion);
+ continue;
+ }
+
+ // The entry is either a vendor tag, or a valid session characteristic key.
+ // Copy over the value
+ to->update(entry);
+ }
+ from.unlock(src);
+ return OK;
+}
+
bool areExtensionKeysSupported(const CameraMetadata& metadata) {
auto requestKeys = metadata.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
if (requestKeys.count == 0) {
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.h b/services/camera/libcameraservice/aidl/AidlUtils.h
index 562aa70..92e878e 100644
--- a/services/camera/libcameraservice/aidl/AidlUtils.h
+++ b/services/camera/libcameraservice/aidl/AidlUtils.h
@@ -122,6 +122,9 @@
status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic = true);
+status_t copySessionCharacteristics(const CameraMetadata& from, CameraMetadata* to,
+ int queryVersion);
+
bool areExtensionKeysSupported(const CameraMetadata& metadata);
status_t filterExtensionKeys(CameraMetadata* metadata /*out*/);
diff --git a/services/camera/libcameraservice/aidl/SessionCharacteristicsTags.h b/services/camera/libcameraservice/aidl/SessionCharacteristicsTags.h
new file mode 100644
index 0000000..cefb8a6
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/SessionCharacteristicsTags.h
@@ -0,0 +1,37 @@
+/*
+ * 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 <map>
+#include <vector>
+#pragma once
+/**
+ * ! Do not edit this file directly !
+ *
+ * Generated automatically from session_characteristics_tags.mako. To be included in
+ * libcameraservice only by aidl/AidlUtils.cpp.
+ */
+
+/**
+ * Mapping of session characteristics to the INFO_SESSION_CONFIGURATION_QUERY_VERSION value
+ * at which they were introduced.
+ */
+std::map<int, std::vector<camera_metadata_tag>> api_level_to_session_characteristic_keys {
+ {35,
+ {
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE,
+ ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+ }},
+};
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index d4b32e8..89e785a 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1858,7 +1858,7 @@
auto& c = mCameraCharacteristics;
status_t res = c.update(ANDROID_INFO_SESSION_CONFIGURATION_QUERY_VERSION, &versionCode, 1);
-
+ mSessionConfigQueryVersion = versionCode;
return res;
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 1a686bd..2e97207 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -654,8 +654,7 @@
virtual status_t getSessionCharacteristics(
const SessionConfiguration &/*configuration*/,
bool /*overrideForPerfClass*/,
- camera3::metadataGetter /*getMetadata*/,
- CameraMetadata* /*sessionCharacteristics*/) {
+ camera3::metadataGetter /*getMetadata*/, CameraMetadata* /*outChars*/) {
return INVALID_OPERATION;
}
@@ -737,6 +736,10 @@
// Only contains characteristics for hidden physical cameras,
// not for public physical cameras.
std::unordered_map<std::string, CameraMetadata> mPhysicalCameraCharacteristics;
+ // Value filled in from addSessionConfigQueryVersionTag.
+ // Cached to make lookups faster
+ int mSessionConfigQueryVersion = 0;
+
void queryPhysicalCameraIds();
SystemCameraKind getSystemCameraKind();
status_t fixupMonochromeTags();
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 8eaa7b4..5b24227 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -17,6 +17,8 @@
#include "common/HalConversionsTemplated.h"
#include "common/CameraProviderInfoTemplated.h"
+#include <aidl/AidlUtils.h>
+
#include <com_android_internal_camera_flags.h>
#include <cutils/properties.h>
@@ -43,6 +45,7 @@
using namespace aidl::android::hardware;
using namespace hardware::camera;
+using android::hardware::cameraservice::utils::conversion::aidl::copySessionCharacteristics;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
using hardware::ICameraService;
using SessionConfigurationUtils::overrideDefaultRequestKeys;
@@ -927,7 +930,7 @@
status_t AidlProviderInfo::AidlDeviceInfo3::getSessionCharacteristics(
const SessionConfiguration &configuration, bool overrideForPerfClass,
- camera3::metadataGetter getMetadata, CameraMetadata *sessionCharacteristics) {
+ camera3::metadataGetter getMetadata, CameraMetadata* outChars) {
camera::device::StreamConfiguration streamConfiguration;
bool earlyExit = false;
auto res = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
@@ -953,24 +956,32 @@
aidl::android::hardware::camera::device::CameraMetadata chars;
::ndk::ScopedAStatus ret =
interface->getSessionCharacteristics(streamConfiguration, &chars);
- std::vector<uint8_t> &metadata = chars.metadata;
+ if (!ret.isOk()) {
+ ALOGE("%s: Unexpected binder error while getting session characteristics (%d): %s",
+ __FUNCTION__, ret.getExceptionCode(), ret.getMessage());
+ return mapToStatusT(ret);
+ }
- camera_metadata_t *buffer = reinterpret_cast<camera_metadata_t*>(metadata.data());
+ std::vector<uint8_t> &metadata = chars.metadata;
+ auto *buffer = reinterpret_cast<camera_metadata_t*>(metadata.data());
size_t expectedSize = metadata.size();
int resV = validate_camera_metadata_structure(buffer, &expectedSize);
if (resV == OK || resV == CAMERA_METADATA_VALIDATION_SHIFTED) {
set_camera_metadata_vendor_id(buffer, mProviderTagid);
- *sessionCharacteristics = buffer;
} else {
ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
return BAD_VALUE;
}
- if (!ret.isOk()) {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.getMessage());
- return mapToStatusT(ret);
- }
- return OK;
+ CameraMetadata rawSessionChars;
+ rawSessionChars = buffer; // clone buffer
+ rawSessionChars.sort(); // sort for faster lookups
+
+ *outChars = mCameraCharacteristics;
+ outChars->sort(); // sort for faster reads and (hopefully!) writes
+
+ return copySessionCharacteristics(/*from=*/rawSessionChars, /*to=*/outChars,
+ mSessionConfigQueryVersion);
}
status_t AidlProviderInfo::convertToAidlHALStreamCombinationAndCameraIdsLocked(
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
index 38ebc94..f5e0db0 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
@@ -137,7 +137,7 @@
virtual status_t getSessionCharacteristics(
const SessionConfiguration &/*configuration*/,
bool overrideForPerfClass, camera3::metadataGetter /*getMetadata*/,
- CameraMetadata *sessionCharacteristics /*sessionCharacteristics*/);
+ CameraMetadata */*outChars*/);
std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
startDeviceInterface();
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 8c6fa8f..3cd4543 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1030,7 +1030,8 @@
status_t Camera3OutputStream::getEndpointUsageForSurface(uint64_t *usage,
const sp<Surface>& surface) {
- if (mConsumerUsageCachedValue.has_value() && flags::surface_ipc()) {
+ bool internalConsumer = (mConsumer.get() != nullptr) && (mConsumer == surface);
+ if (mConsumerUsageCachedValue.has_value() && flags::surface_ipc() && internalConsumer) {
*usage = mConsumerUsageCachedValue.value();
return OK;
}
@@ -1039,7 +1040,9 @@
res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(surface.get()), usage);
applyZSLUsageQuirk(camera_stream::format, usage);
- mConsumerUsageCachedValue = *usage;
+ if (internalConsumer) {
+ mConsumerUsageCachedValue = *usage;
+ }
return res;
}