Camera: Remove small JPEG sizes for performance class primary cameras
For Performance class 12 primary camers, the minimum supported JPEG
resolutions shoould be 1080p.
Filter out JPEG sizes smaller than 1080p from supported stream configurations.
This makes the change in behavior transparent to the camera HAL.
Test: Camera CTS
Bug: 186046918
Change-Id: Ica9cd5f4cdba2d18c7295f0ccb04e3eafd33f41d
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 329400d..83d2bc9 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -232,6 +232,10 @@
}
}
+ //Derive primary rear/front cameras, and filter their charactierstics.
+ //This needs to be done after all cameras are enumerated and camera ids are sorted.
+ filterSPerfClassCharacteristics();
+
return OK;
}
@@ -302,6 +306,45 @@
filterAPI1SystemCameraLocked(mNormalDeviceIds);
}
+void CameraService::filterSPerfClassCharacteristics() {
+ static int32_t kPerformanceClassLevel =
+ property_get_int32("ro.odm.build.media_performance_class", 0);
+ static bool kIsSPerformanceClass = (kPerformanceClassLevel == 31);
+
+ if (!kIsSPerformanceClass) return;
+
+ // To claim to be S Performance primary cameras, the cameras must be
+ // backward compatible. So performance class primary camera Ids must be API1
+ // compatible.
+ bool firstRearCameraSeen = false, firstFrontCameraSeen = false;
+ for (const auto& cameraId : mNormalDeviceIdsWithoutSystemCamera) {
+ int facing = -1;
+ int orientation = 0;
+ String8 cameraId8(cameraId.c_str());
+ getDeviceVersion(cameraId8, /*out*/&facing, /*out*/&orientation);
+ if (facing == -1) {
+ ALOGE("%s: Unable to get camera device \"%s\" facing", __FUNCTION__, cameraId.c_str());
+ return;
+ }
+
+ if ((facing == hardware::CAMERA_FACING_BACK && !firstRearCameraSeen) ||
+ (facing == hardware::CAMERA_FACING_FRONT && !firstFrontCameraSeen)) {
+ mCameraProviderManager->filterSmallJpegSizes(cameraId);
+
+ if (facing == hardware::CAMERA_FACING_BACK) {
+ firstRearCameraSeen = true;
+ }
+ if (facing == hardware::CAMERA_FACING_FRONT) {
+ firstFrontCameraSeen = true;
+ }
+ }
+
+ if (firstRearCameraSeen && firstFrontCameraSeen) {
+ break;
+ }
+ }
+}
+
void CameraService::addStates(const String8 id) {
std::string cameraId(id.c_str());
hardware::camera::common::V1_0::CameraResourceCost cost;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 22dd0db..d1ed59a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -935,6 +935,11 @@
*/
void updateCameraNumAndIds();
+ /**
+ * Filter camera characteristics for S Performance class primary cameras
+ */
+ void filterSPerfClassCharacteristics();
+
// Number of camera devices (excluding hidden secure cameras)
int mNumberOfCameras;
// Number of camera devices (excluding hidden secure cameras and
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 6dffc5d..46e5d6d 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1186,6 +1186,17 @@
return isHiddenPhysicalCameraInternal(cameraId).first;
}
+void CameraProviderManager::filterSmallJpegSizes(const std::string& cameraId) {
+ for (auto& provider : mProviders) {
+ for (auto& deviceInfo : provider->mDevices) {
+ if (deviceInfo->mId == cameraId) {
+ deviceInfo->filterSmallJpegSizes();
+ return;
+ }
+ }
+ }
+}
+
std::pair<bool, CameraProviderManager::ProviderInfo::DeviceInfo *>
CameraProviderManager::isHiddenPhysicalCameraInternal(const std::string& cameraId) const {
auto falseRet = std::make_pair(false, nullptr);
@@ -2562,6 +2573,70 @@
return res;
}
+void CameraProviderManager::ProviderInfo::DeviceInfo3::filterSmallJpegSizes() {
+ static constexpr int FHD_W = 1920;
+ static constexpr int FHD_H = 1080;
+
+ // Remove small JPEG sizes from available stream configurations
+ std::vector<int32_t> newStreamConfigs;
+ camera_metadata_entry streamConfigs =
+ mCameraCharacteristics.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ for (size_t i = 0; i < streamConfigs.count; i += 4) {
+ if ((streamConfigs.data.i32[i] == HAL_PIXEL_FORMAT_BLOB) && (streamConfigs.data.i32[i+3] ==
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) &&
+ (streamConfigs.data.i32[i+1] < FHD_W || streamConfigs.data.i32[i+2] < FHD_H)) {
+ continue;
+ }
+ newStreamConfigs.insert(newStreamConfigs.end(), streamConfigs.data.i32 + i,
+ streamConfigs.data.i32 + i + 4);
+ }
+ if (newStreamConfigs.size() > 0) {
+ mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ newStreamConfigs.data(), newStreamConfigs.size());
+ }
+
+ // Remove small JPEG sizes from available min frame durations
+ std::vector<int64_t> newMinDurations;
+ camera_metadata_entry minDurations =
+ mCameraCharacteristics.find(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
+ for (size_t i = 0; i < minDurations.count; i += 4) {
+ if ((minDurations.data.i64[i] == HAL_PIXEL_FORMAT_BLOB) &&
+ (minDurations.data.i64[i+1] < FHD_W || minDurations.data.i64[i+2] < FHD_H)) {
+ continue;
+ }
+ newMinDurations.insert(newMinDurations.end(), minDurations.data.i64 + i,
+ minDurations.data.i64 + i + 4);
+ }
+ if (newMinDurations.size() > 0) {
+ mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ newMinDurations.data(), newMinDurations.size());
+ }
+
+ // Remove small JPEG sizes from available stall durations
+ std::vector<int64_t> newStallDurations;
+ camera_metadata_entry stallDurations =
+ mCameraCharacteristics.find(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS);
+ for (size_t i = 0; i < stallDurations.count; i += 4) {
+ if ((stallDurations.data.i64[i] == HAL_PIXEL_FORMAT_BLOB) &&
+ (stallDurations.data.i64[i+1] < FHD_W || stallDurations.data.i64[i+2] < FHD_H)) {
+ continue;
+ }
+ newStallDurations.insert(newStallDurations.end(), stallDurations.data.i64 + i,
+ stallDurations.data.i64 + i + 4);
+ }
+ if (newStallDurations.size() > 0) {
+ mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+ newStallDurations.data(), newStallDurations.size());
+ }
+
+ // Re-generate metadata tags that have dependencies on BLOB sizes
+ auto res = addDynamicDepthTags();
+ if (OK != res) {
+ ALOGE("%s: Failed to append dynamic depth tags: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ }
+}
+
status_t CameraProviderManager::ProviderInfo::parseProviderName(const std::string& name,
std::string *type, uint32_t *id) {
// Format must be "<type>/<id>"
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 5531dd7..4fde556 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -327,6 +327,8 @@
status_t getSystemCameraKind(const std::string& id, SystemCameraKind *kind) const;
bool isHiddenPhysicalCamera(const std::string& cameraId) const;
+ void filterSmallJpegSizes(const std::string& cameraId);
+
static const float kDepthARTolerance;
private:
// All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
@@ -486,6 +488,7 @@
bool * /*status*/) {
return INVALID_OPERATION;
}
+ virtual void filterSmallJpegSizes() = 0;
template<class InterfaceT>
sp<InterfaceT> startDeviceInterface();
@@ -544,6 +547,7 @@
const hardware::camera::device::V3_7::StreamConfiguration &configuration,
bool *status /*out*/)
override;
+ virtual void filterSmallJpegSizes() override;
DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion,