diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
index 83c7f0d0..ceb5cfe8 100644
--- a/src/android/camera_capabilities.cpp
+++ b/src/android/camera_capabilities.cpp
@@ -262,6 +262,149 @@ std::vector<T> setMetadata(CameraMetadata *metadata, uint32_t tag,
 	return ret;
 }
 
+
+template<typename T>
+bool metadataContains(camera_metadata_ro_entry_t &entry, T value);
+
+template<>
+bool metadataContains<uint8_t>(camera_metadata_ro_entry_t &entry, uint8_t value)
+{
+	for (unsigned int i = 0; i < entry.count; i++)
+		if (entry.data.u8[i] == value)
+			return true;
+
+	return false;
+}
+
+bool validateManualSensorCapability(CameraMetadata *staticMetadata)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
+					 &entry);
+	if (!found || !metadataContains<uint8_t>(entry, ANDROID_CONTROL_AE_MODE_OFF)) {
+		LOG(HAL, Info)
+			<< "Missing AE mode off: "
+			<< (found ? "not supported" : "not found");
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AE lock";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+					 &entry);
+	if (!found) {
+		LOG(HAL, Info) << "Missing edge modes";
+		return false;
+	}
+
+	return true;
+}
+
+bool validateManualPostProcessingCapability(CameraMetadata *staticMetadata)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+					 &entry);
+	if (!found || !metadataContains<uint8_t>(entry, ANDROID_CONTROL_AWB_MODE_OFF)) {
+		LOG(HAL, Info) << "Missing AWB mode off";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AWB lock";
+		return false;
+	}
+
+	return true;
+}
+
+bool validateBurstCaptureCapability(CameraMetadata *staticMetadata)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AE lock";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+					 &entry);
+	if (!found || !(*entry.data.u8 == ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE)) {
+		LOG(HAL, Info) << "Missing AWB lock";
+		return false;
+	}
+
+	found = staticMetadata->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry);
+	if (!found || *entry.data.i32 < 0 || 4 < *entry.data.i32) {
+		LOG(HAL, Info)
+			<< "Max sync latency is "
+			<< (found ? std::to_string(*entry.data.i32) : "not present");
+		return false;
+	}
+
+	return true;
+}
+
+std::set<camera_metadata_enum_android_request_available_capabilities>
+computeCapabilities(CameraMetadata *staticMetadata,
+		    std::set<camera_metadata_enum_android_request_available_capabilities> &existingCaps)
+{
+	std::set<camera_metadata_enum_android_request_available_capabilities>
+	capabilities = existingCaps;
+
+	capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
+
+	if (validateManualSensorCapability(staticMetadata))
+		capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
+
+	if (validateManualPostProcessingCapability(staticMetadata))
+		capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
+
+	if (validateBurstCaptureCapability(staticMetadata))
+		capabilities.insert(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
+
+	return capabilities;
+}
+
+camera_metadata_enum_android_info_supported_hardware_level
+computeHwLevel(CameraMetadata *staticMetadata,
+	       std::set<camera_metadata_enum_android_request_available_capabilities> capabilities)
+{
+	camera_metadata_ro_entry_t entry;
+	bool found;
+	camera_metadata_enum_android_info_supported_hardware_level
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
+
+	if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR))
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING))
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	if (!capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE))
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	found = staticMetadata->getEntry(ANDROID_SYNC_MAX_LATENCY, &entry);
+	if (!found || *entry.data.i32 != 0)
+		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+
+	return hwLevel;
+}
+
 } /* namespace */
 
 int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera,
@@ -655,17 +798,7 @@ int CameraCapabilities::initializeStaticMetadata()
 	};
 
 	std::set<camera_metadata_enum_android_request_available_capabilities>
-	capabilities = {
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
-		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
-	};
-
-	std::set<camera_metadata_enum_android_info_supported_hardware_level>
-	hwLevels = {
-		ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
-	};
+	capabilities = {};
 
 	/* Color correction static metadata. */
 	{
@@ -692,19 +825,12 @@ int CameraCapabilities::initializeStaticMetadata()
 	staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
 				  aeAvailableAntiBandingModes);
 
-	std::vector<uint8_t> aeModes = setMetadata<uint8_t, bool>(
+	setMetadata<uint8_t, bool>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AE_AVAILABLE_MODES,
 		controlsInfo, &controls::AeEnable,
 		{ ANDROID_CONTROL_AE_MODE_ON });
 
