xref: /aosp_15_r20/hardware/interfaces/boot/aidl/client/BootControlClient.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker 
17*4d7e907cSAndroid Build Coastguard Worker #include <BootControlClient.h>
18*4d7e907cSAndroid Build Coastguard Worker 
19*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/boot/IBootControl.h>
20*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_ibinder.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_manager.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <android/hardware/boot/1.0/IBootControl.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <android/hardware/boot/1.1/IBootControl.h>
25*4d7e907cSAndroid Build Coastguard Worker #include <android/hardware/boot/1.2/IBootControl.h>
26*4d7e907cSAndroid Build Coastguard Worker #include "utils/StrongPointer.h"
27*4d7e907cSAndroid Build Coastguard Worker 
28*4d7e907cSAndroid Build Coastguard Worker #define CONCAT(x, y) x##y
29*4d7e907cSAndroid Build Coastguard Worker 
30*4d7e907cSAndroid Build Coastguard Worker #define LOG_NDK_STATUS(x)                                                                   \
31*4d7e907cSAndroid Build Coastguard Worker     do {                                                                                    \
32*4d7e907cSAndroid Build Coastguard Worker         const auto CONCAT(status, __COUNTER__) = x;                                         \
33*4d7e907cSAndroid Build Coastguard Worker         if (!CONCAT(status, __COUNTER__).isOk()) {                                          \
34*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << #x << " failed " << CONCAT(status, __COUNTER__).getDescription(); \
35*4d7e907cSAndroid Build Coastguard Worker         }                                                                                   \
36*4d7e907cSAndroid Build Coastguard Worker     } while (0)
37*4d7e907cSAndroid Build Coastguard Worker 
38*4d7e907cSAndroid Build Coastguard Worker using aidl::android::hardware::boot::MergeStatus;
39*4d7e907cSAndroid Build Coastguard Worker 
40*4d7e907cSAndroid Build Coastguard Worker #define TEST_OP(_x, _y, op)                                                            \
41*4d7e907cSAndroid Build Coastguard Worker     do {                                                                               \
42*4d7e907cSAndroid Build Coastguard Worker         const auto& x = _x;                                                            \
43*4d7e907cSAndroid Build Coastguard Worker         const auto& y = _y;                                                            \
44*4d7e907cSAndroid Build Coastguard Worker         if (!(x op y)) {                                                               \
45*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << #_x " " #op " " #_y << " failed: " << x << " " #op " " << y; \
46*4d7e907cSAndroid Build Coastguard Worker             return {};                                                                 \
47*4d7e907cSAndroid Build Coastguard Worker         }                                                                              \
48*4d7e907cSAndroid Build Coastguard Worker     } while (0)
49*4d7e907cSAndroid Build Coastguard Worker #define TEST_NE(_x, _y) TEST_OP(_x, _y, !=)
50*4d7e907cSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,MergeStatus status)51*4d7e907cSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, MergeStatus status) {
52*4d7e907cSAndroid Build Coastguard Worker     switch (status) {
53*4d7e907cSAndroid Build Coastguard Worker         case MergeStatus::NONE:
54*4d7e907cSAndroid Build Coastguard Worker             os << "MergeStatus::NONE";
55*4d7e907cSAndroid Build Coastguard Worker             break;
56*4d7e907cSAndroid Build Coastguard Worker         case MergeStatus::UNKNOWN:
57*4d7e907cSAndroid Build Coastguard Worker             os << "MergeStatus::UNKNOWN";
58*4d7e907cSAndroid Build Coastguard Worker             break;
59*4d7e907cSAndroid Build Coastguard Worker         case MergeStatus::SNAPSHOTTED:
60*4d7e907cSAndroid Build Coastguard Worker             os << "MergeStatus::SNAPSHOTTED";
61*4d7e907cSAndroid Build Coastguard Worker             break;
62*4d7e907cSAndroid Build Coastguard Worker         case MergeStatus::MERGING:
63*4d7e907cSAndroid Build Coastguard Worker             os << "MergeStatus::MERGING";
64*4d7e907cSAndroid Build Coastguard Worker             break;
65*4d7e907cSAndroid Build Coastguard Worker         case MergeStatus::CANCELLED:
66*4d7e907cSAndroid Build Coastguard Worker             os << "MergeStatus::CANCELLED";
67*4d7e907cSAndroid Build Coastguard Worker             break;
68*4d7e907cSAndroid Build Coastguard Worker         default:
69*4d7e907cSAndroid Build Coastguard Worker             os << static_cast<int>(status);
70*4d7e907cSAndroid Build Coastguard Worker             break;
71*4d7e907cSAndroid Build Coastguard Worker     }
72*4d7e907cSAndroid Build Coastguard Worker     return os;
73*4d7e907cSAndroid Build Coastguard Worker }
74*4d7e907cSAndroid Build Coastguard Worker 
75*4d7e907cSAndroid Build Coastguard Worker namespace android::hal {
76*4d7e907cSAndroid Build Coastguard Worker class BootControlClientAidl final : public BootControlClient {
77*4d7e907cSAndroid Build Coastguard Worker     using IBootControl = ::aidl::android::hardware::boot::IBootControl;
78*4d7e907cSAndroid Build Coastguard Worker 
79*4d7e907cSAndroid Build Coastguard Worker   public:
BootControlClientAidl(std::shared_ptr<IBootControl> module)80*4d7e907cSAndroid Build Coastguard Worker     explicit BootControlClientAidl(std::shared_ptr<IBootControl> module)
81*4d7e907cSAndroid Build Coastguard Worker         : module_(module),
82*4d7e907cSAndroid Build Coastguard Worker           boot_control_death_recipient(AIBinder_DeathRecipient_new(onBootControlServiceDied)) {
83*4d7e907cSAndroid Build Coastguard Worker         binder_status_t status =
84*4d7e907cSAndroid Build Coastguard Worker                 AIBinder_linkToDeath(module->asBinder().get(), boot_control_death_recipient, this);
85*4d7e907cSAndroid Build Coastguard Worker         if (status != STATUS_OK) {
86*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "Could not link to binder death";
87*4d7e907cSAndroid Build Coastguard Worker             return;
88*4d7e907cSAndroid Build Coastguard Worker         }
89*4d7e907cSAndroid Build Coastguard Worker     }
90*4d7e907cSAndroid Build Coastguard Worker 
GetVersion() const91*4d7e907cSAndroid Build Coastguard Worker     BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
92*4d7e907cSAndroid Build Coastguard Worker 
onBootControlServiceDied()93*4d7e907cSAndroid Build Coastguard Worker     void onBootControlServiceDied() {
94*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "boot control service AIDL died. Attempting to reconnect...";
95*4d7e907cSAndroid Build Coastguard Worker         const auto instance_name =
96*4d7e907cSAndroid Build Coastguard Worker                 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
97*4d7e907cSAndroid Build Coastguard Worker         if (AServiceManager_isDeclared(instance_name.c_str())) {
98*4d7e907cSAndroid Build Coastguard Worker             module_ = ::aidl::android::hardware::boot::IBootControl::fromBinder(
99*4d7e907cSAndroid Build Coastguard Worker                     ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
100*4d7e907cSAndroid Build Coastguard Worker             if (module_ == nullptr) {
101*4d7e907cSAndroid Build Coastguard Worker                 LOG(ERROR) << "AIDL " << instance_name
102*4d7e907cSAndroid Build Coastguard Worker                            << " is declared but waitForService returned nullptr when trying to "
103*4d7e907cSAndroid Build Coastguard Worker                               "reconnect boot control service";
104*4d7e907cSAndroid Build Coastguard Worker                 return;
105*4d7e907cSAndroid Build Coastguard Worker             }
106*4d7e907cSAndroid Build Coastguard Worker             LOG(INFO) << "Reconnected to AIDL version of IBootControl";
107*4d7e907cSAndroid Build Coastguard Worker             binder_status_t status = AIBinder_linkToDeath(module_->asBinder().get(),
108*4d7e907cSAndroid Build Coastguard Worker                                                           boot_control_death_recipient, this);
109*4d7e907cSAndroid Build Coastguard Worker             if (status != STATUS_OK) {
110*4d7e907cSAndroid Build Coastguard Worker                 LOG(ERROR) << "Could not link to binder death";
111*4d7e907cSAndroid Build Coastguard Worker                 return;
112*4d7e907cSAndroid Build Coastguard Worker             }
113*4d7e907cSAndroid Build Coastguard Worker 
114*4d7e907cSAndroid Build Coastguard Worker         } else {
115*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "Failed to get service manager for: " << instance_name;
116*4d7e907cSAndroid Build Coastguard Worker         }
117*4d7e907cSAndroid Build Coastguard Worker     }
118*4d7e907cSAndroid Build Coastguard Worker 
GetNumSlots() const119*4d7e907cSAndroid Build Coastguard Worker     int32_t GetNumSlots() const override {
120*4d7e907cSAndroid Build Coastguard Worker         int32_t ret = -1;
121*4d7e907cSAndroid Build Coastguard Worker         if (!module_) {
122*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "bootctl module not set";
123*4d7e907cSAndroid Build Coastguard Worker             return ret;
124*4d7e907cSAndroid Build Coastguard Worker         }
125*4d7e907cSAndroid Build Coastguard Worker         LOG_NDK_STATUS(module_->getNumberSlots(&ret));
126*4d7e907cSAndroid Build Coastguard Worker         return ret;
127*4d7e907cSAndroid Build Coastguard Worker     }
128*4d7e907cSAndroid Build Coastguard Worker 
GetCurrentSlot() const129*4d7e907cSAndroid Build Coastguard Worker     int32_t GetCurrentSlot() const override {
130*4d7e907cSAndroid Build Coastguard Worker         int32_t ret = -1;
131*4d7e907cSAndroid Build Coastguard Worker         if (!module_) {
132*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "bootctl module not set";
133*4d7e907cSAndroid Build Coastguard Worker             return ret;
134*4d7e907cSAndroid Build Coastguard Worker         }
135*4d7e907cSAndroid Build Coastguard Worker         LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
136*4d7e907cSAndroid Build Coastguard Worker         return ret;
137*4d7e907cSAndroid Build Coastguard Worker     }
138*4d7e907cSAndroid Build Coastguard Worker 
getSnapshotMergeStatus() const139*4d7e907cSAndroid Build Coastguard Worker     MergeStatus getSnapshotMergeStatus() const override {
140*4d7e907cSAndroid Build Coastguard Worker         MergeStatus status = MergeStatus::UNKNOWN;
141*4d7e907cSAndroid Build Coastguard Worker         if (!module_) {
142*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "bootctl module not set";
143*4d7e907cSAndroid Build Coastguard Worker             return status;
144*4d7e907cSAndroid Build Coastguard Worker         }
145*4d7e907cSAndroid Build Coastguard Worker         LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
146*4d7e907cSAndroid Build Coastguard Worker         return status;
147*4d7e907cSAndroid Build Coastguard Worker     }
148*4d7e907cSAndroid Build Coastguard Worker 
GetSuffix(int32_t slot) const149*4d7e907cSAndroid Build Coastguard Worker     std::string GetSuffix(int32_t slot) const override {
150*4d7e907cSAndroid Build Coastguard Worker         TEST_NE(module_, nullptr);
151*4d7e907cSAndroid Build Coastguard Worker         std::string ret;
152*4d7e907cSAndroid Build Coastguard Worker         const auto status = module_->getSuffix(slot, &ret);
153*4d7e907cSAndroid Build Coastguard Worker         if (!status.isOk()) {
154*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
155*4d7e907cSAndroid Build Coastguard Worker                        << status.getDescription();
156*4d7e907cSAndroid Build Coastguard Worker             return {};
157*4d7e907cSAndroid Build Coastguard Worker         }
158*4d7e907cSAndroid Build Coastguard Worker         return ret;
159*4d7e907cSAndroid Build Coastguard Worker     }
160*4d7e907cSAndroid Build Coastguard Worker 
IsSlotBootable(int32_t slot) const161*4d7e907cSAndroid Build Coastguard Worker     std::optional<bool> IsSlotBootable(int32_t slot) const override {
162*4d7e907cSAndroid Build Coastguard Worker         TEST_NE(module_, nullptr);
163*4d7e907cSAndroid Build Coastguard Worker         bool ret = false;
164*4d7e907cSAndroid Build Coastguard Worker         const auto status = module_->isSlotBootable(slot, &ret);
165*4d7e907cSAndroid Build Coastguard Worker         if (!status.isOk()) {
166*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
167*4d7e907cSAndroid Build Coastguard Worker                        << status.getDescription();
168*4d7e907cSAndroid Build Coastguard Worker             return {};
169*4d7e907cSAndroid Build Coastguard Worker         }
170*4d7e907cSAndroid Build Coastguard Worker         return ret;
171*4d7e907cSAndroid Build Coastguard Worker     }
172*4d7e907cSAndroid Build Coastguard Worker 
MarkSlotUnbootable(int32_t slot)173*4d7e907cSAndroid Build Coastguard Worker     CommandResult MarkSlotUnbootable(int32_t slot) override {
174*4d7e907cSAndroid Build Coastguard Worker         TEST_NE(module_, nullptr);
175*4d7e907cSAndroid Build Coastguard Worker         const auto status = module_->setSlotAsUnbootable(slot);
176*4d7e907cSAndroid Build Coastguard Worker         if (!status.isOk()) {
177*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
178*4d7e907cSAndroid Build Coastguard Worker                        << status.getDescription();
179*4d7e907cSAndroid Build Coastguard Worker         }
180*4d7e907cSAndroid Build Coastguard Worker         return {.success = status.isOk(), .errMsg = status.getDescription()};
181*4d7e907cSAndroid Build Coastguard Worker     }
182*4d7e907cSAndroid Build Coastguard Worker 
SetActiveBootSlot(int slot)183*4d7e907cSAndroid Build Coastguard Worker     CommandResult SetActiveBootSlot(int slot) override {
184*4d7e907cSAndroid Build Coastguard Worker         TEST_NE(module_, nullptr);
185*4d7e907cSAndroid Build Coastguard Worker         const auto status = module_->setActiveBootSlot(slot);
186*4d7e907cSAndroid Build Coastguard Worker         if (!status.isOk()) {
187*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
188*4d7e907cSAndroid Build Coastguard Worker                        << status.getDescription();
189*4d7e907cSAndroid Build Coastguard Worker         }
190*4d7e907cSAndroid Build Coastguard Worker         return {.success = status.isOk(), .errMsg = status.getDescription()};
191*4d7e907cSAndroid Build Coastguard Worker     }
192*4d7e907cSAndroid Build Coastguard Worker 
GetActiveBootSlot() const193*4d7e907cSAndroid Build Coastguard Worker     int GetActiveBootSlot() const {
194*4d7e907cSAndroid Build Coastguard Worker         int ret = -1;
195*4d7e907cSAndroid Build Coastguard Worker         if (!module_) {
196*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "bootctl module not set";
197*4d7e907cSAndroid Build Coastguard Worker             return ret;
198*4d7e907cSAndroid Build Coastguard Worker         }
199*4d7e907cSAndroid Build Coastguard Worker         LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
200*4d7e907cSAndroid Build Coastguard Worker         return ret;
201*4d7e907cSAndroid Build Coastguard Worker     }
202*4d7e907cSAndroid Build Coastguard Worker 
203*4d7e907cSAndroid Build Coastguard Worker     // Check if |slot| is marked boot successfully.
IsSlotMarkedSuccessful(int slot) const204*4d7e907cSAndroid Build Coastguard Worker     std::optional<bool> IsSlotMarkedSuccessful(int slot) const override {
205*4d7e907cSAndroid Build Coastguard Worker         TEST_NE(module_, nullptr);
206*4d7e907cSAndroid Build Coastguard Worker         bool ret = false;
207*4d7e907cSAndroid Build Coastguard Worker         const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
208*4d7e907cSAndroid Build Coastguard Worker         if (!status.isOk()) {
209*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
210*4d7e907cSAndroid Build Coastguard Worker                        << status.getDescription();
211*4d7e907cSAndroid Build Coastguard Worker             return {};
212*4d7e907cSAndroid Build Coastguard Worker         }
213*4d7e907cSAndroid Build Coastguard Worker         return ret;
214*4d7e907cSAndroid Build Coastguard Worker     }
215*4d7e907cSAndroid Build Coastguard Worker 
MarkBootSuccessful()216*4d7e907cSAndroid Build Coastguard Worker     CommandResult MarkBootSuccessful() override {
217*4d7e907cSAndroid Build Coastguard Worker         TEST_NE(module_, nullptr);
218*4d7e907cSAndroid Build Coastguard Worker         const auto status = module_->markBootSuccessful();
219*4d7e907cSAndroid Build Coastguard Worker         if (!status.isOk()) {
220*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
221*4d7e907cSAndroid Build Coastguard Worker         }
222*4d7e907cSAndroid Build Coastguard Worker         return {.success = status.isOk(), .errMsg = status.getDescription()};
223*4d7e907cSAndroid Build Coastguard Worker     }
224*4d7e907cSAndroid Build Coastguard Worker 
SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status)225*4d7e907cSAndroid Build Coastguard Worker     CommandResult SetSnapshotMergeStatus(
226*4d7e907cSAndroid Build Coastguard Worker             aidl::android::hardware::boot::MergeStatus merge_status) override {
227*4d7e907cSAndroid Build Coastguard Worker         TEST_NE(module_, nullptr);
228*4d7e907cSAndroid Build Coastguard Worker         const auto status = module_->setSnapshotMergeStatus(merge_status);
229*4d7e907cSAndroid Build Coastguard Worker         if (!status.isOk()) {
230*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
231*4d7e907cSAndroid Build Coastguard Worker                        << status.getDescription();
232*4d7e907cSAndroid Build Coastguard Worker         }
233*4d7e907cSAndroid Build Coastguard Worker         return {.success = status.isOk(), .errMsg = status.getDescription()};
234*4d7e907cSAndroid Build Coastguard Worker     }
235*4d7e907cSAndroid Build Coastguard Worker 
236*4d7e907cSAndroid Build Coastguard Worker   private:
237*4d7e907cSAndroid Build Coastguard Worker     std::shared_ptr<IBootControl> module_;
238*4d7e907cSAndroid Build Coastguard Worker     AIBinder_DeathRecipient* boot_control_death_recipient;
onBootControlServiceDied(void * client)239*4d7e907cSAndroid Build Coastguard Worker     static void onBootControlServiceDied(void* client) {
240*4d7e907cSAndroid Build Coastguard Worker         BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
241*4d7e907cSAndroid Build Coastguard Worker         self->onBootControlServiceDied();
242*4d7e907cSAndroid Build Coastguard Worker     }
243*4d7e907cSAndroid Build Coastguard Worker };
244*4d7e907cSAndroid Build Coastguard Worker 
245*4d7e907cSAndroid Build Coastguard Worker using namespace android::hardware::boot;
246*4d7e907cSAndroid Build Coastguard Worker 
247*4d7e907cSAndroid Build Coastguard Worker class BootControlClientHIDL final : public BootControlClient {
248*4d7e907cSAndroid Build Coastguard Worker   public:
BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,android::sp<V1_1::IBootControl> module_v1_1,android::sp<V1_2::IBootControl> module_v1_2)249*4d7e907cSAndroid Build Coastguard Worker     BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,
250*4d7e907cSAndroid Build Coastguard Worker                           android::sp<V1_1::IBootControl> module_v1_1,
251*4d7e907cSAndroid Build Coastguard Worker                           android::sp<V1_2::IBootControl> module_v1_2)
252*4d7e907cSAndroid Build Coastguard Worker         : module_v1_(module_v1), module_v1_1_(module_v1_1), module_v1_2_(module_v1_2) {
253*4d7e907cSAndroid Build Coastguard Worker         CHECK(module_v1_ != nullptr);
254*4d7e907cSAndroid Build Coastguard Worker     }
GetVersion() const255*4d7e907cSAndroid Build Coastguard Worker     BootControlVersion GetVersion() const override {
256*4d7e907cSAndroid Build Coastguard Worker         if (module_v1_2_ != nullptr) {
257*4d7e907cSAndroid Build Coastguard Worker             return BootControlVersion::BOOTCTL_V1_2;
258*4d7e907cSAndroid Build Coastguard Worker         } else if (module_v1_1_ != nullptr) {
259*4d7e907cSAndroid Build Coastguard Worker             return BootControlVersion::BOOTCTL_V1_1;
260*4d7e907cSAndroid Build Coastguard Worker         } else {
261*4d7e907cSAndroid Build Coastguard Worker             return BootControlVersion::BOOTCTL_V1_0;
262*4d7e907cSAndroid Build Coastguard Worker         }
263*4d7e907cSAndroid Build Coastguard Worker     }
GetNumSlots() const264*4d7e907cSAndroid Build Coastguard Worker     int32_t GetNumSlots() const override {
265*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_->getNumberSlots();
266*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
267*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
268*4d7e907cSAndroid Build Coastguard Worker         }
269*4d7e907cSAndroid Build Coastguard Worker         return ret.withDefault(-1);
270*4d7e907cSAndroid Build Coastguard Worker     }
271*4d7e907cSAndroid Build Coastguard Worker 
GetCurrentSlot() const272*4d7e907cSAndroid Build Coastguard Worker     int32_t GetCurrentSlot() const override {
273*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_->getCurrentSlot();
274*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
275*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
276*4d7e907cSAndroid Build Coastguard Worker         }
277*4d7e907cSAndroid Build Coastguard Worker         return ret.withDefault(-1);
278*4d7e907cSAndroid Build Coastguard Worker     }
279*4d7e907cSAndroid Build Coastguard Worker 
GetSuffix(int32_t slot) const280*4d7e907cSAndroid Build Coastguard Worker     std::string GetSuffix(int32_t slot) const override {
281*4d7e907cSAndroid Build Coastguard Worker         std::string suffix;
282*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_->getSuffix(
283*4d7e907cSAndroid Build Coastguard Worker                 slot,
284*4d7e907cSAndroid Build Coastguard Worker                 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
285*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
286*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
287*4d7e907cSAndroid Build Coastguard Worker         }
288*4d7e907cSAndroid Build Coastguard Worker         return suffix;
289*4d7e907cSAndroid Build Coastguard Worker     }
290*4d7e907cSAndroid Build Coastguard Worker 
IsSlotBootable(int32_t slot) const291*4d7e907cSAndroid Build Coastguard Worker     std::optional<bool> IsSlotBootable(int32_t slot) const override {
292*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_->isSlotBootable(slot);
293*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
294*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
295*4d7e907cSAndroid Build Coastguard Worker             return {};
296*4d7e907cSAndroid Build Coastguard Worker         }
297*4d7e907cSAndroid Build Coastguard Worker         const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
298*4d7e907cSAndroid Build Coastguard Worker         if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
299*4d7e907cSAndroid Build Coastguard Worker             return {};
300*4d7e907cSAndroid Build Coastguard Worker         }
301*4d7e907cSAndroid Build Coastguard Worker         return bool_result == V1_0::BoolResult::TRUE;
302*4d7e907cSAndroid Build Coastguard Worker     }
303*4d7e907cSAndroid Build Coastguard Worker 
MarkSlotUnbootable(int32_t slot)304*4d7e907cSAndroid Build Coastguard Worker     CommandResult MarkSlotUnbootable(int32_t slot) override {
305*4d7e907cSAndroid Build Coastguard Worker         CommandResult result;
306*4d7e907cSAndroid Build Coastguard Worker         const auto ret =
307*4d7e907cSAndroid Build Coastguard Worker                 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
308*4d7e907cSAndroid Build Coastguard Worker                     result.success = error.success;
309*4d7e907cSAndroid Build Coastguard Worker                     result.errMsg = error.errMsg;
310*4d7e907cSAndroid Build Coastguard Worker                 });
311*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
312*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
313*4d7e907cSAndroid Build Coastguard Worker         }
314*4d7e907cSAndroid Build Coastguard Worker         return result;
315*4d7e907cSAndroid Build Coastguard Worker     }
316*4d7e907cSAndroid Build Coastguard Worker 
SetActiveBootSlot(int32_t slot)317*4d7e907cSAndroid Build Coastguard Worker     CommandResult SetActiveBootSlot(int32_t slot) override {
318*4d7e907cSAndroid Build Coastguard Worker         CommandResult result;
319*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
320*4d7e907cSAndroid Build Coastguard Worker             result.success = error.success;
321*4d7e907cSAndroid Build Coastguard Worker             result.errMsg = error.errMsg;
322*4d7e907cSAndroid Build Coastguard Worker         });
323*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
324*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
325*4d7e907cSAndroid Build Coastguard Worker         }
326*4d7e907cSAndroid Build Coastguard Worker         return result;
327*4d7e907cSAndroid Build Coastguard Worker     }
328*4d7e907cSAndroid Build Coastguard Worker 
MarkBootSuccessful()329*4d7e907cSAndroid Build Coastguard Worker     CommandResult MarkBootSuccessful() override {
330*4d7e907cSAndroid Build Coastguard Worker         CommandResult result;
331*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
332*4d7e907cSAndroid Build Coastguard Worker             result.success = error.success;
333*4d7e907cSAndroid Build Coastguard Worker             result.errMsg = error.errMsg;
334*4d7e907cSAndroid Build Coastguard Worker         });
335*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
336*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
337*4d7e907cSAndroid Build Coastguard Worker         }
338*4d7e907cSAndroid Build Coastguard Worker         return result;
339*4d7e907cSAndroid Build Coastguard Worker     }
340*4d7e907cSAndroid Build Coastguard Worker 
IsSlotMarkedSuccessful(int32_t slot) const341*4d7e907cSAndroid Build Coastguard Worker     std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const override {
342*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
343*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
344*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
345*4d7e907cSAndroid Build Coastguard Worker             return {};
346*4d7e907cSAndroid Build Coastguard Worker         }
347*4d7e907cSAndroid Build Coastguard Worker         const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
348*4d7e907cSAndroid Build Coastguard Worker         if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
349*4d7e907cSAndroid Build Coastguard Worker             return {};
350*4d7e907cSAndroid Build Coastguard Worker         }
351*4d7e907cSAndroid Build Coastguard Worker         return bool_result == V1_0::BoolResult::TRUE;
352*4d7e907cSAndroid Build Coastguard Worker     }
353*4d7e907cSAndroid Build Coastguard Worker 
getSnapshotMergeStatus() const354*4d7e907cSAndroid Build Coastguard Worker     MergeStatus getSnapshotMergeStatus() const override {
355*4d7e907cSAndroid Build Coastguard Worker         if (module_v1_1_ == nullptr) {
356*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
357*4d7e907cSAndroid Build Coastguard Worker             return MergeStatus::UNKNOWN;
358*4d7e907cSAndroid Build Coastguard Worker         }
359*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_1_->getSnapshotMergeStatus();
360*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
361*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
362*4d7e907cSAndroid Build Coastguard Worker         }
363*4d7e907cSAndroid Build Coastguard Worker         return static_cast<MergeStatus>(
364*4d7e907cSAndroid Build Coastguard Worker                 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
365*4d7e907cSAndroid Build Coastguard Worker     }
366*4d7e907cSAndroid Build Coastguard Worker 
SetSnapshotMergeStatus(MergeStatus merge_status)367*4d7e907cSAndroid Build Coastguard Worker     CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) override {
368*4d7e907cSAndroid Build Coastguard Worker         if (module_v1_1_ == nullptr) {
369*4d7e907cSAndroid Build Coastguard Worker             return {.success = false,
370*4d7e907cSAndroid Build Coastguard Worker                     .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
371*4d7e907cSAndroid Build Coastguard Worker         }
372*4d7e907cSAndroid Build Coastguard Worker         const auto ret =
373*4d7e907cSAndroid Build Coastguard Worker                 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
374*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
375*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
376*4d7e907cSAndroid Build Coastguard Worker                        << ret.description();
377*4d7e907cSAndroid Build Coastguard Worker         }
378*4d7e907cSAndroid Build Coastguard Worker         return {.success = ret.isOk(), .errMsg = ret.description()};
379*4d7e907cSAndroid Build Coastguard Worker     }
380*4d7e907cSAndroid Build Coastguard Worker 
GetActiveBootSlot() const381*4d7e907cSAndroid Build Coastguard Worker     int32_t GetActiveBootSlot() const override {
382*4d7e907cSAndroid Build Coastguard Worker         if (module_v1_2_ == nullptr) {
383*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
384*4d7e907cSAndroid Build Coastguard Worker             return -1;
385*4d7e907cSAndroid Build Coastguard Worker         }
386*4d7e907cSAndroid Build Coastguard Worker         const auto ret = module_v1_2_->getActiveBootSlot();
387*4d7e907cSAndroid Build Coastguard Worker         if (!ret.isOk()) {
388*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
389*4d7e907cSAndroid Build Coastguard Worker         }
390*4d7e907cSAndroid Build Coastguard Worker         return ret.withDefault(-1);
391*4d7e907cSAndroid Build Coastguard Worker     }
392*4d7e907cSAndroid Build Coastguard Worker 
393*4d7e907cSAndroid Build Coastguard Worker   private:
394*4d7e907cSAndroid Build Coastguard Worker     android::sp<V1_0::IBootControl> module_v1_;
395*4d7e907cSAndroid Build Coastguard Worker     android::sp<V1_1::IBootControl> module_v1_1_;
396*4d7e907cSAndroid Build Coastguard Worker     android::sp<V1_2::IBootControl> module_v1_2_;
397*4d7e907cSAndroid Build Coastguard Worker };
398*4d7e907cSAndroid Build Coastguard Worker 
WaitForService()399*4d7e907cSAndroid Build Coastguard Worker std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
400*4d7e907cSAndroid Build Coastguard Worker     const auto instance_name =
401*4d7e907cSAndroid Build Coastguard Worker             std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
402*4d7e907cSAndroid Build Coastguard Worker     if (AServiceManager_isDeclared(instance_name.c_str())) {
403*4d7e907cSAndroid Build Coastguard Worker         auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
404*4d7e907cSAndroid Build Coastguard Worker                 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
405*4d7e907cSAndroid Build Coastguard Worker         if (module == nullptr) {
406*4d7e907cSAndroid Build Coastguard Worker             LOG(ERROR) << "AIDL " << instance_name
407*4d7e907cSAndroid Build Coastguard Worker                        << " is declared but waitForService returned nullptr.";
408*4d7e907cSAndroid Build Coastguard Worker             return nullptr;
409*4d7e907cSAndroid Build Coastguard Worker         }
410*4d7e907cSAndroid Build Coastguard Worker         LOG(INFO) << "Using AIDL version of IBootControl";
411*4d7e907cSAndroid Build Coastguard Worker         return std::make_unique<BootControlClientAidl>(module);
412*4d7e907cSAndroid Build Coastguard Worker     }
413*4d7e907cSAndroid Build Coastguard Worker     LOG(INFO) << "AIDL IBootControl not available, falling back to HIDL.";
414*4d7e907cSAndroid Build Coastguard Worker 
415*4d7e907cSAndroid Build Coastguard Worker     android::sp<V1_0::IBootControl> v1_0_module;
416*4d7e907cSAndroid Build Coastguard Worker     android::sp<V1_1::IBootControl> v1_1_module;
417*4d7e907cSAndroid Build Coastguard Worker     android::sp<V1_2::IBootControl> v1_2_module;
418*4d7e907cSAndroid Build Coastguard Worker     v1_0_module = V1_0::IBootControl::getService();
419*4d7e907cSAndroid Build Coastguard Worker     if (v1_0_module == nullptr) {
420*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error getting bootctrl v1.0 module.";
421*4d7e907cSAndroid Build Coastguard Worker         return nullptr;
422*4d7e907cSAndroid Build Coastguard Worker     }
423*4d7e907cSAndroid Build Coastguard Worker     v1_1_module = V1_1::IBootControl::castFrom(v1_0_module);
424*4d7e907cSAndroid Build Coastguard Worker     v1_2_module = V1_2::IBootControl::castFrom(v1_0_module);
425*4d7e907cSAndroid Build Coastguard Worker     if (v1_2_module != nullptr) {
426*4d7e907cSAndroid Build Coastguard Worker         LOG(INFO) << "Using HIDL version 1.2 of IBootControl";
427*4d7e907cSAndroid Build Coastguard Worker     } else if (v1_1_module != nullptr) {
428*4d7e907cSAndroid Build Coastguard Worker         LOG(INFO) << "Using HIDL version 1.1 of IBootControl";
429*4d7e907cSAndroid Build Coastguard Worker     } else {
430*4d7e907cSAndroid Build Coastguard Worker         LOG(INFO) << "Using HIDL version 1.0 of IBootControl";
431*4d7e907cSAndroid Build Coastguard Worker     }
432*4d7e907cSAndroid Build Coastguard Worker 
433*4d7e907cSAndroid Build Coastguard Worker     return std::make_unique<BootControlClientHIDL>(v1_0_module, v1_1_module, v1_2_module);
434*4d7e907cSAndroid Build Coastguard Worker }
435*4d7e907cSAndroid Build Coastguard Worker 
436*4d7e907cSAndroid Build Coastguard Worker }  // namespace android::hal
437