1 /**
2 * Copyright (C) 2018 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 <stdlib.h>
18 #include <string.h>
19
20 #include <android-base/logging.h>
21 #include <gtest/gtest.h>
22
23 #include "installd_constants.h"
24 #include "otapreopt_parameters.h"
25
26 namespace android {
27 namespace installd {
28
ParseBool(const char * in)29 static bool ParseBool(const char* in) {
30 if (strcmp(in, "true") == 0) {
31 return true;
32 }
33 return false;
34 }
35
ParseNull(const char * arg)36 static const char* ParseNull(const char* arg) {
37 return (strcmp(arg, "!") == 0) ? nullptr : arg;
38 }
39
40 class OTAPreoptTest : public testing::Test {
41 protected:
SetUp()42 virtual void SetUp() {
43 setenv("ANDROID_LOG_TAGS", "*:f", 1);
44 android::base::InitLogging(nullptr, android::base::StderrLogger);
45 }
46
verifyPackageParameters(const OTAPreoptParameters & params,uint32_t version,bool versioned,const char ** args)47 void verifyPackageParameters(const OTAPreoptParameters& params,
48 uint32_t version,
49 bool versioned,
50 const char** args) {
51 // otapreopt target-slot [version] dexopt {DEXOPT_PARAMETERS}
52 int i = 0;
53 if (version > 2 || (version == 2 && versioned)) {
54 i += 4;
55 } else {
56 i += 3;
57 }
58 ASSERT_STREQ(params.target_slot.c_str(), args[1]);
59 ASSERT_STREQ(params.apk_path, args[i++]);
60 ASSERT_EQ(params.uid, static_cast<uid_t>(atoi(args[i++])));
61 ASSERT_STREQ(params.pkgName, args[i++]);
62 ASSERT_STREQ(params.instruction_set, args[i++]);
63 ASSERT_EQ(params.dexopt_needed, atoi(args[i++]));
64 ASSERT_STREQ(params.oat_dir, args[i++]);
65 const int dexopt_flags = atoi(args[i++]);
66 ASSERT_STREQ(params.compiler_filter, args[i++]);
67 ASSERT_STREQ(params.volume_uuid, ParseNull(args[i++]));
68 ASSERT_STREQ(params.shared_libraries, ParseNull(args[i++]));
69 if (version > 1) {
70 ASSERT_STREQ(params.se_info, ParseNull(args[i++]));
71 } else {
72 ASSERT_EQ(params.se_info, nullptr);
73 }
74 if (version > 2) {
75 ASSERT_EQ(params.downgrade, ParseBool(args[i++]));
76 } else {
77 ASSERT_FALSE(params.downgrade);
78 }
79 if (version > 3) {
80 ASSERT_EQ(params.target_sdk_version, atoi(args[i++]));
81 } else {
82 ASSERT_EQ(params.target_sdk_version, 0);
83 }
84 if (version > 4) {
85 ASSERT_STREQ(params.profile_name, ParseNull(args[i++]));
86 } else {
87 ASSERT_STREQ(params.profile_name, "primary.prof");
88 }
89 if (version > 5) {
90 ASSERT_STREQ(params.dex_metadata_path, ParseNull(args[i++]));
91 } else {
92 ASSERT_EQ(params.dex_metadata_path, nullptr);
93 }
94 if (version > 6) {
95 ASSERT_STREQ(params.compilation_reason, ParseNull(args[i++]));
96 } else {
97 ASSERT_STREQ(params.compilation_reason, "ab-ota");
98 }
99 if (version > 7) {
100 ASSERT_EQ(params.dexopt_flags, dexopt_flags);
101 } else {
102 ASSERT_EQ(params.dexopt_flags, dexopt_flags | DEXOPT_GENERATE_COMPACT_DEX);
103 }
104 }
105
getVersionCStr(uint32_t version)106 const char* getVersionCStr(uint32_t version) {
107 switch (version) {
108 case 1: return "1";
109 case 2: return "2";
110 case 3: return "3";
111 case 4: return "4";
112 case 5: return "5";
113 case 6: return "6";
114 case 7: return "7";
115 case 8: return "8";
116 case 9: return "9";
117 case 10: return "10";
118 }
119 return nullptr;
120 }
121
getArgs(uint32_t version,bool versioned,const char * shared_libs="shared.lib")122 std::vector<const char*> getArgs(uint32_t version,
123 bool versioned,
124 const char* shared_libs = "shared.lib") {
125 std::vector<const char*> args;
126 args.push_back("otapreopt"); // "otapreopt"
127 args.push_back("a"); // slot
128 if (versioned) {
129 args.push_back(getVersionCStr(version));
130 }
131 args.push_back("dexopt"); // "dexopt"
132 args.push_back("foo.apk"); // apk_path
133 args.push_back("123"); // uid
134 args.push_back("pkgname"); // pkg
135 args.push_back("arm"); // isa
136 args.push_back("1"); // dexopt_needed (DEX2OAT_FROM_SCRATCH)
137 args.push_back("oat_dir"); // oat_dir
138 args.push_back("0"); // dexopt_flags
139 args.push_back("speed"); // filter
140 args.push_back("!"); // volume
141 args.push_back(shared_libs); // libs
142
143 if (version > 1) {
144 args.push_back("!"); // seinfo
145 }
146 if (version > 2) {
147 args.push_back("true"); // downgrade
148 }
149 if (version > 3) {
150 args.push_back("28"); // sdk_version
151 }
152 if (version > 4) {
153 args.push_back("split_a.prof"); // profile_name
154 }
155 if (version > 5) {
156 args.push_back("dex_metadata.dm"); // dex_metadata_path
157 }
158 if (version > 6) {
159 args.push_back("ab-ota-test"); // compilation_reason
160 }
161 args.push_back(nullptr); // we have to end with null.
162 return args;
163 }
164
VerifyReadArguments(uint32_t version,bool versioned,const char * shared_libs="shared.lib")165 void VerifyReadArguments(uint32_t version,
166 bool versioned,
167 const char* shared_libs = "shared.lib") {
168 OTAPreoptParameters params;
169 std::vector<const char*> args = getArgs(version, versioned, shared_libs);
170 ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
171 verifyPackageParameters(params, version, versioned, args.data());
172 }
173 };
174
TEST_F(OTAPreoptTest,ReadArgumentsV1)175 TEST_F(OTAPreoptTest, ReadArgumentsV1) {
176 VerifyReadArguments(1, false);
177 }
178
TEST_F(OTAPreoptTest,ReadArgumentsV2Unversioned)179 TEST_F(OTAPreoptTest, ReadArgumentsV2Unversioned) {
180 VerifyReadArguments(2, false);
181 }
182
TEST_F(OTAPreoptTest,ReadArgumentsV2)183 TEST_F(OTAPreoptTest, ReadArgumentsV2) {
184 VerifyReadArguments(2, true);
185 }
186
TEST_F(OTAPreoptTest,ReadArgumentsV3)187 TEST_F(OTAPreoptTest, ReadArgumentsV3) {
188 VerifyReadArguments(3, true);
189 }
190
TEST_F(OTAPreoptTest,ReadArgumentsV4)191 TEST_F(OTAPreoptTest, ReadArgumentsV4) {
192 VerifyReadArguments(4, true);
193 }
194
TEST_F(OTAPreoptTest,ReadArgumentsV5)195 TEST_F(OTAPreoptTest, ReadArgumentsV5) {
196 VerifyReadArguments(5, true);
197 }
198
TEST_F(OTAPreoptTest,ReadArgumentsV6)199 TEST_F(OTAPreoptTest, ReadArgumentsV6) {
200 VerifyReadArguments(6, true);
201 }
202
TEST_F(OTAPreoptTest,ReadArgumentsV7)203 TEST_F(OTAPreoptTest, ReadArgumentsV7) {
204 VerifyReadArguments(7, true);
205 }
206
TEST_F(OTAPreoptTest,ReadArgumentsV9SharedLibsAmpersand)207 TEST_F(OTAPreoptTest, ReadArgumentsV9SharedLibsAmpersand) {
208 OTAPreoptParameters params;
209 std::vector<const char*> args = getArgs(9, true, "&");
210 ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
211 }
212
TEST_F(OTAPreoptTest,ReadArgumentsV10SharedLibsAmpersand)213 TEST_F(OTAPreoptTest, ReadArgumentsV10SharedLibsAmpersand) {
214 OTAPreoptParameters params;
215 std::vector<const char*> args = getArgs(10, true, "&");
216 ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
217 }
218
TEST_F(OTAPreoptTest,ReadArgumentsFailToManyArgs)219 TEST_F(OTAPreoptTest, ReadArgumentsFailToManyArgs) {
220 OTAPreoptParameters params;
221 std::vector<const char*> args = getArgs(5, true);
222 args[2] = "3"; // pretend it's version 3. It should fail since there are too many args.
223 ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
224 }
225
TEST_F(OTAPreoptTest,ReadArgumentsFailInsufficientArgs)226 TEST_F(OTAPreoptTest, ReadArgumentsFailInsufficientArgs) {
227 OTAPreoptParameters params;
228 std::vector<const char*> args = getArgs(4, true);
229 args[2] = "5"; // pretend it's version 5. It should fail since there are insufficient args.
230 ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
231 }
232
TEST_F(OTAPreoptTest,ReadArgumentsFailInvalidDexopt)233 TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidDexopt) {
234 OTAPreoptParameters params;
235 std::vector<const char*> args = getArgs(4, true);
236 args[3] = "dexopt-invalid";
237 ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
238 }
239
TEST_F(OTAPreoptTest,ReadArgumentsFailInvalidSlot)240 TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidSlot) {
241 OTAPreoptParameters params;
242 std::vector<const char*> args = getArgs(3, true);
243 args[1] = "invalid-slot???";
244 ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
245 }
246
247 } // namespace installd
248 } // namespace android
249