| /* |
| * Copyright 2019 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "common/camera_metrics_impl.h" |
| |
| #include <algorithm> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <base/strings/string_split.h> |
| #include <base/strings/string_util.h> |
| #include <base/strings/stringprintf.h> |
| #include <base/system/sys_info.h> |
| #include <hardware/camera3.h> |
| #include <system/graphics.h> |
| |
| #include "camera/mojo/cros_camera_service.mojom.h" |
| #include "cros-camera/common.h" |
| |
| namespace cros { |
| |
| namespace { |
| |
| constexpr char kCameraJpegProcessLatency[] = |
| "ChromeOS.Camera.Jpeg.Latency.%s.%s"; |
| constexpr base::TimeDelta kMinLatency = base::Microseconds(1); |
| constexpr base::TimeDelta kMaxLatency = base::Seconds(1); |
| constexpr int kBucketLatency = 100; |
| |
| constexpr char kCameraJpegResolution[] = |
| "ChromeOS.Camera.Jpeg.Resolution.%s.%s"; |
| constexpr int kMinResolutionInPixels = 1; |
| constexpr int kMaxResolutionInPixels = 15000000; // 15 MegaPixels. |
| constexpr int kBucketResolutionInPixels = 50; |
| |
| constexpr char kCameraConfigureStreamsLatency[] = |
| "ChromeOS.Camera.ConfigureStreamsLatency"; |
| |
| constexpr char kCameraConfigureStreamsResolution[] = |
| "ChromeOS.Camera.ConfigureStreams.Output.Resolution.%s"; |
| |
| constexpr char kCameraOpenDeviceClientType[] = |
| "ChromeOS.Camera.OpenDeviceClientType"; |
| constexpr char kNumClientTypes = |
| static_cast<int32_t>(mojom::CameraClientType::kMaxValue) + 1; |
| |
| constexpr char kCameraOpenDeviceLatency[] = "ChromeOS.Camera.OpenDeviceLatency"; |
| |
| constexpr char kCameraErrorType[] = "ChromeOS.Camera.ErrorType"; |
| |
| constexpr char kCameraFacing[] = "ChromeOS.Camera.Facing"; |
| // Includes CAMERA_FACING_BACK, CAMERA_FACING_FRONT and CAMERA_FACING_EXTERNAL. |
| constexpr int kNumCameraFacings = 3; |
| |
| constexpr char kCameraSessionDuration[] = "ChromeOS.Camera.SessionDuration"; |
| constexpr base::TimeDelta kMinCameraSessionDuration = base::Seconds(1); |
| constexpr base::TimeDelta kMaxCameraSessionDuration = base::Days(1); |
| constexpr int kBucketCameraSessionDuration = 100; |
| |
| constexpr char kCameraFaceAeFunction[] = |
| "ChromeOS.Camera.FaceAutoExposure.FunctionStatus"; |
| // max number of faces detected times in a camera session |
| constexpr char kCameraFaceAeMaxDetectedFaces[] = |
| "ChromeOS.Camera.FaceAutoExposure.MaxNumDetectedFaces"; |
| constexpr int kMaxNumFaces = 10; |
| |
| // *** HDRnet metrics *** |
| |
| constexpr char kHdrnetStreamTypeYuv[] = "YUV"; |
| constexpr char kHdrnetStreamTypeBlob[] = "BLOB"; |
| |
| constexpr char kHdrnetProcessingTypePreprocessing[] = "Preprocessing"; |
| constexpr char kHdrnetProcessingTypeRgbPipeline[] = "RgbPipeline"; |
| constexpr char kHdrnetProcessingTypePostprocessing[] = "Postprocessing"; |
| |
| constexpr char kCameraHdrnetStreamConfiguration[] = |
| "ChromeOS.Camera.HDRnet.StreamConfiguration"; |
| |
| constexpr char kCameraHdrnetMaxStreamSize[] = |
| "ChromeOS.Camera.HDRnet.MaxStreamSize.%s"; |
| constexpr char kCameraHdrnetNumConcurrentStreams[] = |
| "ChromeOS.Camera.HDRnet.NumConcurrentStreams"; |
| constexpr int kMinNumConcurrentHdrnetStreams = 1; |
| constexpr int kMaxNumConcurrentHdrnetStreams = 4; |
| constexpr int kNumConcurrentCameraStreamsBuckets = 4; |
| |
| constexpr char kCameraHdrnetMaxOutputBuffersRendered[] = |
| "ChromeOS.Camera.HDRnet.MaxOutputBuffersRendered"; |
| constexpr int kMinNumOutputBuffers = 1; |
| constexpr int kMaxNumOutputBuffers = 4; |
| constexpr int kNumOutputBuffersBuckets = 4; |
| |
| constexpr char kCameraHdrnetError[] = "ChromeOS.Camera.HDRnet.Error"; |
| |
| constexpr char kCameraHdrnetNumStillShotsTaken[] = |
| "ChromeOS.Camera.HDRnet.NumStillShotsTaken"; |
| constexpr int kMinNumShotsTaken = 0; |
| constexpr int kMaxNumShotsTaken = 1000; |
| constexpr int kNumShotsTakenBuckets = 10; |
| |
| constexpr char kCameraHdrnetAvgLatency[] = |
| "ChromeOS.Camera.HDRnet.AverageLatency.%s"; |
| constexpr int kMinHdrnetLatencyUs = 1; |
| constexpr int kMaxHdrnetLatencyUs = 50000; |
| constexpr int kHdrnetLatencyBuckets = 50; |
| |
| // *** Gcam AE metrics *** |
| |
| constexpr char kCameraGcamAeAvgConvergenceLatency[] = |
| "ChromeOS.Camera.GcamAutoExposure.AverageConvergenceLatency"; |
| constexpr int kMinConvergenceLatencyFrames = 1; |
| constexpr int kMaxConvergenceLatencyFrames = 3000; |
| constexpr int kConvergenceLatencyBuckets = 50; |
| |
| constexpr char kCameraGcamAeAvgHdrRatio[] = |
| "ChromeOS.Camera.GcamAutoExposure.AverageHdrRatio"; |
| constexpr int kMinHdrRatio = 1; |
| constexpr int kMaxHdrRatio = 30; |
| constexpr int kHdrRatioBuckets = 15; |
| |
| constexpr char kCameraGcamAeAvgTet[] = |
| "ChromeOS.Camera.GcamAutoExposure.AverageTet"; |
| constexpr int kMinTet = 1; |
| constexpr int kMaxTet = 10000; |
| constexpr int kTetBuckets = 50; |
| |
| } // namespace |
| |
| // static |
| std::unique_ptr<CameraMetrics> CameraMetrics::New() { |
| return std::make_unique<CameraMetricsImpl>(); |
| } |
| |
| CameraMetricsImpl::CameraMetricsImpl() |
| : metrics_lib_(std::make_unique<MetricsLibrary>()) {} |
| |
| CameraMetricsImpl::~CameraMetricsImpl() = default; |
| |
| void CameraMetricsImpl::SetMetricsLibraryForTesting( |
| std::unique_ptr<MetricsLibraryInterface> metrics_lib) { |
| metrics_lib_ = std::move(metrics_lib); |
| } |
| |
| void CameraMetricsImpl::SendJpegProcessLatency(JpegProcessType process_type, |
| JpegProcessMethod process_layer, |
| base::TimeDelta latency) { |
| std::string action_name = base::StringPrintf( |
| kCameraJpegProcessLatency, |
| (process_layer == JpegProcessMethod::kHardware ? "Hardware" : "Software"), |
| (process_type == JpegProcessType::kDecode ? "Decode" : "Encode")); |
| metrics_lib_->SendToUMA(action_name, latency.InMicroseconds(), |
| kMinLatency.InMicroseconds(), |
| kMaxLatency.InMicroseconds(), kBucketLatency); |
| } |
| |
| void CameraMetricsImpl::SendJpegResolution(JpegProcessType process_type, |
| JpegProcessMethod process_layer, |
| int width, |
| int height) { |
| std::string action_name = base::StringPrintf( |
| kCameraJpegResolution, |
| (process_layer == JpegProcessMethod::kHardware ? "Hardware" : "Software"), |
| (process_type == JpegProcessType::kDecode ? "Decode" : "Encode")); |
| metrics_lib_->SendToUMA(action_name, width * height, kMinResolutionInPixels, |
| kMaxResolutionInPixels, kBucketResolutionInPixels); |
| } |
| |
| void CameraMetricsImpl::SendConfigureStreamsLatency(base::TimeDelta latency) { |
| metrics_lib_->SendToUMA(kCameraConfigureStreamsLatency, |
| latency.InMicroseconds(), |
| kMinLatency.InMicroseconds(), |
| kMaxLatency.InMicroseconds(), kBucketLatency); |
| } |
| |
| void CameraMetricsImpl::SendConfigureStreamResolution(int width, |
| int height, |
| int format) { |
| std::string format_str; |
| switch (format) { |
| case HAL_PIXEL_FORMAT_RGBA_8888: |
| format_str = "RGBA_8888"; |
| break; |
| case HAL_PIXEL_FORMAT_RGBX_8888: |
| format_str = "RGBX_8888"; |
| break; |
| case HAL_PIXEL_FORMAT_BGRA_8888: |
| format_str = "BGRA_8888"; |
| break; |
| case HAL_PIXEL_FORMAT_YCrCb_420_SP: |
| format_str = "YCrCb_420_SP"; |
| break; |
| case HAL_PIXEL_FORMAT_YCbCr_422_I: |
| format_str = "YCbCr_422_I"; |
| break; |
| case HAL_PIXEL_FORMAT_BLOB: |
| format_str = "BLOB"; |
| break; |
| case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: |
| format_str = "IMPLEMENTATION_DEFINED"; |
| break; |
| case HAL_PIXEL_FORMAT_YCbCr_420_888: |
| format_str = "YCbCr_420_888"; |
| break; |
| case HAL_PIXEL_FORMAT_YV12: |
| format_str = "YV12"; |
| break; |
| } |
| std::string action_name = |
| base::StringPrintf(kCameraConfigureStreamsResolution, format_str.c_str()); |
| metrics_lib_->SendToUMA(action_name, width * height, kMinResolutionInPixels, |
| kMaxResolutionInPixels, kBucketResolutionInPixels); |
| } |
| |
| void CameraMetricsImpl::SendOpenDeviceClientType(int client_type) { |
| metrics_lib_->SendEnumToUMA(kCameraOpenDeviceClientType, client_type, |
| kNumClientTypes); |
| } |
| |
| void CameraMetricsImpl::SendOpenDeviceLatency(base::TimeDelta latency) { |
| metrics_lib_->SendToUMA(kCameraOpenDeviceLatency, latency.InMicroseconds(), |
| kMinLatency.InMicroseconds(), |
| kMaxLatency.InMicroseconds(), kBucketLatency); |
| } |
| |
| void CameraMetricsImpl::SendError(int error_code) { |
| metrics_lib_->SendEnumToUMA(kCameraErrorType, error_code, |
| CAMERA3_MSG_NUM_ERRORS); |
| } |
| |
| void CameraMetricsImpl::SendCameraFacing(int facing) { |
| metrics_lib_->SendEnumToUMA(kCameraFacing, facing, kNumCameraFacings); |
| } |
| |
| void CameraMetricsImpl::SendSessionDuration(base::TimeDelta duration) { |
| metrics_lib_->SendToUMA(kCameraSessionDuration, duration.InSeconds(), |
| kMinCameraSessionDuration.InSeconds(), |
| kMaxCameraSessionDuration.InSeconds(), |
| kBucketCameraSessionDuration); |
| } |
| |
| void CameraMetricsImpl::SendFaceAeFunction(FaceAeFunction function) { |
| metrics_lib_->SendEnumToUMA(kCameraFaceAeFunction, function); |
| } |
| |
| void CameraMetricsImpl::SendFaceAeMaxDetectedFaces(int number) { |
| if (number > kMaxNumFaces) { |
| number = kMaxNumFaces; |
| } |
| metrics_lib_->SendEnumToUMA(kCameraFaceAeMaxDetectedFaces, number, |
| kMaxNumFaces + 1); |
| } |
| |
| void CameraMetricsImpl::SendHdrnetStreamConfiguration( |
| HdrnetStreamConfiguration config) { |
| metrics_lib_->SendEnumToUMA(kCameraHdrnetStreamConfiguration, config); |
| } |
| |
| void CameraMetricsImpl::SendHdrnetMaxStreamSize(HdrnetStreamType stream_type, |
| int size) { |
| std::string type_str; |
| switch (stream_type) { |
| case HdrnetStreamType::kYuv: |
| type_str = kHdrnetStreamTypeYuv; |
| break; |
| |
| case HdrnetStreamType::kBlob: |
| type_str = kHdrnetStreamTypeBlob; |
| break; |
| } |
| std::string key = |
| base::StringPrintf(kCameraHdrnetMaxStreamSize, type_str.c_str()); |
| metrics_lib_->SendToUMA(key, size, kMinResolutionInPixels, |
| kMaxResolutionInPixels, kBucketResolutionInPixels); |
| } |
| |
| void CameraMetricsImpl::SendHdrnetNumConcurrentStreams(int num_streams) { |
| metrics_lib_->SendToUMA(kCameraHdrnetNumConcurrentStreams, num_streams, |
| kMinNumConcurrentHdrnetStreams, |
| kMaxNumConcurrentHdrnetStreams, |
| kNumConcurrentCameraStreamsBuckets); |
| } |
| |
| void CameraMetricsImpl::SendHdrnetMaxOutputBuffersRendered(int num_buffers) { |
| metrics_lib_->SendToUMA(kCameraHdrnetMaxOutputBuffersRendered, num_buffers, |
| kMinNumOutputBuffers, kMaxNumOutputBuffers, |
| kNumOutputBuffersBuckets); |
| } |
| |
| void CameraMetricsImpl::SendHdrnetError(HdrnetError error) { |
| metrics_lib_->SendEnumToUMA(kCameraHdrnetError, error); |
| } |
| |
| void CameraMetricsImpl::SendHdrnetNumStillShotsTaken(int num_shots) { |
| metrics_lib_->SendToUMA(kCameraHdrnetNumStillShotsTaken, num_shots, |
| kMinNumShotsTaken, kMaxNumShotsTaken, |
| kNumShotsTakenBuckets); |
| } |
| |
| void CameraMetricsImpl::SendHdrnetAvgLatency( |
| HdrnetProcessingType processing_type, int latency_us) { |
| std::string type_str; |
| switch (processing_type) { |
| case HdrnetProcessingType::kPreprocessing: |
| type_str = kHdrnetProcessingTypePreprocessing; |
| break; |
| |
| case HdrnetProcessingType::kRgbPipeline: |
| type_str = kHdrnetProcessingTypeRgbPipeline; |
| break; |
| |
| case HdrnetProcessingType::kPostprocessing: |
| type_str = kHdrnetProcessingTypePostprocessing; |
| break; |
| } |
| std::string key = |
| base::StringPrintf(kCameraHdrnetAvgLatency, type_str.c_str()); |
| metrics_lib_->SendToUMA(key, latency_us, kMinHdrnetLatencyUs, |
| kMaxHdrnetLatencyUs, kHdrnetLatencyBuckets); |
| } |
| |
| void CameraMetricsImpl::SendGcamAeAvgConvergenceLatency(int latency_frames) { |
| metrics_lib_->SendToUMA(kCameraGcamAeAvgConvergenceLatency, latency_frames, |
| kMinConvergenceLatencyFrames, |
| kMaxConvergenceLatencyFrames, |
| kConvergenceLatencyBuckets); |
| } |
| |
| void CameraMetricsImpl::SendGcamAeAvgHdrRatio(int hdr_ratio) { |
| metrics_lib_->SendToUMA(kCameraGcamAeAvgHdrRatio, hdr_ratio, kMinHdrRatio, |
| kMaxHdrRatio, kHdrRatioBuckets); |
| } |
| |
| void CameraMetricsImpl::SendGcamAeAvgTet(int tet) { |
| metrics_lib_->SendToUMA(kCameraGcamAeAvgTet, tet, kMinTet, kMaxTet, |
| kTetBuckets); |
| } |
| |
| } // namespace cros |