-	if (std::find(aeModes.begin(), aeModes.end(),
-		      ANDROID_CONTROL_AE_MODE_OFF) == aeModes.end()) {
-		LOG(HAL, Info) << "AE cannot be turned off";
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
-	}
-
 	int64_t minFrameDurationNsec = -1;
 	int64_t maxFrameDurationNsec = -1;
 	const auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);
@@ -791,17 +917,11 @@ int CameraCapabilities::initializeStaticMetadata()
 	staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
 				  availableStabilizationModes);
 
-	std::vector<uint8_t> awbModes = setMetadata<uint8_t, int32_t>(
+	setMetadata<uint8_t, int32_t>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AWB_AVAILABLE_MODES,
 		controlsInfo, &controls::AwbMode,
 		{ ANDROID_CONTROL_AWB_MODE_AUTO });
-	if (std::find(awbModes.begin(), awbModes.end(),
-		      ANDROID_CONTROL_AWB_MODE_OFF) == awbModes.end()) {
-		LOG(HAL, Info) << "AWB cannot be turned off";
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
-	}
 
 	std::vector<int32_t> availableMaxRegions = {
 		0, 0, 0,
@@ -817,29 +937,19 @@ int CameraCapabilities::initializeStaticMetadata()
 	staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
 				  sceneModesOverride);
 
-	uint8_t aeLockAvailable = setMetadata<uint8_t, bool>(
+	setMetadata<uint8_t, bool>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AE_LOCK_AVAILABLE,
 		controlsInfo, &controls::AeLock,
 		ControlRange::Max,
 		ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE);
-	if (aeLockAvailable != ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE) {
-		LOG(HAL, Info) << "AE lock is unavailable";
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
-	}
 
-	uint8_t awbLockAvailable = setMetadata<uint8_t, bool>(
+	setMetadata<uint8_t, bool>(
 		staticMetadata_.get(),
 		ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
 		controlsInfo, &controls::AwbLock,
 		ControlRange::Max,
 		ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE);
-	if (awbLockAvailable != ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE) {
-		LOG(HAL, Info) << "AWB lock is unavailable";
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
-	}
 
 	char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
 	staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
@@ -859,10 +969,6 @@ int CameraCapabilities::initializeStaticMetadata()
 		availableCharacteristicsKeys_.insert(ANDROID_EDGE_AVAILABLE_EDGE_MODES);
 		availableRequestKeys_.insert(ANDROID_EDGE_MODE);
 		availableResultKeys_.insert(ANDROID_EDGE_MODE);
-	} else {
-		LOG(HAL, Info) << "Edge mode unavailable";
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
 	}
 
 	/* JPEG static metadata. */
@@ -1046,17 +1152,11 @@ int CameraCapabilities::initializeStaticMetadata()
 	}
 
 	/* Sync static metadata. */
-	int32_t maxLatency = setMetadata<int32_t, int32_t>(
+	setMetadata<int32_t, int32_t>(
 		staticMetadata_.get(), ANDROID_SYNC_MAX_LATENCY,
 		controlsInfo, &controls::draft::MaxLatency,
 		ControlRange::Def,
 		ANDROID_SYNC_MAX_LATENCY_UNKNOWN);
-	LOG(HAL, Info) << "Max sync latency is " << maxLatency;
-	/* CTS allows a sync latency of up to 4 for burst capture capability */
-	if (maxLatency < 0 || 4 < maxLatency)
-		capabilities.erase(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
-	if (maxLatency != 0)
-		hwLevels.erase(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
 
 	/* Flash static metadata. */
 	char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
@@ -1220,19 +1320,14 @@ int CameraCapabilities::initializeStaticMetadata()
 				  numOutStreams);
 
 	/* Check capabilities */
-	std::vector<uint8_t> availableCapabilities(capabilities.begin(),
-						   capabilities.end());
-	staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
-				  availableCapabilities);
-
-	uint8_t hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
-	if (capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) &&
-	    capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING) &&
-	    capabilities.count(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) &&
-	    hwLevels.count(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL))
-		hwLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
-	staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
-				  hwLevel);
+	capabilities = computeCapabilities(staticMetadata_.get(), capabilities);
+	std::vector<camera_metadata_enum_android_request_available_capabilities>
+		capsVec = std::vector<camera_metadata_enum_android_request_available_capabilities>(capabilities.begin(), capabilities.end());
+	staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capsVec);
+
+	camera_metadata_enum_android_info_supported_hardware_level hwLevel =
+		computeHwLevel(staticMetadata_.get(), capabilities);
+	staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, hwLevel);
 
 	LOG(HAL, Info)
 		<< "Hardware level: "
