Skip to content

Commit b6cbe7b

Browse files
committed
Add a CombinedAndroidBuild class.
This represents Android build information coming from multiple sources. Individual sources can implement parts of the API, and an instance of this class combines non-error results to provide as much information as possible to the caller. Bug: b/469557768
1 parent 0b617de commit b6cbe7b

File tree

3 files changed

+180
-0
lines changed

3 files changed

+180
-0
lines changed

base/cvd/cuttlefish/host/commands/assemble_cvd/android_build/BUILD.bazel

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,15 @@ cf_cc_library(
1616
"@fmt",
1717
],
1818
)
19+
20+
cf_cc_library(
21+
name = "combined_android_build",
22+
srcs = ["combined_android_build.cc"],
23+
hdrs = ["combined_android_build.h"],
24+
deps = [
25+
"//cuttlefish/common/libs/utils:result",
26+
"//cuttlefish/host/commands/assemble_cvd/android_build",
27+
"@abseil-cpp//absl/strings:str_format",
28+
"@fmt",
29+
],
30+
)
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//
2+
// Copyright (C) 2025 The Android Open Source Project
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
#include "cuttlefish/host/commands/assemble_cvd/android_build/combined_android_build.h"
17+
18+
#include <functional>
19+
#include <memory>
20+
#include <optional>
21+
#include <ostream>
22+
#include <set>
23+
#include <string>
24+
#include <string_view>
25+
#include <utility>
26+
#include <vector>
27+
28+
#include "fmt/ostream.h"
29+
30+
#include "cuttlefish/common/libs/utils/result.h"
31+
#include "cuttlefish/host/commands/assemble_cvd/android_build/android_build.h"
32+
33+
namespace cuttlefish {
34+
namespace {
35+
36+
class CombinedAndroidBuildImpl : public AndroidBuild {
37+
public:
38+
CombinedAndroidBuildImpl(std::string name,
39+
std::vector<std::unique_ptr<AndroidBuild>> builds)
40+
: name_(std::move(name)), builds_(std::move(builds)) {}
41+
42+
Result<std::set<std::string, std::less<void>>> Images() override {
43+
return CF_EXPECT(MergeSuccessful(&AndroidBuild::Images));
44+
}
45+
46+
Result<std::string> ImageFile(
47+
std::string_view name,
48+
std::optional<std::string_view> extract_dir) override {
49+
Result<std::string> res;
50+
51+
// If the file is already extracted somewhere, prefer that version.
52+
for (const std::unique_ptr<AndroidBuild>& build : builds_) {
53+
if (res = build->ImageFile(name, std::nullopt); res.ok()) {
54+
return res;
55+
}
56+
}
57+
// Now try to extract if it any of the builds have it.
58+
CF_EXPECTF(extract_dir.has_value(), "Need extract_dir for '{}'", name);
59+
for (const std::unique_ptr<AndroidBuild>& build : builds_) {
60+
if (res = build->ImageFile(name, extract_dir); res.ok()) {
61+
return res;
62+
}
63+
}
64+
return CF_ERRF("Could not extract '{}' from {}", name,
65+
static_cast<AndroidBuild&>(*this));
66+
}
67+
68+
Result<std::set<std::string, std::less<void>>> AbPartitions() override {
69+
return CF_EXPECT(MergeSuccessful(&AndroidBuild::AbPartitions));
70+
}
71+
72+
Result<std::set<std::string, std::less<void>>> SystemPartitions() override {
73+
return CF_EXPECT(MergeSuccessful(&AndroidBuild::SystemPartitions));
74+
}
75+
76+
Result<std::set<std::string, std::less<void>>> VendorPartitions() override {
77+
return CF_EXPECT(MergeSuccessful(&AndroidBuild::VendorPartitions));
78+
}
79+
80+
Result<std::set<std::string, std::less<void>>> LogicalPartitions() override {
81+
return CF_EXPECT(MergeSuccessful(&AndroidBuild::LogicalPartitions));
82+
}
83+
84+
Result<std::set<std::string, std::less<void>>> PhysicalPartitions() override {
85+
return CF_EXPECT(MergeSuccessful(&AndroidBuild::PhysicalPartitions));
86+
}
87+
88+
private:
89+
std::ostream& Format(std::ostream& out) const override {
90+
fmt::print(out, "CombinedAndroidBuild({}) {{ ", name_);
91+
for (const std::unique_ptr<AndroidBuild>& build : builds_) {
92+
fmt::print(out, "{}, ", *build);
93+
}
94+
return out << "}";
95+
}
96+
97+
Result<std::set<std::string, std::less<void>>> MergeSuccessful(
98+
Result<std::set<std::string, std::less<void>>> (AndroidBuild::*fn)()) {
99+
Result<std::set<std::string, std::less<void>>> res = CF_ERR("No members");
100+
bool one_succeeded = false;
101+
102+
std::set<std::string, std::less<void>> merged;
103+
for (const std::unique_ptr<AndroidBuild>& build : builds_) {
104+
if (res = ((*build).*fn)(); res.ok()) {
105+
merged.merge(std::move(*res));
106+
}
107+
}
108+
return one_succeeded ? merged : res;
109+
}
110+
111+
std::string name_;
112+
std::vector<std::unique_ptr<AndroidBuild>> builds_;
113+
};
114+
115+
} // namespace
116+
117+
Result<std::unique_ptr<AndroidBuild>> CombinedAndroidBuild(
118+
std::string name, std::vector<std::unique_ptr<AndroidBuild>> builds) {
119+
for (auto& build : builds) {
120+
CF_EXPECT(build.get());
121+
}
122+
return std::make_unique<CombinedAndroidBuildImpl>(std::move(name),
123+
std::move(builds));
124+
}
125+
126+
} // namespace cuttlefish
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// Copyright (C) 2025 The Android Open Source Project
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
#pragma once
17+
18+
#include <memory>
19+
#include <string>
20+
#include <vector>
21+
22+
#include "cuttlefish/common/libs/utils/result.h"
23+
#include "cuttlefish/host/commands/assemble_cvd/android_build/android_build.h"
24+
25+
namespace cuttlefish {
26+
27+
/**
28+
* Combines information from multiple `AndroidBuild` instances.
29+
*
30+
* Individual sources can implement parts of the API, and an instance of
31+
* this class combines non-error results to provide as much information as
32+
* possible to the caller.
33+
*
34+
* Instances provided to this class are expected to be part of the same build
35+
* and consistent with each other. Specifically, if files are from different
36+
* build targets, have different build ids, or are built from different sources,
37+
* they should not be combined with each other.
38+
*/
39+
Result<std::unique_ptr<AndroidBuild>> CombinedAndroidBuild(
40+
std::string name, std::vector<std::unique_ptr<AndroidBuild>>);
41+
42+
} // namespace cuttlefish

0 commit comments

Comments
 (0)