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