[libcamera-devel] [PATCH 2/2] android: Introduce CameraCapabilties class

Jacopo Mondi jacopo at jmondi.org
Tue Jun 22 09:41:07 CEST 2021


Hi Hiro,

On Tue, Jun 22, 2021 at 10:34:27AM +0900, Hirokazu Honda wrote:
> Hi Jacopo, thank you for the patch.
>
> I failed to apply the patch on the top of the latest tree to review.
> Could you tell me the parent commit which I can apply this patch?

weird, I just applied these two patches cleanly on the latest
master which for me is
969da3189439 ("libcamera: utils: Support systems that lack secure_getenv and issetugid"

>
> -Hiro
> On Tue, Jun 22, 2021 at 12:29 AM Jacopo Mondi <jacopo at jmondi.org> wrote:
>
> > The camera_device.cpp has grown a little too much, and it has quickly
> > become hard to maintain. Break out the handling of the static
> > information collected at camera initialization time to a new
> > CameraCapabilities class.
> >
> > Break out from the camera_device.cpp file all the functions relative to:
> > - Initialization of supported stream configurations
> > - Initialization of static metadata
> > - Initialization of request templates
> >
> > Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> > Acked-by: Paul Elder <paul.elder at ideasonboard.com>
> > Tested-by: Paul Elder <paul.elder at ideasonboard.com>
> > ---
> >  src/android/camera_capabilities.cpp | 1164 +++++++++++++++++++++++++++
> >  src/android/camera_capabilities.h   |   65 ++
> >  src/android/camera_device.cpp       | 1147 +-------------------------
> >  src/android/camera_device.h         |   27 +-
> >  src/android/meson.build             |    1 +
> >  5 files changed, 1245 insertions(+), 1159 deletions(-)
> >  create mode 100644 src/android/camera_capabilities.cpp
> >  create mode 100644 src/android/camera_capabilities.h
> >
> > diff --git a/src/android/camera_capabilities.cpp
> > b/src/android/camera_capabilities.cpp
> > new file mode 100644
> > index 000000000000..311a2c839586
> > --- /dev/null
> > +++ b/src/android/camera_capabilities.cpp
> > @@ -0,0 +1,1164 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +/*
> > + * Copyright (C) 2021, Google Inc.
> > + *
> > + * camera_capabilities.cpp - Camera static properties manager
> > + */
> > +
> > +#include "camera_capabilities.h"
> > +
> > +#include <array>
> > +#include <cmath>
> > +
> > +#include <hardware/camera3.h>
> > +
> > +#include <libcamera/control_ids.h>
> > +#include <libcamera/controls.h>
> > +#include <libcamera/property_ids.h>
> > +
> > +#include "libcamera/internal/formats.h"
> > +#include "libcamera/internal/log.h"
> > +
> > +using namespace libcamera;
> > +
> > +LOG_DECLARE_CATEGORY(HAL)
> > +
> > +namespace {
> > +
> > +/*
> > + * \var camera3Resolutions
> > + * \brief The list of image resolutions defined as mandatory to be
> > supported by
> > + * the Android Camera3 specification
> > + */
> > +const std::vector<Size> camera3Resolutions = {
> > +       { 320, 240 },
> > +       { 640, 480 },
> > +       { 1280, 720 },
> > +       { 1920, 1080 }
> > +};
> > +
> > +/*
> > + * \struct Camera3Format
> > + * \brief Data associated with an Android format identifier
> > + * \var libcameraFormats List of libcamera pixel formats compatible with
> > the
> > + * Android format
> > + * \var name The human-readable representation of the Android format code
> > + */
> > +struct Camera3Format {
> > +       std::vector<PixelFormat> libcameraFormats;
> > +       bool mandatory;
> > +       const char *name;
> > +};
> > +
> > +/*
> > + * \var camera3FormatsMap
> > + * \brief Associate Android format code with ancillary data
> > + */
> > +const std::map<int, const Camera3Format> camera3FormatsMap = {
> > +       {
> > +               HAL_PIXEL_FORMAT_BLOB, {
> > +                       { formats::MJPEG },
> > +                       true,
> > +                       "BLOB"
> > +               }
> > +       }, {
> > +               HAL_PIXEL_FORMAT_YCbCr_420_888, {
> > +                       { formats::NV12, formats::NV21 },
> > +                       true,
> > +                       "YCbCr_420_888"
> > +               }
> > +       }, {
> > +               /*
> > +                * \todo Translate IMPLEMENTATION_DEFINED inspecting the
> > gralloc
> > +                * usage flag. For now, copy the YCbCr_420 configuration.
> > +                */
> > +               HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, {
> > +                       { formats::NV12, formats::NV21 },
> > +                       true,
> > +                       "IMPLEMENTATION_DEFINED"
> > +               }
> > +       }, {
> > +               HAL_PIXEL_FORMAT_RAW10, {
> > +                       {
> > +                               formats::SBGGR10_CSI2P,
> > +                               formats::SGBRG10_CSI2P,
> > +                               formats::SGRBG10_CSI2P,
> > +                               formats::SRGGB10_CSI2P
> > +                       },
> > +                       false,
> > +                       "RAW10"
> > +               }
> > +       }, {
> > +               HAL_PIXEL_FORMAT_RAW12, {
> > +                       {
> > +                               formats::SBGGR12_CSI2P,
> > +                               formats::SGBRG12_CSI2P,
> > +                               formats::SGRBG12_CSI2P,
> > +                               formats::SRGGB12_CSI2P
> > +                       },
> > +                       false,
> > +                       "RAW12"
> > +               }
> > +       }, {
> > +               HAL_PIXEL_FORMAT_RAW16, {
> > +                       {
> > +                               formats::SBGGR16,
> > +                               formats::SGBRG16,
> > +                               formats::SGRBG16,
> > +                               formats::SRGGB16
> > +                       },
> > +                       false,
> > +                       "RAW16"
> > +               }
> > +       },
> > +};
> > +
> > +} /* namespace */
> > +
> > +int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera>
> > camera,
> > +                                  int orientation, int facing)
> > +{
> > +       camera_ = camera;
> > +       orientation_ = orientation;
> > +       facing_ = facing;
> > +
> > +       /* Acquire the camera and initialize available stream
> > configurations. */
> > +       int ret = camera_->acquire();
> > +       if (ret) {
> > +               LOG(HAL, Error) << "Failed to temporarily acquire the
> > camera";
> > +               return ret;
> > +       }
> > +
> > +       ret = initializeStreamConfigurations();
> > +       camera_->release();
> > +       if (ret)
> > +               return ret;
> > +
> > +       return initializeStaticMetadata();
> > +}
> > +
> > +std::vector<Size>
> > CameraCapabilities::getYUVResolutions(CameraConfiguration *cameraConfig,
> > +                                                       const PixelFormat
> > &pixelFormat,
> > +                                                       const
> > std::vector<Size> &resolutions)
> > +{
> > +       std::vector<Size> supportedResolutions;
> > +
> > +       StreamConfiguration &cfg = cameraConfig->at(0);
> > +       for (const Size &res : resolutions) {
> > +               cfg.pixelFormat = pixelFormat;
> > +               cfg.size = res;
> > +
> > +               CameraConfiguration::Status status =
> > cameraConfig->validate();
> > +               if (status != CameraConfiguration::Valid) {
> > +                       LOG(HAL, Debug) << cfg.toString() << " not
> > supported";
> > +                       continue;
> > +               }
> > +
> > +               LOG(HAL, Debug) << cfg.toString() << " supported";
> > +
> > +               supportedResolutions.push_back(res);
> > +       }
> > +
> > +       return supportedResolutions;
> > +}
> > +
> > +std::vector<Size> CameraCapabilities::getRawResolutions(const
> > libcamera::PixelFormat &pixelFormat)
> > +{
> > +       std::unique_ptr<CameraConfiguration> cameraConfig =
> > +               camera_->generateConfiguration({ StreamRole::Raw });
> > +       StreamConfiguration &cfg = cameraConfig->at(0);
> > +       const StreamFormats &formats = cfg.formats();
> > +       std::vector<Size> supportedResolutions =
> > formats.sizes(pixelFormat);
> > +
> > +       return supportedResolutions;
> > +}
> > +
> > +/*
> > + * Initialize the format conversion map to translate from Android format
> > + * identifier to libcamera pixel formats and fill in the list of supported
> > + * stream configurations to be reported to the Android camera framework
> > through
> > + * the Camera static metadata.
> > + */
> > +int CameraCapabilities::initializeStreamConfigurations()
> > +{
> > +       /*
> > +        * Get the maximum output resolutions
> > +        * \todo Get this from the camera properties once defined
> > +        */
> > +       std::unique_ptr<CameraConfiguration> cameraConfig =
> > +               camera_->generateConfiguration({ StillCapture });
> > +       if (!cameraConfig) {
> > +               LOG(HAL, Error) << "Failed to get maximum resolution";
> > +               return -EINVAL;
> > +       }
> > +       StreamConfiguration &cfg = cameraConfig->at(0);
> > +
> > +       /*
> > +        * \todo JPEG - Adjust the maximum available resolution by taking
> > the
> > +        * JPEG encoder requirements into account (alignment and aspect
> > ratio).
> > +        */
> > +       const Size maxRes = cfg.size;
> > +       LOG(HAL, Debug) << "Maximum supported resolution: " <<
> > maxRes.toString();
> > +
> > +       /*
> > +        * Build the list of supported image resolutions.
> > +        *
> > +        * The resolutions listed in camera3Resolution are mandatory to be
> > +        * supported, up to the camera maximum resolution.
> > +        *
> > +        * Augment the list by adding resolutions calculated from the
> > camera
> > +        * maximum one.
> > +        */
> > +       std::vector<Size> cameraResolutions;
> > +       std::copy_if(camera3Resolutions.begin(), camera3Resolutions.end(),
> > +                    std::back_inserter(cameraResolutions),
> > +                    [&](const Size &res) { return res < maxRes; });
> > +
> > +       /*
> > +        * The Camera3 specification suggests adding 1/2 and 1/4 of the
> > maximum
> > +        * resolution.
> > +        */
> > +       for (unsigned int divider = 2;; divider <<= 1) {
> > +               Size derivedSize{
> > +                       maxRes.width / divider,
> > +                       maxRes.height / divider,
> > +               };
> > +
> > +               if (derivedSize.width < 320 ||
> > +                   derivedSize.height < 240)
> > +                       break;
> > +
> > +               cameraResolutions.push_back(derivedSize);
> > +       }
> > +       cameraResolutions.push_back(maxRes);
> > +
> > +       /* Remove duplicated entries from the list of supported
> > resolutions. */
> > +       std::sort(cameraResolutions.begin(), cameraResolutions.end());
> > +       auto last = std::unique(cameraResolutions.begin(),
> > cameraResolutions.end());
> > +       cameraResolutions.erase(last, cameraResolutions.end());
> > +
> > +       /*
> > +        * Build the list of supported camera formats.
> > +        *
> > +        * To each Android format a list of compatible libcamera formats is
> > +        * associated. The first libcamera format that tests successful is
> > added
> > +        * to the format translation map used when configuring the streams.
> > +        * It is then tested against the list of supported camera
> > resolutions to
> > +        * build the stream configuration map reported through the camera
> > static
> > +        * metadata.
> > +        */
> > +       Size maxJpegSize;
> > +       for (const auto &format : camera3FormatsMap) {
> > +               int androidFormat = format.first;
> > +               const Camera3Format &camera3Format = format.second;
> > +               const std::vector<PixelFormat> &libcameraFormats =
> > +                       camera3Format.libcameraFormats;
> > +
> > +               LOG(HAL, Debug) << "Trying to map Android format "
> > +                               << camera3Format.name;
> > +
> > +               /*
> > +                * JPEG is always supported, either produced directly by
> > the
> > +                * camera, or encoded in the HAL.
> > +                */
> > +               if (androidFormat == HAL_PIXEL_FORMAT_BLOB) {
> > +                       formatsMap_[androidFormat] = formats::MJPEG;
> > +                       LOG(HAL, Debug) << "Mapped Android format "
> > +                                       << camera3Format.name << " to "
> > +                                       << formats::MJPEG.toString()
> > +                                       << " (fixed mapping)";
> > +                       continue;
> > +               }
> > +
> > +               /*
> > +                * Test the libcamera formats that can produce images
> > +                * compatible with the format defined by Android.
> > +                */
> > +               PixelFormat mappedFormat;
> > +               for (const PixelFormat &pixelFormat : libcameraFormats) {
> > +
> > +                       LOG(HAL, Debug) << "Testing " <<
> > pixelFormat.toString();
> > +
> > +                       /*
> > +                        * The stream configuration size can be adjusted,
> > +                        * not the pixel format.
> > +                        *
> > +                        * \todo This could be simplified once all pipeline
> > +                        * handlers will report the StreamFormats list of
> > +                        * supported formats.
> > +                        */
> > +                       cfg.pixelFormat = pixelFormat;
> > +
> > +                       CameraConfiguration::Status status =
> > cameraConfig->validate();
> > +                       if (status != CameraConfiguration::Invalid &&
> > +                           cfg.pixelFormat == pixelFormat) {
> > +                               mappedFormat = pixelFormat;
> > +                               break;
> > +                       }
> > +               }
> > +
> > +               if (!mappedFormat.isValid()) {
> > +                       /* If the format is not mandatory, skip it. */
> > +                       if (!camera3Format.mandatory)
> > +                               continue;
> > +
> > +                       LOG(HAL, Error)
> > +                               << "Failed to map mandatory Android format
> > "
> > +                               << camera3Format.name << " ("
> > +                               << utils::hex(androidFormat) << "):
> > aborting";
> > +                       return -EINVAL;
> > +               }
> > +
> > +               /*
> > +                * Record the mapping and then proceed to generate the
> > +                * stream configurations map, by testing the image
> > resolutions.
> > +                */
> > +               formatsMap_[androidFormat] = mappedFormat;
> > +               LOG(HAL, Debug) << "Mapped Android format "
> > +                               << camera3Format.name << " to "
> > +                               << mappedFormat.toString();
> > +
> > +               std::vector<Size> resolutions;
> > +               const PixelFormatInfo &info =
> > PixelFormatInfo::info(mappedFormat);
> > +               if (info.colourEncoding ==
> > PixelFormatInfo::ColourEncodingRAW)
> > +                       resolutions = getRawResolutions(mappedFormat);
> > +               else
> > +                       resolutions = getYUVResolutions(cameraConfig.get(),
> > +                                                       mappedFormat,
> > +                                                       cameraResolutions);
> > +
> > +               for (const Size &res : resolutions) {
> > +                       streamConfigurations_.push_back({ res,
> > androidFormat });
> > +
> > +                       /*
> > +                        * If the format is HAL_PIXEL_FORMAT_YCbCr_420_888
> > +                        * from which JPEG is produced, add an entry for
> > +                        * the JPEG stream.
> > +                        *
> > +                        * \todo Wire the JPEG encoder to query the
> > supported
> > +                        * sizes provided a list of formats it can encode.
> > +                        *
> > +                        * \todo Support JPEG streams produced by the
> > Camera
> > +                        * natively.
> > +                        */
> > +                       if (androidFormat ==
> > HAL_PIXEL_FORMAT_YCbCr_420_888) {
> > +                               streamConfigurations_.push_back(
> > +                                       { res, HAL_PIXEL_FORMAT_BLOB });
> > +                               maxJpegSize = std::max(maxJpegSize, res);
> > +                       }
> > +               }
> > +
> > +               /*
> > +                * \todo Calculate the maximum JPEG buffer size by asking
> > the
> > +                * encoder giving the maximum frame size required.
> > +                */
> > +               maxJpegBufferSize_ = maxJpegSize.width *
> > maxJpegSize.height * 1.5;
> > +       }
> > +
> > +       LOG(HAL, Debug) << "Collected stream configuration map: ";
> > +       for (const auto &entry : streamConfigurations_)
> > +               LOG(HAL, Debug) << "{ " << entry.resolution.toString() <<
> > " - "
> > +                               << utils::hex(entry.androidFormat) << " }";
> > +
> > +       return 0;
> > +}
> > +
> > +int CameraCapabilities::initializeStaticMetadata()
> > +{
> > +       staticMetadata_ = std::make_unique<CameraMetadata>(64, 1024);
> > +       if (!staticMetadata_->isValid()) {
> > +               LOG(HAL, Error) << "Failed to allocate static metadata";
> > +               staticMetadata_.reset();
> > +               return -EINVAL;
> > +       }
> > +
> > +       const ControlInfoMap &controlsInfo = camera_->controls();
> > +       const ControlList &properties = camera_->properties();
> > +
> > +       /* Color correction static metadata. */
> > +       {
> > +               std::vector<uint8_t> data;
> > +               data.reserve(3);
> > +               const auto &infoMap =
> > controlsInfo.find(&controls::draft::ColorCorrectionAberrationMode);
> > +               if (infoMap != controlsInfo.end()) {
> > +                       for (const auto &value : infoMap->second.values())
> > +                               data.push_back(value.get<int32_t>());
> > +               } else {
> > +
> >  data.push_back(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF);
> > +               }
> > +
> >  staticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
> > +                                         data);
> > +       }
> > +
> > +       /* Control static metadata. */
> > +       std::vector<uint8_t> aeAvailableAntiBandingModes = {
> > +               ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
> > +               ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
> > +               ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
> > +               ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
> > +       };
> > +
> >  staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
> > +                                 aeAvailableAntiBandingModes);
> > +
> > +       std::vector<uint8_t> aeAvailableModes = {
> > +               ANDROID_CONTROL_AE_MODE_ON,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
> > +                                 aeAvailableModes);
> > +
> > +       int64_t minFrameDurationNsec = -1;
> > +       int64_t maxFrameDurationNsec = -1;
> > +       const auto frameDurationsInfo =
> > controlsInfo.find(&controls::FrameDurationLimits);
> > +       if (frameDurationsInfo != controlsInfo.end()) {
> > +               minFrameDurationNsec =
> > frameDurationsInfo->second.min().get<int64_t>() * 1000;
> > +               maxFrameDurationNsec =
> > frameDurationsInfo->second.max().get<int64_t>() * 1000;
> > +
> > +               /*
> > +                * Adjust the minimum frame duration to comply with Android
> > +                * requirements. The camera service mandates all
> > preview/record
> > +                * streams to have a minimum frame duration < 33,366
> > milliseconds
> > +                * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera
> > service
> > +                * implementation).
> > +                *
> > +                * If we're close enough (+ 500 useconds) to that value,
> > round
> > +                * the minimum frame duration of the camera to an accepted
> > +                * value.
> > +                */
> > +               static constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS =
> > 1e9 / 29.97;
> > +               if (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS
> > &&
> > +                   minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS
> > + 500000)
> > +                       minFrameDurationNsec =
> > MAX_PREVIEW_RECORD_DURATION_NS - 1000;
> > +
> > +               /*
> > +                * The AE routine frame rate limits are computed using the
> > frame
> > +                * duration limits, as libcamera clips the AE routine to
> > the
> > +                * frame durations.
> > +                */
> > +               int32_t maxFps = std::round(1e9 / minFrameDurationNsec);
> > +               int32_t minFps = std::round(1e9 / maxFrameDurationNsec);
> > +               minFps = std::max(1, minFps);
> > +
> > +               /*
> > +                * Force rounding errors so that we have the proper frame
> > +                * durations for when we reuse these variables later
> > +                */
> > +               minFrameDurationNsec = 1e9 / maxFps;
> > +               maxFrameDurationNsec = 1e9 / minFps;
> > +
> > +               /*
> > +                * Register to the camera service {min, max} and {max, max}
> > +                * intervals as requested by the metadata documentation.
> > +                */
> > +               int32_t availableAeFpsTarget[] = {
> > +                       minFps, maxFps, maxFps, maxFps
> > +               };
> > +
> >  staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > +                                         availableAeFpsTarget);
> > +       }
> > +
> > +       std::vector<int32_t> aeCompensationRange = {
> > +               0, 0,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
> > +                                 aeCompensationRange);
> > +
> > +       const camera_metadata_rational_t aeCompensationStep[] = {
> > +               { 0, 1 }
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,
> > +                                 aeCompensationStep);
> > +
> > +       std::vector<uint8_t> availableAfModes = {
> > +               ANDROID_CONTROL_AF_MODE_OFF,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,
> > +                                 availableAfModes);
> > +
> > +       std::vector<uint8_t> availableEffects = {
> > +               ANDROID_CONTROL_EFFECT_MODE_OFF,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,
> > +                                 availableEffects);
> > +
> > +       std::vector<uint8_t> availableSceneModes = {
> > +               ANDROID_CONTROL_SCENE_MODE_DISABLED,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
> > +                                 availableSceneModes);
> > +
> > +       std::vector<uint8_t> availableStabilizationModes = {
> > +               ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
> > +       };
> > +
> >  staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
> > +                                 availableStabilizationModes);
> > +
> > +       /*
> > +        * \todo Inspect the Camera capabilities to report the available
> > +        * AWB modes. Default to AUTO as CTS tests require it.
> > +        */
> > +       std::vector<uint8_t> availableAwbModes = {
> > +               ANDROID_CONTROL_AWB_MODE_AUTO,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
> > +                                 availableAwbModes);
> > +
> > +       std::vector<int32_t> availableMaxRegions = {
> > +               0, 0, 0,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,
> > +                                 availableMaxRegions);
> > +
> > +       std::vector<uint8_t> sceneModesOverride = {
> > +               ANDROID_CONTROL_AE_MODE_ON,
> > +               ANDROID_CONTROL_AWB_MODE_AUTO,
> > +               ANDROID_CONTROL_AF_MODE_OFF,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
> > +                                 sceneModesOverride);
> > +
> > +       uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
> > +                                 aeLockAvailable);
> > +
> > +       uint8_t awbLockAvailable =
> > ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
> > +                                 awbLockAvailable);
> > +
> > +       char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
> > +       staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
> > +                                 availableControlModes);
> > +
> > +       /* JPEG static metadata. */
> > +
> > +       /*
> > +        * Create the list of supported thumbnail sizes by inspecting the
> > +        * available JPEG resolutions collected in streamConfigurations_
> > and
> > +        * generate one entry for each aspect ratio.
> > +        *
> > +        * The JPEG thumbnailer can freely scale, so pick an arbitrary
> > +        * (160, 160) size as the bounding rectangle, which is then
> > cropped to
> > +        * the different supported aspect ratios.
> > +        */
> > +       constexpr Size maxJpegThumbnail(160, 160);
> > +       std::vector<Size> thumbnailSizes;
> > +       thumbnailSizes.push_back({ 0, 0 });
> > +       for (const auto &entry : streamConfigurations_) {
> > +               if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)
> > +                       continue;
> > +
> > +               Size thumbnailSize = maxJpegThumbnail
> > +                                    .boundedToAspectRatio({
> > entry.resolution.width,
> > +
> > entry.resolution.height });
> > +               thumbnailSizes.push_back(thumbnailSize);
> > +       }
> > +
> > +       std::sort(thumbnailSizes.begin(), thumbnailSizes.end());
> > +       auto last = std::unique(thumbnailSizes.begin(),
> > thumbnailSizes.end());
> > +       thumbnailSizes.erase(last, thumbnailSizes.end());
> > +
> > +       /* Transform sizes in to a list of integers that can be consumed.
> > */
> > +       std::vector<int32_t> thumbnailEntries;
> > +       thumbnailEntries.reserve(thumbnailSizes.size() * 2);
> > +       for (const auto &size : thumbnailSizes) {
> > +               thumbnailEntries.push_back(size.width);
> > +               thumbnailEntries.push_back(size.height);
> > +       }
> > +       staticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
> > +                                 thumbnailEntries);
> > +
> > +       staticMetadata_->addEntry(ANDROID_JPEG_MAX_SIZE,
> > maxJpegBufferSize_);
> > +
> > +       /* Sensor static metadata. */
> > +       std::array<int32_t, 2> pixelArraySize;
> > +       {
> > +               const Size &size =
> > properties.get(properties::PixelArraySize);
> > +               pixelArraySize[0] = size.width;
> > +               pixelArraySize[1] = size.height;
> > +
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
> > +                                         pixelArraySize);
> > +       }
> > +
> > +       if (properties.contains(properties::UnitCellSize)) {
> > +               const Size &cellSize =
> > properties.get<Size>(properties::UnitCellSize);
> > +               std::array<float, 2> physicalSize{
> > +                       cellSize.width * pixelArraySize[0] / 1e6f,
> > +                       cellSize.height * pixelArraySize[1] / 1e6f
> > +               };
> > +
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
> > +                                         physicalSize);
> > +       }
> > +
> > +       {
> > +               const Span<const Rectangle> &rects =
> > +                       properties.get(properties::PixelArrayActiveAreas);
> > +               std::vector<int32_t> data{
> > +                       static_cast<int32_t>(rects[0].x),
> > +                       static_cast<int32_t>(rects[0].y),
> > +                       static_cast<int32_t>(rects[0].width),
> > +                       static_cast<int32_t>(rects[0].height),
> > +               };
> > +
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
> > +                                         data);
> > +       }
> > +
> > +       int32_t sensitivityRange[] = {
> > +               32, 2400,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
> > +                                 sensitivityRange);
> > +
> > +       /* Report the color filter arrangement if the camera reports it. */
> > +       if
> > (properties.contains(properties::draft::ColorFilterArrangement)) {
> > +               uint8_t filterArr =
> > properties.get(properties::draft::ColorFilterArrangement);
> > +
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
> > +                                         filterArr);
> > +       }
> > +
> > +       const auto &exposureInfo =
> > controlsInfo.find(&controls::ExposureTime);
> > +       if (exposureInfo != controlsInfo.end()) {
> > +               int64_t exposureTimeRange[2] = {
> > +                       exposureInfo->second.min().get<int32_t>() * 1000LL,
> > +                       exposureInfo->second.max().get<int32_t>() * 1000LL,
> > +               };
> > +
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
> > +                                         exposureTimeRange, 2);
> > +       }
> > +
> > +       staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,
> > orientation_);
> > +
> > +       std::vector<int32_t> testPatternModes = {
> > +               ANDROID_SENSOR_TEST_PATTERN_MODE_OFF
> > +       };
> > +       const auto &testPatternsInfo =
> > +               controlsInfo.find(&controls::draft::TestPatternMode);
> > +       if (testPatternsInfo != controlsInfo.end()) {
> > +               const auto &values = testPatternsInfo->second.values();
> > +               ASSERT(!values.empty());
> > +               for (const auto &value : values) {
> > +                       switch (value.get<int32_t>()) {
> > +                       case controls::draft::TestPatternModeOff:
> > +                               /*
> > +                                * ANDROID_SENSOR_TEST_PATTERN_MODE_OFF is
> > +                                * already in testPatternModes.
> > +                                */
> > +                               break;
> > +
> > +                       case controls::draft::TestPatternModeSolidColor:
> > +                               testPatternModes.push_back(
> > +
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR);
> > +                               break;
> > +
> > +                       case controls::draft::TestPatternModeColorBars:
> > +                               testPatternModes.push_back(
> > +
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS);
> > +                               break;
> > +
> > +                       case
> > controls::draft::TestPatternModeColorBarsFadeToGray:
> > +                               testPatternModes.push_back(
> > +
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY);
> > +                               break;
> > +
> > +                       case controls::draft::TestPatternModePn9:
> > +                               testPatternModes.push_back(
> > +
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_PN9);
> > +                               break;
> > +
> > +                       case controls::draft::TestPatternModeCustom1:
> > +                               /* We don't support this yet. */
> > +                               break;
> > +
> > +                       default:
> > +                               LOG(HAL, Error) << "Unknown test pattern
> > mode: "
> > +                                               << value.get<int32_t>();
> > +                               continue;
> > +                       }
> > +               }
> > +       }
> > +
> >  staticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
> > +                                 testPatternModes);
> > +
> > +       uint8_t timestampSource =
> > ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
> > +       staticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
> > +                                 timestampSource);
> > +
> > +       if (maxFrameDurationNsec > 0)
> > +
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
> > +                                         maxFrameDurationNsec);
> > +
> > +       /* Statistics static metadata. */
> > +       uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
> > +
> >  staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
> > +                                 faceDetectMode);
> > +
> > +       int32_t maxFaceCount = 0;
> > +       staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
> > +                                 maxFaceCount);
> > +
> > +       {
> > +               std::vector<uint8_t> data;
> > +               data.reserve(2);
> > +               const auto &infoMap =
> > controlsInfo.find(&controls::draft::LensShadingMapMode);
> > +               if (infoMap != controlsInfo.end()) {
> > +                       for (const auto &value : infoMap->second.values())
> > +                               data.push_back(value.get<int32_t>());
> > +               } else {
> > +
> >  data.push_back(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);
> > +               }
> > +
> >  staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
> > +                                         data);
> > +       }
> > +
> > +       /* Sync static metadata. */
> > +       int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
> > +       staticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, maxLatency);
> > +
> > +       /* Flash static metadata. */
> > +       char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
> > +       staticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,
> > +                                 flashAvailable);
> > +
> > +       /* Lens static metadata. */
> > +       std::vector<float> lensApertures = {
> > +               2.53 / 100,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
> > +                                 lensApertures);
> > +
> > +       uint8_t lensFacing;
> > +       switch (facing_) {
> > +       default:
> > +       case CAMERA_FACING_FRONT:
> > +               lensFacing = ANDROID_LENS_FACING_FRONT;
> > +               break;
> > +       case CAMERA_FACING_BACK:
> > +               lensFacing = ANDROID_LENS_FACING_BACK;
> > +               break;
> > +       case CAMERA_FACING_EXTERNAL:
> > +               lensFacing = ANDROID_LENS_FACING_EXTERNAL;
> > +               break;
> > +       }
> > +       staticMetadata_->addEntry(ANDROID_LENS_FACING, lensFacing);
> > +
> > +       std::vector<float> lensFocalLengths = {
> > +               1,
> > +       };
> > +
> >  staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
> > +                                 lensFocalLengths);
> > +
> > +       std::vector<uint8_t> opticalStabilizations = {
> > +               ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
> > +       };
> > +
> >  staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
> > +                                 opticalStabilizations);
> > +
> > +       float hypeFocalDistance = 0;
> > +       staticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
> > +                                 hypeFocalDistance);
> > +
> > +       float minFocusDistance = 0;
> > +       staticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
> > +                                 minFocusDistance);
> > +
> > +       /* Noise reduction modes. */
> > +       {
> > +               std::vector<uint8_t> data;
> > +               data.reserve(5);
> > +               const auto &infoMap =
> > controlsInfo.find(&controls::draft::NoiseReductionMode);
> > +               if (infoMap != controlsInfo.end()) {
> > +                       for (const auto &value : infoMap->second.values())
> > +                               data.push_back(value.get<int32_t>());
> > +               } else {
> > +                       data.push_back(ANDROID_NOISE_REDUCTION_MODE_OFF);
> > +               }
> > +
> >  staticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
> > +                                         data);
> > +       }
> > +
> > +       /* Scaler static metadata. */
> > +
> > +       /*
> > +        * \todo The digital zoom factor is a property that depends on the
> > +        * desired output configuration and the sensor frame size input to
> > the
> > +        * ISP. This information is not available to the Android HAL, not
> > at
> > +        * initialization time at least.
> > +        *
> > +        * As a workaround rely on pipeline handlers initializing the
> > +        * ScalerCrop control with the camera default configuration and
> > use the
> > +        * maximum and minimum crop rectangles to calculate the digital
> > zoom
> > +        * factor.
> > +        */
> > +       float maxZoom = 1.0f;
> > +       const auto scalerCrop = controlsInfo.find(&controls::ScalerCrop);
> > +       if (scalerCrop != controlsInfo.end()) {
> > +               Rectangle min = scalerCrop->second.min().get<Rectangle>();
> > +               Rectangle max = scalerCrop->second.max().get<Rectangle>();
> > +               maxZoom = std::min(1.0f * max.width / min.width,
> > +                                  1.0f * max.height / min.height);
> > +       }
> > +
> >  staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
> > +                                 maxZoom);
> > +
> > +       std::vector<uint32_t> availableStreamConfigurations;
> > +       availableStreamConfigurations.reserve(streamConfigurations_.size()
> > * 4);
> > +       for (const auto &entry : streamConfigurations_) {
> > +
> >  availableStreamConfigurations.push_back(entry.androidFormat);
> > +
> >  availableStreamConfigurations.push_back(entry.resolution.width);
> > +
> >  availableStreamConfigurations.push_back(entry.resolution.height);
> > +               availableStreamConfigurations.push_back(
> > +
> >  ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
> > +       }
> > +
> >  staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
> > +                                 availableStreamConfigurations);
> > +
> > +       std::vector<int64_t> availableStallDurations = {
> > +               ANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,
> > 33333333,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
> > +                                 availableStallDurations);
> > +
> > +       /* Use the minimum frame duration for all the YUV/RGB formats. */
> > +       if (minFrameDurationNsec > 0) {
> > +               std::vector<int64_t> minFrameDurations;
> > +               minFrameDurations.reserve(streamConfigurations_.size() *
> > 4);
> > +               for (const auto &entry : streamConfigurations_) {
> > +                       minFrameDurations.push_back(entry.androidFormat);
> > +
> >  minFrameDurations.push_back(entry.resolution.width);
> > +
> >  minFrameDurations.push_back(entry.resolution.height);
> > +                       minFrameDurations.push_back(minFrameDurationNsec);
> > +               }
> > +
> >  staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
> > +                                         minFrameDurations);
> > +       }
> > +
> > +       uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
> > +       staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE,
> > croppingType);
> > +
> > +       /* Info static metadata. */
> > +       uint8_t supportedHWLevel =
> > ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
> > +       staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
> > +                                 supportedHWLevel);
> > +
> > +       /* Request static metadata. */
> > +       int32_t partialResultCount = 1;
> > +       staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
> > +                                 partialResultCount);
> > +
> > +       {
> > +               /* Default the value to 2 if not reported by the camera. */
> > +               uint8_t maxPipelineDepth = 2;
> > +               const auto &infoMap =
> > controlsInfo.find(&controls::draft::PipelineDepth);
> > +               if (infoMap != controlsInfo.end())
> > +                       maxPipelineDepth =
> > infoMap->second.max().get<int32_t>();
> > +
> >  staticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
> > +                                         maxPipelineDepth);
> > +       }
> > +
> > +       /* LIMITED does not support reprocessing. */
> > +       uint32_t maxNumInputStreams = 0;
> > +       staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
> > +                                 maxNumInputStreams);
> > +
> > +       std::vector<uint8_t> availableCapabilities = {
> > +               ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
> > +       };
> > +
> > +       /* Report if camera supports RAW. */
> > +       bool rawStreamAvailable = false;
> > +       std::unique_ptr<CameraConfiguration> cameraConfig =
> > +               camera_->generateConfiguration({ StreamRole::Raw });
> > +       if (cameraConfig && !cameraConfig->empty()) {
> > +               const PixelFormatInfo &info =
> > +
> >  PixelFormatInfo::info(cameraConfig->at(0).pixelFormat);
> > +               /* Only advertise RAW support if RAW16 is possible. */
> > +               if (info.colourEncoding ==
> > PixelFormatInfo::ColourEncodingRAW &&
> > +                   info.bitsPerPixel == 16) {
> > +                       rawStreamAvailable = true;
> > +
> >  availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
> > +               }
> > +       }
> > +
> > +       /* Number of { RAW, YUV, JPEG } supported output streams */
> > +       int32_t numOutStreams[] = { rawStreamAvailable, 2, 1 };
> > +       staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
> > +                                 numOutStreams);
> > +
> > +       staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
> > +                                 availableCapabilities);
> > +
> > +       std::vector<int32_t> availableCharacteristicsKeys = {
> > +               ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
> > +               ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
> > +               ANDROID_CONTROL_AE_AVAILABLE_MODES,
> > +               ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > +               ANDROID_CONTROL_AE_COMPENSATION_RANGE,
> > +               ANDROID_CONTROL_AE_COMPENSATION_STEP,
> > +               ANDROID_CONTROL_AE_LOCK_AVAILABLE,
> > +               ANDROID_CONTROL_AF_AVAILABLE_MODES,
> > +               ANDROID_CONTROL_AVAILABLE_EFFECTS,
> > +               ANDROID_CONTROL_AVAILABLE_MODES,
> > +               ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
> > +               ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
> > +               ANDROID_CONTROL_AWB_AVAILABLE_MODES,
> > +               ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
> > +               ANDROID_CONTROL_MAX_REGIONS,
> > +               ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
> > +               ANDROID_FLASH_INFO_AVAILABLE,
> > +               ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
> > +               ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
> > +               ANDROID_JPEG_MAX_SIZE,
> > +               ANDROID_LENS_FACING,
> > +               ANDROID_LENS_INFO_AVAILABLE_APERTURES,
> > +               ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
> > +               ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
> > +               ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
> > +               ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
> > +               ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
> > +               ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
> > +               ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
> > +               ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
> > +               ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
> > +               ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
> > +               ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
> > +               ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
> > +               ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
> > +               ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
> > +               ANDROID_SCALER_CROPPING_TYPE,
> > +               ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
> > +               ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
> > +               ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
> > +               ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
> > +               ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
> > +               ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
> > +               ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
> > +               ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
> > +               ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
> > +               ANDROID_SENSOR_ORIENTATION,
> > +               ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
> > +               ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
> > +               ANDROID_SYNC_MAX_LATENCY,
> > +       };
> > +
> >  staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
> > +                                 availableCharacteristicsKeys);
> > +
> > +       std::vector<int32_t> availableRequestKeys = {
> > +               ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
> > +               ANDROID_CONTROL_AE_ANTIBANDING_MODE,
> > +               ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
> > +               ANDROID_CONTROL_AE_LOCK,
> > +               ANDROID_CONTROL_AE_MODE,
> > +               ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
> > +               ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > +               ANDROID_CONTROL_AF_MODE,
> > +               ANDROID_CONTROL_AF_TRIGGER,
> > +               ANDROID_CONTROL_AWB_LOCK,
> > +               ANDROID_CONTROL_AWB_MODE,
> > +               ANDROID_CONTROL_CAPTURE_INTENT,
> > +               ANDROID_CONTROL_EFFECT_MODE,
> > +               ANDROID_CONTROL_MODE,
> > +               ANDROID_CONTROL_SCENE_MODE,
> > +               ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
> > +               ANDROID_FLASH_MODE,
> > +               ANDROID_JPEG_ORIENTATION,
> > +               ANDROID_JPEG_QUALITY,
> > +               ANDROID_JPEG_THUMBNAIL_QUALITY,
> > +               ANDROID_JPEG_THUMBNAIL_SIZE,
> > +               ANDROID_LENS_APERTURE,
> > +               ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
> > +               ANDROID_NOISE_REDUCTION_MODE,
> > +               ANDROID_SCALER_CROP_REGION,
> > +               ANDROID_STATISTICS_FACE_DETECT_MODE
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
> > +                                 availableRequestKeys);
> > +
> > +       std::vector<int32_t> availableResultKeys = {
> > +               ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
> > +               ANDROID_CONTROL_AE_ANTIBANDING_MODE,
> > +               ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
> > +               ANDROID_CONTROL_AE_LOCK,
> > +               ANDROID_CONTROL_AE_MODE,
> > +               ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
> > +               ANDROID_CONTROL_AE_STATE,
> > +               ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > +               ANDROID_CONTROL_AF_MODE,
> > +               ANDROID_CONTROL_AF_STATE,
> > +               ANDROID_CONTROL_AF_TRIGGER,
> > +               ANDROID_CONTROL_AWB_LOCK,
> > +               ANDROID_CONTROL_AWB_MODE,
> > +               ANDROID_CONTROL_AWB_STATE,
> > +               ANDROID_CONTROL_CAPTURE_INTENT,
> > +               ANDROID_CONTROL_EFFECT_MODE,
> > +               ANDROID_CONTROL_MODE,
> > +               ANDROID_CONTROL_SCENE_MODE,
> > +               ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
> > +               ANDROID_FLASH_MODE,
> > +               ANDROID_FLASH_STATE,
> > +               ANDROID_JPEG_GPS_COORDINATES,
> > +               ANDROID_JPEG_GPS_PROCESSING_METHOD,
> > +               ANDROID_JPEG_GPS_TIMESTAMP,
> > +               ANDROID_JPEG_ORIENTATION,
> > +               ANDROID_JPEG_QUALITY,
> > +               ANDROID_JPEG_SIZE,
> > +               ANDROID_JPEG_THUMBNAIL_QUALITY,
> > +               ANDROID_JPEG_THUMBNAIL_SIZE,
> > +               ANDROID_LENS_APERTURE,
> > +               ANDROID_LENS_FOCAL_LENGTH,
> > +               ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
> > +               ANDROID_LENS_STATE,
> > +               ANDROID_NOISE_REDUCTION_MODE,
> > +               ANDROID_REQUEST_PIPELINE_DEPTH,
> > +               ANDROID_SCALER_CROP_REGION,
> > +               ANDROID_SENSOR_EXPOSURE_TIME,
> > +               ANDROID_SENSOR_FRAME_DURATION,
> > +               ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
> > +               ANDROID_SENSOR_TEST_PATTERN_MODE,
> > +               ANDROID_SENSOR_TIMESTAMP,
> > +               ANDROID_STATISTICS_FACE_DETECT_MODE,
> > +               ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
> > +               ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
> > +               ANDROID_STATISTICS_SCENE_FLICKER,
> > +       };
> > +       staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
> > +                                 availableResultKeys);
> > +
> > +       if (!staticMetadata_->isValid()) {
> > +               LOG(HAL, Error) << "Failed to construct static metadata";
> > +               staticMetadata_.reset();
> > +               return -EINVAL;
> > +       }
> > +
> > +       if (staticMetadata_->resized()) {
> > +               auto [entryCount, dataCount] = staticMetadata_->usage();
> > +               LOG(HAL, Info)
> > +                       << "Static metadata resized: " << entryCount
> > +                       << " entries and " << dataCount << " bytes used";
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +/* Translate Android format code to libcamera pixel format. */
> > +PixelFormat CameraCapabilities::toPixelFormat(int format) const
> > +{
> > +       auto it = formatsMap_.find(format);
> > +       if (it == formatsMap_.end()) {
> > +               LOG(HAL, Error) << "Requested format " <<
> > utils::hex(format)
> > +                               << " not supported";
> > +               return PixelFormat();
> > +       }
> > +
> > +       return it->second;
> > +}
> > +
> > +std::unique_ptr<CameraMetadata>
> > CameraCapabilities::requestTemplatePreview() const
> > +{
> > +       /*
> > +        * \todo Keep this in sync with the actual number of entries.
> > +        * Currently: 20 entries, 35 bytes
> > +        */
> > +       auto requestTemplate = std::make_unique<CameraMetadata>(21, 36);
> > +       if (!requestTemplate->isValid()) {
> > +               return nullptr;
> > +       }
> > +
> > +       /* Get the FPS range registered in the static metadata. */
> > +       camera_metadata_ro_entry_t entry;
> > +       bool found =
> > staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > +                                              &entry);
> > +       if (!found) {
> > +               LOG(HAL, Error) << "Cannot create capture template without
> > FPS range";
> > +               return nullptr;
> > +       }
> > +
> > +       /*
> > +        * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
> > +        * has been assembled as {{min, max} {max, max}}.
> > +        */
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > +                                 entry.data.i32, 2);
> > +
> > +       uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AE_MODE, aeMode);
> > +
> > +       int32_t aeExposureCompensation = 0;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
> > +                                 aeExposureCompensation);
> > +
> > +       uint8_t aePrecaptureTrigger =
> > ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
> > +                                 aePrecaptureTrigger);
> > +
> > +       uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AE_LOCK, aeLock);
> > +
> > +       uint8_t aeAntibandingMode =
> > ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AE_ANTIBANDING_MODE,
> > +                                 aeAntibandingMode);
> > +
> > +       uint8_t afMode = ANDROID_CONTROL_AF_MODE_OFF;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AF_MODE, afMode);
> > +
> > +       uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AF_TRIGGER, afTrigger);
> > +
> > +       uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AWB_MODE, awbMode);
> > +
> > +       uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_AWB_LOCK, awbLock);
> > +
> > +       uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
> > +       requestTemplate->addEntry(ANDROID_FLASH_MODE, flashMode);
> > +
> > +       uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
> > +       requestTemplate->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,
> > +                                 faceDetectMode);
> > +
> > +       uint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;
> > +       requestTemplate->addEntry(ANDROID_NOISE_REDUCTION_MODE,
> > +                                 noiseReduction);
> > +
> > +       uint8_t aberrationMode =
> > ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;
> > +       requestTemplate->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
> > +                                 aberrationMode);
> > +
> > +       uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_MODE, controlMode);
> > +
> > +       float lensAperture = 2.53 / 100;
> > +       requestTemplate->addEntry(ANDROID_LENS_APERTURE, lensAperture);
> > +
> > +       uint8_t opticalStabilization =
> > ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
> > +       requestTemplate->addEntry(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
> > +                                 opticalStabilization);
> > +
> > +       uint8_t captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
> > +       requestTemplate->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,
> > +                                 captureIntent);
> > +
> > +       return requestTemplate;
> > +}
> > +
> > +std::unique_ptr<CameraMetadata>
> > CameraCapabilities::requestTemplateVideo() const
> > +{
> > +       std::unique_ptr<CameraMetadata> previewTemplate =
> > requestTemplatePreview();
> > +       if (!previewTemplate)
> > +               return nullptr;
> > +
> > +       /*
> > +        * The video template requires a fixed FPS range. Everything else
> > +        * stays the same as the preview template.
> > +        */
> > +       camera_metadata_ro_entry_t entry;
> > +
> >  staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > +                                 &entry);
> > +
> > +       /*
> > +        * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
> > +        * has been assembled as {{min, max} {max, max}}.
> > +        */
> > +       previewTemplate->updateEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > +                                    entry.data.i32 + 2, 2);
> > +
> > +       return previewTemplate;
> > +}
> > diff --git a/src/android/camera_capabilities.h
> > b/src/android/camera_capabilities.h
> > new file mode 100644
> > index 000000000000..f511607bbd90
> > --- /dev/null
> > +++ b/src/android/camera_capabilities.h
> > @@ -0,0 +1,65 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +/*
> > + * Copyright (C) 2021, Google Inc.
> > + *
> > + * camera_capabilities.h - Camera static properties manager
> > + */
> > +#ifndef __ANDROID_CAMERA_CAPABILITIES_H__
> > +#define __ANDROID_CAMERA_CAPABILITIES_H__
> > +
> > +#include <map>
> > +#include <memory>
> > +#include <vector>
> > +
> > +#include <libcamera/camera.h>
> > +#include <libcamera/class.h>
> > +#include <libcamera/formats.h>
> > +#include <libcamera/geometry.h>
> > +
> > +#include "camera_metadata.h"
> > +
> > +class CameraCapabilities
> > +{
> > +public:
> > +       CameraCapabilities() = default;
> > +
> > +       int initialize(std::shared_ptr<libcamera::Camera> camera,
> > +                      int orientation, int facing);
> > +
> > +       CameraMetadata *staticMetadata() const { return
> > staticMetadata_.get(); }
> > +       libcamera::PixelFormat toPixelFormat(int format) const;
> > +       unsigned int maxJpegBufferSize() const { return
> > maxJpegBufferSize_; }
> > +
> > +       std::unique_ptr<CameraMetadata> requestTemplatePreview() const;
> > +       std::unique_ptr<CameraMetadata> requestTemplateVideo() const;
> > +
> > +private:
> > +       LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraCapabilities)
> > +
> > +       struct Camera3StreamConfiguration {
> > +               libcamera::Size resolution;
> > +               int androidFormat;
> > +       };
> > +
> > +       std::vector<libcamera::Size>
> > +       getYUVResolutions(libcamera::CameraConfiguration *cameraConfig,
> > +                         const libcamera::PixelFormat &pixelFormat,
> > +                         const std::vector<libcamera::Size> &resolutions);
> > +       std::vector<libcamera::Size>
> > +       getRawResolutions(const libcamera::PixelFormat &pixelFormat);
> > +       int initializeStreamConfigurations();
> > +
> > +       int initializeStaticMetadata();
> > +
> > +       std::shared_ptr<libcamera::Camera> camera_;
> > +
> > +       int facing_;
> > +       int orientation_;
> > +
> > +       std::vector<Camera3StreamConfiguration> streamConfigurations_;
> > +       std::map<int, libcamera::PixelFormat> formatsMap_;
> > +       std::unique_ptr<CameraMetadata> staticMetadata_;
> > +       unsigned int maxJpegBufferSize_;
> > +};
> > +
> > +#endif /* __ANDROID_CAMERA_CAPABILITIES_H__ */
> > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
> > index 8c71fd0675d3..4bd125d7020a 100644
> > --- a/src/android/camera_device.cpp
> > +++ b/src/android/camera_device.cpp
> > @@ -10,11 +10,8 @@
> >  #include "camera_ops.h"
> >  #include "post_processor.h"
> >
> > -#include <array>
> > -#include <cmath>
> >  #include <fstream>
> >  #include <sys/mman.h>
> > -#include <tuple>
> >  #include <unistd.h>
> >  #include <vector>
> >
> > @@ -23,7 +20,6 @@
> >  #include <libcamera/formats.h>
> >  #include <libcamera/property_ids.h>
> >
> > -#include "libcamera/internal/formats.h"
> >  #include "libcamera/internal/log.h"
> >  #include "libcamera/internal/thread.h"
> >  #include "libcamera/internal/utils.h"
> > @@ -36,94 +32,6 @@ LOG_DECLARE_CATEGORY(HAL)
> >
> >  namespace {
> >
> > -/*
> > - * \var camera3Resolutions
> > - * \brief The list of image resolutions defined as mandatory to be
> > supported by
> > - * the Android Camera3 specification
> > - */
> > -const std::vector<Size> camera3Resolutions = {
> > -       { 320, 240 },
> > -       { 640, 480 },
> > -       { 1280, 720 },
> > -       { 1920, 1080 }
> > -};
> > -
> > -/*
> > - * \struct Camera3Format
> > - * \brief Data associated with an Android format identifier
> > - * \var libcameraFormats List of libcamera pixel formats compatible with
> > the
> > - * Android format
> > - * \var name The human-readable representation of the Android format code
> > - */
> > -struct Camera3Format {
> > -       std::vector<PixelFormat> libcameraFormats;
> > -       bool mandatory;
> > -       const char *name;
> > -};
> > -
> > -/*
> > - * \var camera3FormatsMap
> > - * \brief Associate Android format code with ancillary data
> > - */
> > -const std::map<int, const Camera3Format> camera3FormatsMap = {
> > -       {
> > -               HAL_PIXEL_FORMAT_BLOB, {
> > -                       { formats::MJPEG },
> > -                       true,
> > -                       "BLOB"
> > -               }
> > -       }, {
> > -               HAL_PIXEL_FORMAT_YCbCr_420_888, {
> > -                       { formats::NV12, formats::NV21 },
> > -                       true,
> > -                       "YCbCr_420_888"
> > -               }
> > -       }, {
> > -               /*
> > -                * \todo Translate IMPLEMENTATION_DEFINED inspecting the
> > gralloc
> > -                * usage flag. For now, copy the YCbCr_420 configuration.
> > -                */
> > -               HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, {
> > -                       { formats::NV12, formats::NV21 },
> > -                       true,
> > -                       "IMPLEMENTATION_DEFINED"
> > -               }
> > -       }, {
> > -               HAL_PIXEL_FORMAT_RAW10, {
> > -                       {
> > -                               formats::SBGGR10_CSI2P,
> > -                               formats::SGBRG10_CSI2P,
> > -                               formats::SGRBG10_CSI2P,
> > -                               formats::SRGGB10_CSI2P
> > -                       },
> > -                       false,
> > -                       "RAW10"
> > -               }
> > -       }, {
> > -               HAL_PIXEL_FORMAT_RAW12, {
> > -                       {
> > -                               formats::SBGGR12_CSI2P,
> > -                               formats::SGBRG12_CSI2P,
> > -                               formats::SGRBG12_CSI2P,
> > -                               formats::SRGGB12_CSI2P
> > -                       },
> > -                       false,
> > -                       "RAW12"
> > -               }
> > -       }, {
> > -               HAL_PIXEL_FORMAT_RAW16, {
> > -                       {
> > -                               formats::SBGGR16,
> > -                               formats::SGBRG16,
> > -                               formats::SGRBG16,
> > -                               formats::SRGGB16
> > -                       },
> > -                       false,
> > -                       "RAW16"
> > -               }
> > -       },
> > -};
> > -
> >  /*
> >   * \struct Camera3StreamConfig
> >   * \brief Data to store StreamConfiguration associated with
> > camera3_stream(s)
> > @@ -512,242 +420,7 @@ int CameraDevice::initialize(const CameraConfigData
> > *cameraConfigData)
> >                 orientation_ = 0;
> >         }
> >
> > -       /* Acquire the camera and initialize available stream
> > configurations. */
> > -       int ret = camera_->acquire();
> > -       if (ret) {
> > -               LOG(HAL, Error) << "Failed to temporarily acquire the
> > camera";
> > -               return ret;
> > -       }
> > -
> > -       ret = initializeStreamConfigurations();
> > -       camera_->release();
> > -       return ret;
> > -}
> > -
> > -std::vector<Size> CameraDevice::getYUVResolutions(CameraConfiguration
> > *cameraConfig,
> > -                                                 const PixelFormat
> > &pixelFormat,
> > -                                                 const std::vector<Size>
> > &resolutions)
> > -{
> > -       std::vector<Size> supportedResolutions;
> > -
> > -       StreamConfiguration &cfg = cameraConfig->at(0);
> > -       for (const Size &res : resolutions) {
> > -               cfg.pixelFormat = pixelFormat;
> > -               cfg.size = res;
> > -
> > -               CameraConfiguration::Status status =
> > cameraConfig->validate();
> > -               if (status != CameraConfiguration::Valid) {
> > -                       LOG(HAL, Debug) << cfg.toString() << " not
> > supported";
> > -                       continue;
> > -               }
> > -
> > -               LOG(HAL, Debug) << cfg.toString() << " supported";
> > -
> > -               supportedResolutions.push_back(res);
> > -       }
> > -
> > -       return supportedResolutions;
> > -}
> > -
> > -std::vector<Size> CameraDevice::getRawResolutions(const
> > libcamera::PixelFormat &pixelFormat)
> > -{
> > -       std::unique_ptr<CameraConfiguration> cameraConfig =
> > -               camera_->generateConfiguration({ StreamRole::Raw });
> > -       StreamConfiguration &cfg = cameraConfig->at(0);
> > -       const StreamFormats &formats = cfg.formats();
> > -       std::vector<Size> supportedResolutions =
> > formats.sizes(pixelFormat);
> > -
> > -       return supportedResolutions;
> > -}
> > -
> > -/*
> > - * Initialize the format conversion map to translate from Android format
> > - * identifier to libcamera pixel formats and fill in the list of supported
> > - * stream configurations to be reported to the Android camera framework
> > through
> > - * the static stream configuration metadata.
> > - */
> > -int CameraDevice::initializeStreamConfigurations()
> > -{
> > -       /*
> > -        * Get the maximum output resolutions
> > -        * \todo Get this from the camera properties once defined
> > -        */
> > -       std::unique_ptr<CameraConfiguration> cameraConfig =
> > -               camera_->generateConfiguration({ StillCapture });
> > -       if (!cameraConfig) {
> > -               LOG(HAL, Error) << "Failed to get maximum resolution";
> > -               return -EINVAL;
> > -       }
> > -       StreamConfiguration &cfg = cameraConfig->at(0);
> > -
> > -       /*
> > -        * \todo JPEG - Adjust the maximum available resolution by taking
> > the
> > -        * JPEG encoder requirements into account (alignment and aspect
> > ratio).
> > -        */
> > -       const Size maxRes = cfg.size;
> > -       LOG(HAL, Debug) << "Maximum supported resolution: " <<
> > maxRes.toString();
> > -
> > -       /*
> > -        * Build the list of supported image resolutions.
> > -        *
> > -        * The resolutions listed in camera3Resolution are mandatory to be
> > -        * supported, up to the camera maximum resolution.
> > -        *
> > -        * Augment the list by adding resolutions calculated from the
> > camera
> > -        * maximum one.
> > -        */
> > -       std::vector<Size> cameraResolutions;
> > -       std::copy_if(camera3Resolutions.begin(), camera3Resolutions.end(),
> > -                    std::back_inserter(cameraResolutions),
> > -                    [&](const Size &res) { return res < maxRes; });
> > -
> > -       /*
> > -        * The Camera3 specification suggests adding 1/2 and 1/4 of the
> > maximum
> > -        * resolution.
> > -        */
> > -       for (unsigned int divider = 2;; divider <<= 1) {
> > -               Size derivedSize{
> > -                       maxRes.width / divider,
> > -                       maxRes.height / divider,
> > -               };
> > -
> > -               if (derivedSize.width < 320 ||
> > -                   derivedSize.height < 240)
> > -                       break;
> > -
> > -               cameraResolutions.push_back(derivedSize);
> > -       }
> > -       cameraResolutions.push_back(maxRes);
> > -
> > -       /* Remove duplicated entries from the list of supported
> > resolutions. */
> > -       std::sort(cameraResolutions.begin(), cameraResolutions.end());
> > -       auto last = std::unique(cameraResolutions.begin(),
> > cameraResolutions.end());
> > -       cameraResolutions.erase(last, cameraResolutions.end());
> > -
> > -       /*
> > -        * Build the list of supported camera formats.
> > -        *
> > -        * To each Android format a list of compatible libcamera formats is
> > -        * associated. The first libcamera format that tests successful is
> > added
> > -        * to the format translation map used when configuring the streams.
> > -        * It is then tested against the list of supported camera
> > resolutions to
> > -        * build the stream configuration map reported through the camera
> > static
> > -        * metadata.
> > -        */
> > -       Size maxJpegSize;
> > -       for (const auto &format : camera3FormatsMap) {
> > -               int androidFormat = format.first;
> > -               const Camera3Format &camera3Format = format.second;
> > -               const std::vector<PixelFormat> &libcameraFormats =
> > -                       camera3Format.libcameraFormats;
> > -
> > -               LOG(HAL, Debug) << "Trying to map Android format "
> > -                               << camera3Format.name;
> > -
> > -               /*
> > -                * JPEG is always supported, either produced directly by
> > the
> > -                * camera, or encoded in the HAL.
> > -                */
> > -               if (androidFormat == HAL_PIXEL_FORMAT_BLOB) {
> > -                       formatsMap_[androidFormat] = formats::MJPEG;
> > -                       LOG(HAL, Debug) << "Mapped Android format "
> > -                                       << camera3Format.name << " to "
> > -                                       << formats::MJPEG.toString()
> > -                                       << " (fixed mapping)";
> > -                       continue;
> > -               }
> > -
> > -               /*
> > -                * Test the libcamera formats that can produce images
> > -                * compatible with the format defined by Android.
> > -                */
> > -               PixelFormat mappedFormat;
> > -               for (const PixelFormat &pixelFormat : libcameraFormats) {
> > -
> > -                       LOG(HAL, Debug) << "Testing " <<
> > pixelFormat.toString();
> > -
> > -                       /*
> > -                        * The stream configuration size can be adjusted,
> > -                        * not the pixel format.
> > -                        *
> > -                        * \todo This could be simplified once all pipeline
> > -                        * handlers will report the StreamFormats list of
> > -                        * supported formats.
> > -                        */
> > -                       cfg.pixelFormat = pixelFormat;
> > -
> > -                       CameraConfiguration::Status status =
> > cameraConfig->validate();
> > -                       if (status != CameraConfiguration::Invalid &&
> > -                           cfg.pixelFormat == pixelFormat) {
> > -                               mappedFormat = pixelFormat;
> > -                               break;
> > -                       }
> > -               }
> > -
> > -               if (!mappedFormat.isValid()) {
> > -                       /* If the format is not mandatory, skip it. */
> > -                       if (!camera3Format.mandatory)
> > -                               continue;
> > -
> > -                       LOG(HAL, Error)
> > -                               << "Failed to map mandatory Android format
> > "
> > -                               << camera3Format.name << " ("
> > -                               << utils::hex(androidFormat) << "):
> > aborting";
> > -                       return -EINVAL;
> > -               }
> > -
> > -               /*
> > -                * Record the mapping and then proceed to generate the
> > -                * stream configurations map, by testing the image
> > resolutions.
> > -                */
> > -               formatsMap_[androidFormat] = mappedFormat;
> > -               LOG(HAL, Debug) << "Mapped Android format "
> > -                               << camera3Format.name << " to "
> > -                               << mappedFormat.toString();
> > -
> > -               std::vector<Size> resolutions;
> > -               const PixelFormatInfo &info =
> > PixelFormatInfo::info(mappedFormat);
> > -               if (info.colourEncoding ==
> > PixelFormatInfo::ColourEncodingRAW)
> > -                       resolutions = getRawResolutions(mappedFormat);
> > -               else
> > -                       resolutions = getYUVResolutions(cameraConfig.get(),
> > -                                                       mappedFormat,
> > -                                                       cameraResolutions);
> > -
> > -               for (const Size &res : resolutions) {
> > -                       streamConfigurations_.push_back({ res,
> > androidFormat });
> > -
> > -                       /*
> > -                        * If the format is HAL_PIXEL_FORMAT_YCbCr_420_888
> > -                        * from which JPEG is produced, add an entry for
> > -                        * the JPEG stream.
> > -                        *
> > -                        * \todo Wire the JPEG encoder to query the
> > supported
> > -                        * sizes provided a list of formats it can encode.
> > -                        *
> > -                        * \todo Support JPEG streams produced by the
> > Camera
> > -                        * natively.
> > -                        */
> > -                       if (androidFormat ==
> > HAL_PIXEL_FORMAT_YCbCr_420_888) {
> > -                               streamConfigurations_.push_back(
> > -                                       { res, HAL_PIXEL_FORMAT_BLOB });
> > -                               maxJpegSize = std::max(maxJpegSize, res);
> > -                       }
> > -               }
> > -
> > -               /*
> > -                * \todo Calculate the maximum JPEG buffer size by asking
> > the
> > -                * encoder giving the maximum frame size required.
> > -                */
> > -               maxJpegBufferSize_ = maxJpegSize.width *
> > maxJpegSize.height * 1.5;
> > -       }
> > -
> > -       LOG(HAL, Debug) << "Collected stream configuration map: ";
> > -       for (const auto &entry : streamConfigurations_)
> > -               LOG(HAL, Debug) << "{ " << entry.resolution.toString() <<
> > " - "
> > -                               << utils::hex(entry.androidFormat) << " }";
> > -
> > -       return 0;
> > +       return capabilities_.initialize(camera_, orientation_, facing_);
> >  }
> >
> >  /*
> > @@ -817,802 +490,19 @@ void CameraDevice::stop()
> >         state_ = State::Stopped;
> >  }
> >
> > -void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)
> > +unsigned int CameraDevice::maxJpegBufferSize() const
> >  {
> > -       callbacks_ = callbacks;
> > +       return capabilities_.maxJpegBufferSize();
> >  }
> >
> > -/*
> > - * Return static information for the camera.
> > - */
> > -const camera_metadata_t *CameraDevice::getStaticMetadata()
> > -{
> > -       if (staticMetadata_)
> > -               return staticMetadata_->get();
> > -
> > -       staticMetadata_ = std::make_unique<CameraMetadata>(64, 1024);
> > -       if (!staticMetadata_->isValid()) {
> > -               LOG(HAL, Error) << "Failed to allocate static metadata";
> > -               staticMetadata_.reset();
> > -               return nullptr;
> > -       }
> > -
> > -       const ControlInfoMap &controlsInfo = camera_->controls();
> > -       const ControlList &properties = camera_->properties();
> > -
> > -       /* Color correction static metadata. */
> > -       {
> > -               std::vector<uint8_t> data;
> > -               data.reserve(3);
> > -               const auto &infoMap =
> > controlsInfo.find(&controls::draft::ColorCorrectionAberrationMode);
> > -               if (infoMap != controlsInfo.end()) {
> > -                       for (const auto &value : infoMap->second.values())
> > -                               data.push_back(value.get<int32_t>());
> > -               } else {
> > -
> >  data.push_back(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF);
> > -               }
> > -
> >  staticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
> > -                                         data);
> > -       }
> > -
> > -       /* Control static metadata. */
> > -       std::vector<uint8_t> aeAvailableAntiBandingModes = {
> > -               ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
> > -               ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
> > -               ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
> > -               ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
> > -       };
> > -
> >  staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
> > -                                 aeAvailableAntiBandingModes);
> > -
> > -       std::vector<uint8_t> aeAvailableModes = {
> > -               ANDROID_CONTROL_AE_MODE_ON,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
> > -                                 aeAvailableModes);
> > -
> > -       int64_t minFrameDurationNsec = -1;
> > -       int64_t maxFrameDurationNsec = -1;
> > -       const auto frameDurationsInfo =
> > controlsInfo.find(&controls::FrameDurationLimits);
> > -       if (frameDurationsInfo != controlsInfo.end()) {
> > -               minFrameDurationNsec =
> > frameDurationsInfo->second.min().get<int64_t>() * 1000;
> > -               maxFrameDurationNsec =
> > frameDurationsInfo->second.max().get<int64_t>() * 1000;
> > -
> > -               /*
> > -                * Adjust the minimum frame duration to comply with Android
> > -                * requirements. The camera service mandates all
> > preview/record
> > -                * streams to have a minimum frame duration < 33,366
> > milliseconds
> > -                * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera
> > service
> > -                * implementation).
> > -                *
> > -                * If we're close enough (+ 500 useconds) to that value,
> > round
> > -                * the minimum frame duration of the camera to an accepted
> > -                * value.
> > -                */
> > -               static constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS =
> > 1e9 / 29.97;
> > -               if (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS
> > &&
> > -                   minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS
> > + 500000)
> > -                       minFrameDurationNsec =
> > MAX_PREVIEW_RECORD_DURATION_NS - 1000;
> > -
> > -               /*
> > -                * The AE routine frame rate limits are computed using the
> > frame
> > -                * duration limits, as libcamera clips the AE routine to
> > the
> > -                * frame durations.
> > -                */
> > -               int32_t maxFps = std::round(1e9 / minFrameDurationNsec);
> > -               int32_t minFps = std::round(1e9 / maxFrameDurationNsec);
> > -               minFps = std::max(1, minFps);
> > -
> > -               /*
> > -                * Force rounding errors so that we have the proper frame
> > -                * durations for when we reuse these variables later
> > -                */
> > -               minFrameDurationNsec = 1e9 / maxFps;
> > -               maxFrameDurationNsec = 1e9 / minFps;
> > -
> > -               /*
> > -                * Register to the camera service {min, max} and {max, max}
> > -                * intervals as requested by the metadata documentation.
> > -                */
> > -               int32_t availableAeFpsTarget[] = {
> > -                       minFps, maxFps, maxFps, maxFps
> > -               };
> > -
> >  staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > -                                         availableAeFpsTarget);
> > -       }
> > -
> > -       std::vector<int32_t> aeCompensationRange = {
> > -               0, 0,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
> > -                                 aeCompensationRange);
> > -
> > -       const camera_metadata_rational_t aeCompensationStep[] = {
> > -               { 0, 1 }
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,
> > -                                 aeCompensationStep);
> > -
> > -       std::vector<uint8_t> availableAfModes = {
> > -               ANDROID_CONTROL_AF_MODE_OFF,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,
> > -                                 availableAfModes);
> > -
> > -       std::vector<uint8_t> availableEffects = {
> > -               ANDROID_CONTROL_EFFECT_MODE_OFF,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,
> > -                                 availableEffects);
> > -
> > -       std::vector<uint8_t> availableSceneModes = {
> > -               ANDROID_CONTROL_SCENE_MODE_DISABLED,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
> > -                                 availableSceneModes);
> > -
> > -       std::vector<uint8_t> availableStabilizationModes = {
> > -               ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
> > -       };
> > -
> >  staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
> > -                                 availableStabilizationModes);
> > -
> > -       /*
> > -        * \todo Inspect the Camera capabilities to report the available
> > -        * AWB modes. Default to AUTO as CTS tests require it.
> > -        */
> > -       std::vector<uint8_t> availableAwbModes = {
> > -               ANDROID_CONTROL_AWB_MODE_AUTO,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
> > -                                 availableAwbModes);
> > -
> > -       std::vector<int32_t> availableMaxRegions = {
> > -               0, 0, 0,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,
> > -                                 availableMaxRegions);
> > -
> > -       std::vector<uint8_t> sceneModesOverride = {
> > -               ANDROID_CONTROL_AE_MODE_ON,
> > -               ANDROID_CONTROL_AWB_MODE_AUTO,
> > -               ANDROID_CONTROL_AF_MODE_OFF,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
> > -                                 sceneModesOverride);
> > -
> > -       uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
> > -                                 aeLockAvailable);
> > -
> > -       uint8_t awbLockAvailable =
> > ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
> > -                                 awbLockAvailable);
> > -
> > -       char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
> > -       staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
> > -                                 availableControlModes);
> > -
> > -       /* JPEG static metadata. */
> > -
> > -       /*
> > -        * Create the list of supported thumbnail sizes by inspecting the
> > -        * available JPEG resolutions collected in streamConfigurations_
> > and
> > -        * generate one entry for each aspect ratio.
> > -        *
> > -        * The JPEG thumbnailer can freely scale, so pick an arbitrary
> > -        * (160, 160) size as the bounding rectangle, which is then
> > cropped to
> > -        * the different supported aspect ratios.
> > -        */
> > -       constexpr Size maxJpegThumbnail(160, 160);
> > -       std::vector<Size> thumbnailSizes;
> > -       thumbnailSizes.push_back({ 0, 0 });
> > -       for (const auto &entry : streamConfigurations_) {
> > -               if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)
> > -                       continue;
> > -
> > -               Size thumbnailSize = maxJpegThumbnail
> > -                                    .boundedToAspectRatio({
> > entry.resolution.width,
> > -
> > entry.resolution.height });
> > -               thumbnailSizes.push_back(thumbnailSize);
> > -       }
> > -
> > -       std::sort(thumbnailSizes.begin(), thumbnailSizes.end());
> > -       auto last = std::unique(thumbnailSizes.begin(),
> > thumbnailSizes.end());
> > -       thumbnailSizes.erase(last, thumbnailSizes.end());
> > -
> > -       /* Transform sizes in to a list of integers that can be consumed.
> > */
> > -       std::vector<int32_t> thumbnailEntries;
> > -       thumbnailEntries.reserve(thumbnailSizes.size() * 2);
> > -       for (const auto &size : thumbnailSizes) {
> > -               thumbnailEntries.push_back(size.width);
> > -               thumbnailEntries.push_back(size.height);
> > -       }
> > -       staticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
> > -                                 thumbnailEntries);
> > -
> > -       staticMetadata_->addEntry(ANDROID_JPEG_MAX_SIZE,
> > maxJpegBufferSize_);
> > -
> > -       /* Sensor static metadata. */
> > -       std::array<int32_t, 2> pixelArraySize;
> > -       {
> > -               const Size &size =
> > properties.get(properties::PixelArraySize);
> > -               pixelArraySize[0] = size.width;
> > -               pixelArraySize[1] = size.height;
> > -
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
> > -                                         pixelArraySize);
> > -       }
> > -
> > -       if (properties.contains(properties::UnitCellSize)) {
> > -               const Size &cellSize =
> > properties.get<Size>(properties::UnitCellSize);
> > -               std::array<float, 2> physicalSize{
> > -                       cellSize.width * pixelArraySize[0] / 1e6f,
> > -                       cellSize.height * pixelArraySize[1] / 1e6f
> > -               };
> > -
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
> > -                                         physicalSize);
> > -       }
> > -
> > -       {
> > -               const Span<const Rectangle> &rects =
> > -                       properties.get(properties::PixelArrayActiveAreas);
> > -               std::vector<int32_t> data{
> > -                       static_cast<int32_t>(rects[0].x),
> > -                       static_cast<int32_t>(rects[0].y),
> > -                       static_cast<int32_t>(rects[0].width),
> > -                       static_cast<int32_t>(rects[0].height),
> > -               };
> > -
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
> > -                                         data);
> > -       }
> > -
> > -       int32_t sensitivityRange[] = {
> > -               32, 2400,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
> > -                                 sensitivityRange);
> > -
> > -       /* Report the color filter arrangement if the camera reports it. */
> > -       if
> > (properties.contains(properties::draft::ColorFilterArrangement)) {
> > -               uint8_t filterArr =
> > properties.get(properties::draft::ColorFilterArrangement);
> > -
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
> > -                                         filterArr);
> > -       }
> > -
> > -       const auto &exposureInfo =
> > controlsInfo.find(&controls::ExposureTime);
> > -       if (exposureInfo != controlsInfo.end()) {
> > -               int64_t exposureTimeRange[2] = {
> > -                       exposureInfo->second.min().get<int32_t>() * 1000LL,
> > -                       exposureInfo->second.max().get<int32_t>() * 1000LL,
> > -               };
> > -
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
> > -                                         exposureTimeRange, 2);
> > -       }
> > -
> > -       staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,
> > orientation_);
> > -
> > -       std::vector<int32_t> testPatternModes = {
> > -               ANDROID_SENSOR_TEST_PATTERN_MODE_OFF
> > -       };
> > -       const auto &testPatternsInfo =
> > -               controlsInfo.find(&controls::draft::TestPatternMode);
> > -       if (testPatternsInfo != controlsInfo.end()) {
> > -               const auto &values = testPatternsInfo->second.values();
> > -               ASSERT(!values.empty());
> > -               for (const auto &value : values) {
> > -                       switch (value.get<int32_t>()) {
> > -                       case controls::draft::TestPatternModeOff:
> > -                               /*
> > -                                * ANDROID_SENSOR_TEST_PATTERN_MODE_OFF is
> > -                                * already in testPatternModes.
> > -                                */
> > -                               break;
> > -
> > -                       case controls::draft::TestPatternModeSolidColor:
> > -                               testPatternModes.push_back(
> > -
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR);
> > -                               break;
> > -
> > -                       case controls::draft::TestPatternModeColorBars:
> > -                               testPatternModes.push_back(
> > -
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS);
> > -                               break;
> > -
> > -                       case
> > controls::draft::TestPatternModeColorBarsFadeToGray:
> > -                               testPatternModes.push_back(
> > -
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY);
> > -                               break;
> > -
> > -                       case controls::draft::TestPatternModePn9:
> > -                               testPatternModes.push_back(
> > -
> >  ANDROID_SENSOR_TEST_PATTERN_MODE_PN9);
> > -                               break;
> > -
> > -                       case controls::draft::TestPatternModeCustom1:
> > -                               /* We don't support this yet. */
> > -                               break;
> > -
> > -                       default:
> > -                               LOG(HAL, Error) << "Unknown test pattern
> > mode: "
> > -                                               << value.get<int32_t>();
> > -                               continue;
> > -                       }
> > -               }
> > -       }
> > -
> >  staticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
> > -                                 testPatternModes);
> > -
> > -       uint8_t timestampSource =
> > ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
> > -       staticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
> > -                                 timestampSource);
> > -
> > -       if (maxFrameDurationNsec > 0)
> > -
> >  staticMetadata_->addEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
> > -                                         maxFrameDurationNsec);
> > -
> > -       /* Statistics static metadata. */
> > -       uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
> > -
> >  staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
> > -                                 faceDetectMode);
> > -
> > -       int32_t maxFaceCount = 0;
> > -       staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
> > -                                 maxFaceCount);
> > -
> > -       {
> > -               std::vector<uint8_t> data;
> > -               data.reserve(2);
> > -               const auto &infoMap =
> > controlsInfo.find(&controls::draft::LensShadingMapMode);
> > -               if (infoMap != controlsInfo.end()) {
> > -                       for (const auto &value : infoMap->second.values())
> > -                               data.push_back(value.get<int32_t>());
> > -               } else {
> > -
> >  data.push_back(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);
> > -               }
> > -
> >  staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
> > -                                         data);
> > -       }
> > -
> > -       /* Sync static metadata. */
> > -       int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
> > -       staticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, maxLatency);
> > -
> > -       /* Flash static metadata. */
> > -       char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
> > -       staticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,
> > -                                 flashAvailable);
> > -
> > -       /* Lens static metadata. */
> > -       std::vector<float> lensApertures = {
> > -               2.53 / 100,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
> > -                                 lensApertures);
> > -
> > -       uint8_t lensFacing;
> > -       switch (facing_) {
> > -       default:
> > -       case CAMERA_FACING_FRONT:
> > -               lensFacing = ANDROID_LENS_FACING_FRONT;
> > -               break;
> > -       case CAMERA_FACING_BACK:
> > -               lensFacing = ANDROID_LENS_FACING_BACK;
> > -               break;
> > -       case CAMERA_FACING_EXTERNAL:
> > -               lensFacing = ANDROID_LENS_FACING_EXTERNAL;
> > -               break;
> > -       }
> > -       staticMetadata_->addEntry(ANDROID_LENS_FACING, lensFacing);
> > -
> > -       std::vector<float> lensFocalLengths = {
> > -               1,
> > -       };
> > -
> >  staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
> > -                                 lensFocalLengths);
> > -
> > -       std::vector<uint8_t> opticalStabilizations = {
> > -               ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
> > -       };
> > -
> >  staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
> > -                                 opticalStabilizations);
> > -
> > -       float hypeFocalDistance = 0;
> > -       staticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
> > -                                 hypeFocalDistance);
> > -
> > -       float minFocusDistance = 0;
> > -       staticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
> > -                                 minFocusDistance);
> > -
> > -       /* Noise reduction modes. */
> > -       {
> > -               std::vector<uint8_t> data;
> > -               data.reserve(5);
> > -               const auto &infoMap =
> > controlsInfo.find(&controls::draft::NoiseReductionMode);
> > -               if (infoMap != controlsInfo.end()) {
> > -                       for (const auto &value : infoMap->second.values())
> > -                               data.push_back(value.get<int32_t>());
> > -               } else {
> > -                       data.push_back(ANDROID_NOISE_REDUCTION_MODE_OFF);
> > -               }
> > -
> >  staticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
> > -                                         data);
> > -       }
> > -
> > -       /* Scaler static metadata. */
> > -
> > -       /*
> > -        * \todo The digital zoom factor is a property that depends on the
> > -        * desired output configuration and the sensor frame size input to
> > the
> > -        * ISP. This information is not available to the Android HAL, not
> > at
> > -        * initialization time at least.
> > -        *
> > -        * As a workaround rely on pipeline handlers initializing the
> > -        * ScalerCrop control with the camera default configuration and
> > use the
> > -        * maximum and minimum crop rectangles to calculate the digital
> > zoom
> > -        * factor.
> > -        */
> > -       float maxZoom = 1.0f;
> > -       const auto scalerCrop = controlsInfo.find(&controls::ScalerCrop);
> > -       if (scalerCrop != controlsInfo.end()) {
> > -               Rectangle min = scalerCrop->second.min().get<Rectangle>();
> > -               Rectangle max = scalerCrop->second.max().get<Rectangle>();
> > -               maxZoom = std::min(1.0f * max.width / min.width,
> > -                                  1.0f * max.height / min.height);
> > -       }
> > -
> >  staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
> > -                                 maxZoom);
> > -
> > -       std::vector<uint32_t> availableStreamConfigurations;
> > -       availableStreamConfigurations.reserve(streamConfigurations_.size()
> > * 4);
> > -       for (const auto &entry : streamConfigurations_) {
> > -
> >  availableStreamConfigurations.push_back(entry.androidFormat);
> > -
> >  availableStreamConfigurations.push_back(entry.resolution.width);
> > -
> >  availableStreamConfigurations.push_back(entry.resolution.height);
> > -               availableStreamConfigurations.push_back(
> > -
> >  ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
> > -       }
> > -
> >  staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
> > -                                 availableStreamConfigurations);
> > -
> > -       std::vector<int64_t> availableStallDurations = {
> > -               ANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,
> > 33333333,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
> > -                                 availableStallDurations);
> > -
> > -       /* Use the minimum frame duration for all the YUV/RGB formats. */
> > -       if (minFrameDurationNsec > 0) {
> > -               std::vector<int64_t> minFrameDurations;
> > -               minFrameDurations.reserve(streamConfigurations_.size() *
> > 4);
> > -               for (const auto &entry : streamConfigurations_) {
> > -                       minFrameDurations.push_back(entry.androidFormat);
> > -
> >  minFrameDurations.push_back(entry.resolution.width);
> > -
> >  minFrameDurations.push_back(entry.resolution.height);
> > -                       minFrameDurations.push_back(minFrameDurationNsec);
> > -               }
> > -
> >  staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
> > -                                         minFrameDurations);
> > -       }
> > -
> > -       uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
> > -       staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE,
> > croppingType);
> > -
> > -       /* Info static metadata. */
> > -       uint8_t supportedHWLevel =
> > ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
> > -       staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
> > -                                 supportedHWLevel);
> > -
> > -       /* Request static metadata. */
> > -       int32_t partialResultCount = 1;
> > -       staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
> > -                                 partialResultCount);
> > -
> > -       {
> > -               /* Default the value to 2 if not reported by the camera. */
> > -               uint8_t maxPipelineDepth = 2;
> > -               const auto &infoMap =
> > controlsInfo.find(&controls::draft::PipelineDepth);
> > -               if (infoMap != controlsInfo.end())
> > -                       maxPipelineDepth =
> > infoMap->second.max().get<int32_t>();
> > -
> >  staticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
> > -                                         maxPipelineDepth);
> > -       }
> > -
> > -       /* LIMITED does not support reprocessing. */
> > -       uint32_t maxNumInputStreams = 0;
> > -       staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
> > -                                 maxNumInputStreams);
> > -
> > -       std::vector<uint8_t> availableCapabilities = {
> > -               ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
> > -       };
> > -
> > -       /* Report if camera supports RAW. */
> > -       bool rawStreamAvailable = false;
> > -       std::unique_ptr<CameraConfiguration> cameraConfig =
> > -               camera_->generateConfiguration({ StreamRole::Raw });
> > -       if (cameraConfig && !cameraConfig->empty()) {
> > -               const PixelFormatInfo &info =
> > -
> >  PixelFormatInfo::info(cameraConfig->at(0).pixelFormat);
> > -               /* Only advertise RAW support if RAW16 is possible. */
> > -               if (info.colourEncoding ==
> > PixelFormatInfo::ColourEncodingRAW &&
> > -                   info.bitsPerPixel == 16) {
> > -                       rawStreamAvailable = true;
> > -
> >  availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
> > -               }
> > -       }
> > -
> > -       /* Number of { RAW, YUV, JPEG } supported output streams */
> > -       int32_t numOutStreams[] = { rawStreamAvailable, 2, 1 };
> > -       staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
> > -                                 numOutStreams);
> > -
> > -       staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
> > -                                 availableCapabilities);
> > -
> > -       std::vector<int32_t> availableCharacteristicsKeys = {
> > -               ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
> > -               ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
> > -               ANDROID_CONTROL_AE_AVAILABLE_MODES,
> > -               ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > -               ANDROID_CONTROL_AE_COMPENSATION_RANGE,
> > -               ANDROID_CONTROL_AE_COMPENSATION_STEP,
> > -               ANDROID_CONTROL_AE_LOCK_AVAILABLE,
> > -               ANDROID_CONTROL_AF_AVAILABLE_MODES,
> > -               ANDROID_CONTROL_AVAILABLE_EFFECTS,
> > -               ANDROID_CONTROL_AVAILABLE_MODES,
> > -               ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
> > -               ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
> > -               ANDROID_CONTROL_AWB_AVAILABLE_MODES,
> > -               ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
> > -               ANDROID_CONTROL_MAX_REGIONS,
> > -               ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
> > -               ANDROID_FLASH_INFO_AVAILABLE,
> > -               ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
> > -               ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
> > -               ANDROID_JPEG_MAX_SIZE,
> > -               ANDROID_LENS_FACING,
> > -               ANDROID_LENS_INFO_AVAILABLE_APERTURES,
> > -               ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
> > -               ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
> > -               ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
> > -               ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
> > -               ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
> > -               ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
> > -               ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
> > -               ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
> > -               ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
> > -               ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
> > -               ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
> > -               ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
> > -               ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
> > -               ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
> > -               ANDROID_SCALER_CROPPING_TYPE,
> > -               ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
> > -               ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
> > -               ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
> > -               ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
> > -               ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
> > -               ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
> > -               ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
> > -               ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
> > -               ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
> > -               ANDROID_SENSOR_ORIENTATION,
> > -               ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
> > -               ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
> > -               ANDROID_SYNC_MAX_LATENCY,
> > -       };
> > -
> >  staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
> > -                                 availableCharacteristicsKeys);
> > -
> > -       std::vector<int32_t> availableRequestKeys = {
> > -               ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
> > -               ANDROID_CONTROL_AE_ANTIBANDING_MODE,
> > -               ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
> > -               ANDROID_CONTROL_AE_LOCK,
> > -               ANDROID_CONTROL_AE_MODE,
> > -               ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
> > -               ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > -               ANDROID_CONTROL_AF_MODE,
> > -               ANDROID_CONTROL_AF_TRIGGER,
> > -               ANDROID_CONTROL_AWB_LOCK,
> > -               ANDROID_CONTROL_AWB_MODE,
> > -               ANDROID_CONTROL_CAPTURE_INTENT,
> > -               ANDROID_CONTROL_EFFECT_MODE,
> > -               ANDROID_CONTROL_MODE,
> > -               ANDROID_CONTROL_SCENE_MODE,
> > -               ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
> > -               ANDROID_FLASH_MODE,
> > -               ANDROID_JPEG_ORIENTATION,
> > -               ANDROID_JPEG_QUALITY,
> > -               ANDROID_JPEG_THUMBNAIL_QUALITY,
> > -               ANDROID_JPEG_THUMBNAIL_SIZE,
> > -               ANDROID_LENS_APERTURE,
> > -               ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
> > -               ANDROID_NOISE_REDUCTION_MODE,
> > -               ANDROID_SCALER_CROP_REGION,
> > -               ANDROID_STATISTICS_FACE_DETECT_MODE
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
> > -                                 availableRequestKeys);
> > -
> > -       std::vector<int32_t> availableResultKeys = {
> > -               ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
> > -               ANDROID_CONTROL_AE_ANTIBANDING_MODE,
> > -               ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
> > -               ANDROID_CONTROL_AE_LOCK,
> > -               ANDROID_CONTROL_AE_MODE,
> > -               ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
> > -               ANDROID_CONTROL_AE_STATE,
> > -               ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > -               ANDROID_CONTROL_AF_MODE,
> > -               ANDROID_CONTROL_AF_STATE,
> > -               ANDROID_CONTROL_AF_TRIGGER,
> > -               ANDROID_CONTROL_AWB_LOCK,
> > -               ANDROID_CONTROL_AWB_MODE,
> > -               ANDROID_CONTROL_AWB_STATE,
> > -               ANDROID_CONTROL_CAPTURE_INTENT,
> > -               ANDROID_CONTROL_EFFECT_MODE,
> > -               ANDROID_CONTROL_MODE,
> > -               ANDROID_CONTROL_SCENE_MODE,
> > -               ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
> > -               ANDROID_FLASH_MODE,
> > -               ANDROID_FLASH_STATE,
> > -               ANDROID_JPEG_GPS_COORDINATES,
> > -               ANDROID_JPEG_GPS_PROCESSING_METHOD,
> > -               ANDROID_JPEG_GPS_TIMESTAMP,
> > -               ANDROID_JPEG_ORIENTATION,
> > -               ANDROID_JPEG_QUALITY,
> > -               ANDROID_JPEG_SIZE,
> > -               ANDROID_JPEG_THUMBNAIL_QUALITY,
> > -               ANDROID_JPEG_THUMBNAIL_SIZE,
> > -               ANDROID_LENS_APERTURE,
> > -               ANDROID_LENS_FOCAL_LENGTH,
> > -               ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
> > -               ANDROID_LENS_STATE,
> > -               ANDROID_NOISE_REDUCTION_MODE,
> > -               ANDROID_REQUEST_PIPELINE_DEPTH,
> > -               ANDROID_SCALER_CROP_REGION,
> > -               ANDROID_SENSOR_EXPOSURE_TIME,
> > -               ANDROID_SENSOR_FRAME_DURATION,
> > -               ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
> > -               ANDROID_SENSOR_TEST_PATTERN_MODE,
> > -               ANDROID_SENSOR_TIMESTAMP,
> > -               ANDROID_STATISTICS_FACE_DETECT_MODE,
> > -               ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
> > -               ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
> > -               ANDROID_STATISTICS_SCENE_FLICKER,
> > -       };
> > -       staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
> > -                                 availableResultKeys);
> > -
> > -       if (!staticMetadata_->isValid()) {
> > -               LOG(HAL, Error) << "Failed to construct static metadata";
> > -               staticMetadata_.reset();
> > -               return nullptr;
> > -       }
> > -
> > -       if (staticMetadata_->resized()) {
> > -               auto [entryCount, dataCount] = staticMetadata_->usage();
> > -               LOG(HAL, Info)
> > -                       << "Static metadata resized: " << entryCount
> > -                       << " entries and " << dataCount << " bytes used";
> > -       }
> > -
> > -       return staticMetadata_->get();
> > -}
> > -
> > -std::unique_ptr<CameraMetadata> CameraDevice::requestTemplatePreview()
> > +void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)
> >  {
> > -       /*
> > -        * \todo Keep this in sync with the actual number of entries.
> > -        * Currently: 20 entries, 35 bytes
> > -        */
> > -       auto requestTemplate = std::make_unique<CameraMetadata>(21, 36);
> > -       if (!requestTemplate->isValid()) {
> > -               return nullptr;
> > -       }
> > -
> > -       /* Get the FPS range registered in the static metadata. */
> > -       camera_metadata_ro_entry_t entry;
> > -       bool found =
> > staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > -                                              &entry);
> > -       if (!found) {
> > -               LOG(HAL, Error) << "Cannot create capture template without
> > FPS range";
> > -               return nullptr;
> > -       }
> > -
> > -       /*
> > -        * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
> > -        * has been assembled as {{min, max} {max, max}}.
> > -        */
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > -                                 entry.data.i32, 2);
> > -
> > -       uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AE_MODE, aeMode);
> > -
> > -       int32_t aeExposureCompensation = 0;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
> > -                                 aeExposureCompensation);
> > -
> > -       uint8_t aePrecaptureTrigger =
> > ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
> > -                                 aePrecaptureTrigger);
> > -
> > -       uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AE_LOCK, aeLock);
> > -
> > -       uint8_t aeAntibandingMode =
> > ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AE_ANTIBANDING_MODE,
> > -                                 aeAntibandingMode);
> > -
> > -       uint8_t afMode = ANDROID_CONTROL_AF_MODE_OFF;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AF_MODE, afMode);
> > -
> > -       uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AF_TRIGGER, afTrigger);
> > -
> > -       uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AWB_MODE, awbMode);
> > -
> > -       uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_AWB_LOCK, awbLock);
> > -
> > -       uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
> > -       requestTemplate->addEntry(ANDROID_FLASH_MODE, flashMode);
> > -
> > -       uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
> > -       requestTemplate->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,
> > -                                 faceDetectMode);
> > -
> > -       uint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;
> > -       requestTemplate->addEntry(ANDROID_NOISE_REDUCTION_MODE,
> > -                                 noiseReduction);
> > -
> > -       uint8_t aberrationMode =
> > ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;
> > -       requestTemplate->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
> > -                                 aberrationMode);
> > -
> > -       uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_MODE, controlMode);
> > -
> > -       float lensAperture = 2.53 / 100;
> > -       requestTemplate->addEntry(ANDROID_LENS_APERTURE, lensAperture);
> > -
> > -       uint8_t opticalStabilization =
> > ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
> > -       requestTemplate->addEntry(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
> > -                                 opticalStabilization);
> > -
> > -       uint8_t captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
> > -       requestTemplate->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,
> > -                                 captureIntent);
> > -
> > -       return requestTemplate;
> > +       callbacks_ = callbacks;
> >  }
> >
> > -std::unique_ptr<CameraMetadata> CameraDevice::requestTemplateVideo()
> > +const camera_metadata_t *CameraDevice::getStaticMetadata()
> >  {
> > -       std::unique_ptr<CameraMetadata> previewTemplate =
> > requestTemplatePreview();
> > -       if (!previewTemplate)
> > -               return nullptr;
> > -
> > -       /*
> > -        * The video template requires a fixed FPS range. Everything else
> > -        * stays the same as the preview template.
> > -        */
> > -       camera_metadata_ro_entry_t entry;
> > -
> >  staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > -                                 &entry);
> > -
> > -       /*
> > -        * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
> > -        * has been assembled as {{min, max} {max, max}}.
> > -        */
> > -       previewTemplate->updateEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
> > -                                    entry.data.i32 + 2, 2);
> > -
> > -       return previewTemplate;
> > +       return capabilities_.staticMetadata()->get();
> >  }
> >
> >  /*
> > @@ -1630,7 +520,7 @@ const camera_metadata_t
> > *CameraDevice::constructDefaultRequestSettings(int type)
> >         switch (type) {
> >         case CAMERA3_TEMPLATE_PREVIEW:
> >                 captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
> > -               requestTemplate = requestTemplatePreview();
> > +               requestTemplate = capabilities_.requestTemplatePreview();
> >                 break;
> >         case CAMERA3_TEMPLATE_STILL_CAPTURE:
> >                 /*
> > @@ -1638,15 +528,15 @@ const camera_metadata_t
> > *CameraDevice::constructDefaultRequestSettings(int type)
> >                  * for the torch mode we currently do not support.
> >                  */
> >                 captureIntent =
> > ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
> > -               requestTemplate = requestTemplatePreview();
> > +               requestTemplate = capabilities_.requestTemplatePreview();
> >                 break;
> >         case CAMERA3_TEMPLATE_VIDEO_RECORD:
> >                 captureIntent =
> > ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
> > -               requestTemplate = requestTemplateVideo();
> > +               requestTemplate = capabilities_.requestTemplateVideo();
> >                 break;
> >         case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
> >                 captureIntent =
> > ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
> > -               requestTemplate = requestTemplateVideo();
> > +               requestTemplate = capabilities_.requestTemplateVideo();
> >                 break;
> >         /* \todo Implement templates generation for the remaining use
> > cases. */
> >         case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
> > @@ -1668,19 +558,6 @@ const camera_metadata_t
> > *CameraDevice::constructDefaultRequestSettings(int type)
> >         return requestTemplates_[type]->get();
> >  }
> >
> > -PixelFormat CameraDevice::toPixelFormat(int format) const
> > -{
> > -       /* Translate Android format code to libcamera pixel format. */
> > -       auto it = formatsMap_.find(format);
> > -       if (it == formatsMap_.end()) {
> > -               LOG(HAL, Error) << "Requested format " <<
> > utils::hex(format)
> > -                               << " not supported";
> > -               return PixelFormat();
> > -       }
> > -
> > -       return it->second;
> > -}
> > -
> >  /*
> >   * Inspect the stream_list to produce a list of StreamConfiguration to
> >   * be use to configure the Camera.
> > @@ -1727,7 +604,7 @@ int
> > CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
> >                 camera3_stream_t *stream = stream_list->streams[i];
> >                 Size size(stream->width, stream->height);
> >
> > -               PixelFormat format = toPixelFormat(stream->format);
> > +               PixelFormat format =
> > capabilities_.toPixelFormat(stream->format);
> >
> >                 LOG(HAL, Info) << "Stream #" << i
> >                                << ", direction: " << stream->stream_type
> > diff --git a/src/android/camera_device.h b/src/android/camera_device.h
> > index 4aadb27c562c..090fe28a551e 100644
> > --- a/src/android/camera_device.h
> > +++ b/src/android/camera_device.h
> > @@ -10,14 +10,12 @@
> >  #include <map>
> >  #include <memory>
> >  #include <mutex>
> > -#include <tuple>
> >  #include <vector>
> >
> >  #include <hardware/camera3.h>
> >
> >  #include <libcamera/buffer.h>
> >  #include <libcamera/camera.h>
> > -#include <libcamera/geometry.h>
> >  #include <libcamera/request.h>
> >  #include <libcamera/stream.h>
> >
> > @@ -26,6 +24,7 @@
> >  #include "libcamera/internal/message.h"
> >  #include "libcamera/internal/thread.h"
> >
> > +#include "camera_capabilities.h"
> >  #include "camera_metadata.h"
> >  #include "camera_stream.h"
> >  #include "camera_worker.h"
> > @@ -57,7 +56,7 @@ public:
> >         const std::string &model() const { return model_; }
> >         int facing() const { return facing_; }
> >         int orientation() const { return orientation_; }
> > -       unsigned int maxJpegBufferSize() const { return
> > maxJpegBufferSize_; }
> > +       unsigned int maxJpegBufferSize() const;
> >
> >         void setCallbacks(const camera3_callback_ops_t *callbacks);
> >         const camera_metadata_t *getStaticMetadata();
> > @@ -86,11 +85,6 @@ private:
> >                 std::unique_ptr<CaptureRequest> request_;
> >         };
> >
> > -       struct Camera3StreamConfiguration {
> > -               libcamera::Size resolution;
> > -               int androidFormat;
> > -       };
> > -
> >         enum class State {
> >                 Stopped,
> >                 Flushing,
> > @@ -99,22 +93,11 @@ private:
> >
> >         void stop();
> >
> > -       int initializeStreamConfigurations();
> > -       std::vector<libcamera::Size>
> > -       getYUVResolutions(libcamera::CameraConfiguration *cameraConfig,
> > -                         const libcamera::PixelFormat &pixelFormat,
> > -                         const std::vector<libcamera::Size> &resolutions);
> > -       std::vector<libcamera::Size>
> > -       getRawResolutions(const libcamera::PixelFormat &pixelFormat);
> > -
> >         libcamera::FrameBuffer *createFrameBuffer(const buffer_handle_t
> > camera3buffer);
> >         void abortRequest(camera3_capture_request_t *request);
> >         void notifyShutter(uint32_t frameNumber, uint64_t timestamp);
> >         void notifyError(uint32_t frameNumber, camera3_stream_t *stream,
> >                          camera3_error_msg_code code);
> > -       std::unique_ptr<CameraMetadata> requestTemplatePreview();
> > -       std::unique_ptr<CameraMetadata> requestTemplateVideo();
> > -       libcamera::PixelFormat toPixelFormat(int format) const;
> >         int processControls(Camera3RequestDescriptor *descriptor);
> >         std::unique_ptr<CameraMetadata> getResultMetadata(
> >                 const Camera3RequestDescriptor &descriptor) const;
> > @@ -129,13 +112,11 @@ private:
> >
> >         std::shared_ptr<libcamera::Camera> camera_;
> >         std::unique_ptr<libcamera::CameraConfiguration> config_;
> > +       CameraCapabilities capabilities_;
> >
> > -       std::unique_ptr<CameraMetadata> staticMetadata_;
> >         std::map<unsigned int, std::unique_ptr<CameraMetadata>>
> > requestTemplates_;
> >         const camera3_callback_ops_t *callbacks_;
> >
> > -       std::vector<Camera3StreamConfiguration> streamConfigurations_;
> > -       std::map<int, libcamera::PixelFormat> formatsMap_;
> >         std::vector<CameraStream> streams_;
> >
> >         libcamera::Mutex descriptorsMutex_; /* Protects descriptors_. */
> > @@ -147,8 +128,6 @@ private:
> >         int facing_;
> >         int orientation_;
> >
> > -       unsigned int maxJpegBufferSize_;
> > -
> >         CameraMetadata lastSettings_;
> >  };
> >
> > diff --git a/src/android/meson.build b/src/android/meson.build
> > index f27fd5316705..6270fb201338 100644
> > --- a/src/android/meson.build
> > +++ b/src/android/meson.build
> > @@ -44,6 +44,7 @@ subdir('cros')
> >
> >  android_hal_sources = files([
> >      'camera3_hal.cpp',
> > +    'camera_capabilities.cpp',
> >      'camera_device.cpp',
> >      'camera_hal_config.cpp',
> >      'camera_hal_manager.cpp',
> > --
> > 2.31.1
> >
> >


More information about the libcamera-devel mailing list