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 <android-base/logging.h>
18 
19 #include <cutils/properties.h>
20 
21 #include <aidl/android/hardware/boot/IBootControl.h>
22 
23 #include <aidl/Vintf.h>
24 #include <android/binder_manager.h>
25 #include <gtest/gtest.h>
26 #include <hidl/GtestPrinter.h>
27 #include <hidl/ServiceManagement.h>
28 
29 #include <unordered_set>
30 
31 using aidl::android::hardware::boot::IBootControl;
32 using std::string;
33 using std::unordered_set;
34 
35 // The main test class for the Boot HIDL HAL.
36 class BootAidlTest : public ::testing::TestWithParam<std::string> {
37   public:
SetUp()38     virtual void SetUp() override {
39         const auto instance_name = GetParam();
40         ASSERT_TRUE(AServiceManager_isDeclared(instance_name.c_str()))
41                 << " instance " << instance_name << " not declared.";
42         boot = ::aidl::android::hardware::boot::IBootControl::fromBinder(
43                 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
44         ASSERT_NE(boot, nullptr);
45     }
46 
47     std::shared_ptr<IBootControl> boot;
48 };
49 
50 // validity check Boot::getNumberSlots().
TEST_P(BootAidlTest,GetNumberSlots)51 TEST_P(BootAidlTest, GetNumberSlots) {
52     int32_t slots{};
53     boot->getNumberSlots(&slots);
54     ASSERT_LE(2, slots);
55 }
56 
57 // validity check Boot::getCurrentSlot().
TEST_P(BootAidlTest,GetCurrentSlot)58 TEST_P(BootAidlTest, GetCurrentSlot) {
59     int curSlot = -1;
60     boot->getCurrentSlot(&curSlot);
61     int slots = 0;
62     boot->getNumberSlots(&slots);
63     ASSERT_LT(curSlot, slots);
64 }
65 
66 // validity check Boot::markBootSuccessful().
TEST_P(BootAidlTest,MarkBootSuccessful)67 TEST_P(BootAidlTest, MarkBootSuccessful) {
68     const auto result = boot->markBootSuccessful();
69     ASSERT_TRUE(result.isOk());
70     int curSlot = 0;
71     boot->getCurrentSlot(&curSlot);
72     bool ret = false;
73     boot->isSlotMarkedSuccessful(curSlot, &ret);
74     ASSERT_TRUE(ret);
75 }
76 
TEST_P(BootAidlTest,SetActiveBootSlot)77 TEST_P(BootAidlTest, SetActiveBootSlot) {
78     int curSlot = -1;
79     boot->getCurrentSlot(&curSlot);
80     ASSERT_GE(curSlot, 0);
81     int otherSlot = curSlot ? 0 : 1;
82     bool otherBootable = true;
83     boot->isSlotBootable(otherSlot, &otherBootable);
84 
85     for (int s = 0; s < 2; s++) {
86         const auto result = boot->setActiveBootSlot(s);
87         ASSERT_TRUE(result.isOk());
88     }
89     {
90         // Restore original flags to avoid problems on reboot
91         auto result = boot->setActiveBootSlot(curSlot);
92         ASSERT_TRUE(result.isOk());
93 
94         if (!otherBootable) {
95             const auto result = boot->setSlotAsUnbootable(otherSlot);
96             ASSERT_TRUE(result.isOk());
97         }
98 
99         result = boot->markBootSuccessful();
100         ASSERT_TRUE(result.isOk());
101     }
102     {
103         int slots = 0;
104         boot->getNumberSlots(&slots);
105         const auto result = boot->setActiveBootSlot(slots);
106         ASSERT_FALSE(result.isOk()) << "setActiveBootSlot on invalid slot should fail";
107     }
108 }
109 
TEST_P(BootAidlTest,SetSlotAsUnbootable)110 TEST_P(BootAidlTest, SetSlotAsUnbootable) {
111     int curSlot = -1;
112     boot->getCurrentSlot(&curSlot);
113     ASSERT_GE(curSlot, 0);
114     int otherSlot = curSlot ? 0 : 1;
115     bool otherBootable = false;
116     boot->isSlotBootable(otherSlot, &otherBootable);
117     {
118         auto result = boot->setSlotAsUnbootable(otherSlot);
119         ASSERT_TRUE(result.isOk());
120         boot->isSlotBootable(otherSlot, &otherBootable);
121         ASSERT_FALSE(otherBootable);
122 
123         // Restore original flags to avoid problems on reboot
124         if (otherBootable) {
125             result = boot->setActiveBootSlot(otherSlot);
126             ASSERT_TRUE(result.isOk());
127         }
128         result = boot->setActiveBootSlot(curSlot);
129         ASSERT_TRUE(result.isOk());
130         result = boot->markBootSuccessful();
131         ASSERT_TRUE(result.isOk());
132     }
133     {
134         int32_t slots = 0;
135         boot->getNumberSlots(&slots);
136         const auto result = boot->setSlotAsUnbootable(slots);
137         ASSERT_FALSE(result.isOk());
138     }
139 }
140 
141 // validity check Boot::isSlotBootable() on good and bad inputs.
TEST_P(BootAidlTest,IsSlotBootable)142 TEST_P(BootAidlTest, IsSlotBootable) {
143     for (int s = 0; s < 2; s++) {
144         bool bootable = false;
145         const auto res = boot->isSlotBootable(s, &bootable);
146         ASSERT_TRUE(res.isOk()) << res.getMessage();
147     }
148     int32_t slots = 0;
149     boot->getNumberSlots(&slots);
150     bool bootable = false;
151     const auto res = boot->isSlotBootable(slots, &bootable);
152     ASSERT_FALSE(res.isOk());
153 }
154 
155 // validity check Boot::isSlotMarkedSuccessful() on good and bad inputs.
TEST_P(BootAidlTest,IsSlotMarkedSuccessful)156 TEST_P(BootAidlTest, IsSlotMarkedSuccessful) {
157     for (int32_t s = 0; s < 2; s++) {
158         bool isSuccess = false;
159         const auto res = boot->isSlotMarkedSuccessful(s, &isSuccess);
160     }
161     int32_t slots = 0;
162     boot->getNumberSlots(&slots);
163     bool isSuccess = false;
164     const auto res = boot->isSlotMarkedSuccessful(slots, &isSuccess);
165     ASSERT_FALSE(res.isOk());
166 }
167 
168 // validity check Boot::getSuffix() on good and bad inputs.
TEST_P(BootAidlTest,GetSuffix)169 TEST_P(BootAidlTest, GetSuffix) {
170     string suffixStr;
171     unordered_set<string> suffixes;
172     int numSlots = 0;
173     boot->getNumberSlots(&numSlots);
174     for (int32_t i = 0; i < numSlots; i++) {
175         std::string suffix;
176         const auto result = boot->getSuffix(i, &suffixStr);
177         ASSERT_TRUE(result.isOk());
178         ASSERT_EQ('_', suffixStr[0]);
179         ASSERT_LE((unsigned)2, suffixStr.size());
180         suffixes.insert(suffixStr);
181     }
182     // All suffixes should be unique
183     ASSERT_EQ(numSlots, suffixes.size());
184     {
185         const string emptySuffix = "";
186         const auto result = boot->getSuffix(numSlots, &suffixStr);
187         ASSERT_TRUE(result.isOk());
188         ASSERT_EQ(suffixStr, emptySuffix);
189     }
190 }
191 
192 INSTANTIATE_TEST_SUITE_P(
193         PerInstance, BootAidlTest,
194         testing::ValuesIn(android::getAidlHalInstanceNames(IBootControl::descriptor)));
195 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BootAidlTest);
196