Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ cf_cc_binary(
"//cuttlefish/common/libs/utils:in_sandbox",
"//cuttlefish/common/libs/utils:tee_logging",
"//cuttlefish/host/commands/assemble_cvd:assemble_cvd_flags",
"//cuttlefish/host/commands/assemble_cvd:camera",
"//cuttlefish/host/commands/assemble_cvd:clean",
"//cuttlefish/host/commands/assemble_cvd:create_dynamic_disk_files",
"//cuttlefish/host/commands/assemble_cvd:display",
Expand Down Expand Up @@ -306,6 +307,7 @@ cf_cc_library(
"//cuttlefish/common/libs/utils:network",
"//cuttlefish/host/commands/assemble_cvd:alloc",
"//cuttlefish/host/commands/assemble_cvd:assemble_cvd_flags",
"//cuttlefish/host/commands/assemble_cvd:camera",
"//cuttlefish/host/commands/assemble_cvd:disk_image_flags_vectorization",
"//cuttlefish/host/commands/assemble_cvd:display",
"//cuttlefish/host/commands/assemble_cvd:flags_defaults",
Expand Down Expand Up @@ -638,3 +640,19 @@ cf_cc_library(
# required for the gflags `DEFINE`s when included in other targets
alwayslink = 1,
)

cf_cc_library(
name = "camera",
srcs = ["camera.cpp"],
hdrs = ["camera.h"],
deps = [
"//cuttlefish/common/libs/utils:flag_parser",
"//cuttlefish/host/libs/config:camera",
"//cuttlefish/host/libs/config:config_flag",
"//cuttlefish/host/libs/config:config_fragment",
"//cuttlefish/host/libs/config:cuttlefish_config",
"//cuttlefish/host/libs/feature",
"@abseil-cpp//absl/log",
"@fruit",
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "cuttlefish/host/commands/assemble_cvd/android_build/android_builds.h"
#include "cuttlefish/host/commands/assemble_cvd/android_build/identify_build.h"
#include "cuttlefish/host/commands/assemble_cvd/assemble_cvd_flags.h"
#include "cuttlefish/host/commands/assemble_cvd/camera.h"
#include "cuttlefish/host/commands/assemble_cvd/clean.h"
#include "cuttlefish/host/commands/assemble_cvd/create_dynamic_disk_files.h"
#include "cuttlefish/host/commands/assemble_cvd/disk/ap_composite_disk.h"
Expand Down Expand Up @@ -520,7 +521,10 @@ fruit::Component<> FlagsComponent(SystemImageDirFlag* system_image_dir) {
.install(FastbootConfigFragmentComponent)
.install(GflagsComponent)
.install(ConfigFlagComponent)
.install(CustomActionsComponent);
.install(CustomActionsComponent)
.install(CamerasConfigsComponent)
.install(CamerasConfigsFlagComponent)
.install(CamerasConfigsFragmentComponent);
}

Result<void> CheckNoTTY() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,15 @@ Result<std::unordered_map<std::string, std::string>> BootconfigArgsFromConfig(
bootconfig_args["androidboot.wifi_impl"] = "virt_wifi";
}

bootconfig_args
["androidboot.vendor.apex.com.google.emulated.camera.provider.hal"] =
// Camera configs is only populated for virtio-media host camera
// devices. The V4L2 Camera HAL implementation would handle all
// (possibly multiple) host cameras devices.
instance.camera_configs().empty()
? "com.google.emulated.camera.provider.hal"
: "com.google.emulated.camera.provider.hal.v4l2";

if (!instance.vcpu_config_path().empty()) {
auto vcpu_config_json =
CF_EXPECT(LoadFromFile(instance.vcpu_config_path()));
Expand Down
147 changes: 147 additions & 0 deletions base/cvd/cuttlefish/host/commands/assemble_cvd/camera.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//
// Copyright (C) 2026 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cuttlefish/host/commands/assemble_cvd/camera.h"

#include "absl/log/log.h"

#include "cuttlefish/common/libs/utils/flag_parser.h"
#include "cuttlefish/host/libs/config/camera.h"

namespace cuttlefish {
namespace {

class CamerasConfigsImpl : public CamerasConfigs {
public:
INJECT(CamerasConfigsImpl()) {}

const std::vector<CuttlefishConfig::CameraConfig>& GetConfigs()
const override {
return camera_configs_;
}

void SetConfigs(const std::vector<CuttlefishConfig::CameraConfig>& configs) override {
camera_configs_ = configs;
}

std::string Name() const override { return "CamerasConfigsImpl"; }

private:
std::vector<CuttlefishConfig::CameraConfig> camera_configs_;
};

} // namespace

fruit::Component<CamerasConfigs> CamerasConfigsComponent() {
return fruit::createComponent()
.bind<CamerasConfigs, CamerasConfigsImpl>()
.addMultibinding<CamerasConfigs, CamerasConfigs>();
}

namespace {

class CamerasConfigsFlagImpl : public CamerasConfigsFlag {
public:
INJECT(CamerasConfigsFlagImpl(CamerasConfigs& configs,
ConfigFlag& config_flag))
: camera_configs_(configs), config_flag_dependency_(config_flag) {}

std::string Name() const override { return "CamerasConfigsFlagImpl"; }

std::unordered_set<FlagFeature*> Dependencies() const override {
return {static_cast<FlagFeature*>(&config_flag_dependency_)};
}

Result<void> Process(std::vector<std::string>& args) override {
camera_configs_.SetConfigs(CF_EXPECT(ParseCameraConfigsFromArgs(args)));
return {};
}

bool WriteGflagsCompatHelpXml(std::ostream& out) const override {
Flag camera_flag = GflagsCompatFlag(kCameraFlag).Help(kCameraHelp);
return WriteGflagsCompatXml({camera_flag}, out);
}

private:
CamerasConfigs& camera_configs_;
ConfigFlag& config_flag_dependency_;
};

} // namespace

fruit::Component<fruit::Required<CamerasConfigs, ConfigFlag>,
CamerasConfigsFlag>
CamerasConfigsFlagComponent() {
return fruit::createComponent()
.bind<CamerasConfigsFlag, CamerasConfigsFlagImpl>()
.addMultibinding<FlagFeature, CamerasConfigsFlag>();
}

namespace {

class CamerasConfigsFragmentImpl : public CamerasConfigsFragment {
public:
INJECT(CamerasConfigsFragmentImpl(CamerasConfigs& configs))
: configs_(configs) {}

std::string Name() const override { return "CamerasConfigsFragmentImpl"; }

Json::Value Serialize() const override {
Json::Value configs_json(Json::arrayValue);
for (const auto& config : configs_.GetConfigs()) {
Json::Value json(Json::objectValue);
json[kType] = static_cast<int>(config.type);
configs_json.append(json);
}
return configs_json;
}

bool Deserialize(const Json::Value& json) override {
if (!json.isMember(kCameraConfigs)) {
LOG(ERROR) << "Invalid value for " << kCameraConfigs;
return false;
}

const Json::Value& configs_json = json[kCameraConfigs];

std::vector<CuttlefishConfig::CameraConfig> configs;
for (auto& json : configs_json) {
CuttlefishConfig::CameraConfig config = {};
config.type =
static_cast<CuttlefishConfig::CameraType>(json[kType].asInt());
configs.emplace_back(config);
}

configs_.SetConfigs(configs);
return true;
}

private:
static constexpr char kCameraConfigs[] = "camera_configs";
static constexpr char kType[] = "type";
CamerasConfigs& configs_;
};

} // namespace

fruit::Component<fruit::Required<CamerasConfigs>, CamerasConfigsFragment>
CamerasConfigsFragmentComponent() {
return fruit::createComponent()
.bind<CamerasConfigsFragment, CamerasConfigsFragmentImpl>()
.addMultibinding<ConfigFragment, CamerasConfigsFragment>();
}

} // namespace cuttlefish

58 changes: 58 additions & 0 deletions base/cvd/cuttlefish/host/commands/assemble_cvd/camera.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// Copyright (C) 2026 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <fruit/fruit.h>
#include <string>
#include <vector>

#include "cuttlefish/host/libs/config/config_flag.h"
#include "cuttlefish/host/libs/config/config_fragment.h"
#include "cuttlefish/host/libs/config/cuttlefish_config.h"
// #include "cuttlefish/host/libs/config/feature.h"

namespace cuttlefish {

// Component to share data between CamerasConfigsFlag and CamerasConfigsFragment
class CamerasConfigs {
public:
virtual ~CamerasConfigs() = default;

virtual std::string Name() const = 0;

virtual const std::vector<CuttlefishConfig::CameraConfig>& GetConfigs()
const = 0;
virtual void SetConfigs(
const std::vector<CuttlefishConfig::CameraConfig>& configs) = 0;
};

// Component to parse the --camera command line flag and update the
// CamerasConfigs.
class CamerasConfigsFlag : public FlagFeature {};

// Component to serialize and deserialize the CamerasConfigs to/from Json.
class CamerasConfigsFragment : public ConfigFragment {};

fruit::Component<CamerasConfigs> CamerasConfigsComponent();

fruit::Component<fruit::Required<CamerasConfigs, ConfigFlag>,
CamerasConfigsFlag>
CamerasConfigsFlagComponent();

fruit::Component<fruit::Required<CamerasConfigs>, CamerasConfigsFragment>
CamerasConfigsFragmentComponent();

} // namespace cuttlefish
7 changes: 7 additions & 0 deletions base/cvd/cuttlefish/host/commands/assemble_cvd/flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
#include "cuttlefish/host/commands/assemble_cvd/flags/use_cvdalloc.h"
#include "cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.h"
#include "cuttlefish/host/commands/assemble_cvd/flags/vm_manager.h"
#include "cuttlefish/host/commands/assemble_cvd/camera.h"
#include "cuttlefish/host/commands/assemble_cvd/graphics_flags.h"
#include "cuttlefish/host/commands/assemble_cvd/guest_config.h"
#include "cuttlefish/host/commands/assemble_cvd/network_flags.h"
Expand Down Expand Up @@ -1307,6 +1308,12 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(

instance.set_enable_tap_devices(enable_tap_devices_vec[instance_index]);

auto cameras_configs_bindings = injector.getMultibindings<CamerasConfigs>();
CF_EXPECT_EQ(cameras_configs_bindings.size(), 1,
"Expected a single binding?");
auto camera_configs = cameras_configs_bindings[0]->GetConfigs();
instance.set_camera_configs(camera_configs);

instance_index++;
} // end of num_instances loop

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,6 @@

// Virtual Cpufreq default configuration path
#define CF_DEFAULTS_VCPU_CONFIG_PATH ""

// Camera
#define CF_DEFAULTS_CAMERA_TYPE 1
15 changes: 15 additions & 0 deletions base/cvd/cuttlefish/host/libs/config/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,18 @@ cf_cc_library(
"@abseil-cpp//absl/strings",
],
)

cf_cc_library(
name = "camera",
srcs = ["camera.cpp"],
hdrs = ["camera.h"],
deps = [
"//cuttlefish/common/libs/utils:contains",
"//cuttlefish/common/libs/utils:flag_parser",
"//cuttlefish/host/commands/assemble_cvd:flags_defaults",
"//cuttlefish/host/libs/config:cuttlefish_config",
"//cuttlefish/result",
"//libbase",
"@abseil-cpp//absl/strings",
],
)
Loading
Loading