1 /*
2 ** Copyright 2016, 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 "otapreopt_parameters.h"
18
19 #include <android-base/logging.h>
20
21 #include "dexopt.h"
22 #include "installd_constants.h"
23 #include "otapreopt_utils.h"
24
25 #ifndef LOG_TAG
26 #define LOG_TAG "otapreopt"
27 #endif
28
29 namespace android {
30 namespace installd {
31
ParseBool(const char * in)32 static bool ParseBool(const char* in) {
33 if (strcmp(in, "true") == 0) {
34 return true;
35 }
36 return false;
37 }
38
ParseNull(const char * arg)39 static const char* ParseNull(const char* arg) {
40 return (strcmp(arg, "!") == 0) ? nullptr : arg;
41 }
42
ParseUInt(const char * in,uint32_t * out)43 static bool ParseUInt(const char* in, uint32_t* out) {
44 char* end;
45 long long int result = strtoll(in, &end, 0);
46 if (in == end || *end != '\0') {
47 return false;
48 }
49 if (result < std::numeric_limits<uint32_t>::min() ||
50 std::numeric_limits<uint32_t>::max() < result) {
51 return false;
52 }
53 *out = static_cast<uint32_t>(result);
54 return true;
55 }
56
ReadArguments(int argc,const char ** argv)57 bool OTAPreoptParameters::ReadArguments(int argc, const char** argv) {
58 // Expected command line:
59 // target-slot [version] dexopt {DEXOPT_PARAMETERS}
60
61 const char* target_slot_arg = argv[1];
62 if (target_slot_arg == nullptr) {
63 LOG(ERROR) << "Missing parameters";
64 return false;
65 }
66 // Sanitize value. Only allow (a-zA-Z0-9_)+.
67 target_slot = target_slot_arg;
68 if (!ValidateTargetSlotSuffix(target_slot)) {
69 LOG(ERROR) << "Target slot suffix not legal: " << target_slot;
70 return false;
71 }
72
73 // Check for version or "dexopt" next.
74 if (argv[2] == nullptr) {
75 LOG(ERROR) << "Missing parameters";
76 return false;
77 }
78
79 if (std::string("dexopt").compare(argv[2]) == 0) {
80 // This is version 1 (N) or pre-versioning version 2.
81 constexpr int kV2ArgCount = 1 // "otapreopt"
82 + 1 // slot
83 + 1 // "dexopt"
84 + 1 // apk_path
85 + 1 // uid
86 + 1 // pkg
87 + 1 // isa
88 + 1 // dexopt_needed
89 + 1 // oat_dir
90 + 1 // dexopt_flags
91 + 1 // filter
92 + 1 // volume
93 + 1 // libs
94 + 1; // seinfo
95 if (argc == kV2ArgCount) {
96 return ReadArgumentsPostV1(2, argv, false);
97 } else {
98 return ReadArgumentsV1(argv);
99 }
100 }
101
102 uint32_t version;
103 if (!ParseUInt(argv[2], &version)) {
104 LOG(ERROR) << "Could not parse version: " << argv[2];
105 return false;
106 }
107
108 return ReadArgumentsPostV1(version, argv, true);
109 }
110
ReplaceMask(int input,int old_mask,int new_mask)111 static int ReplaceMask(int input, int old_mask, int new_mask) {
112 return (input & old_mask) != 0 ? new_mask : 0;
113 }
114
SetDefaultsForPostV1Arguments()115 void OTAPreoptParameters::SetDefaultsForPostV1Arguments() {
116 // Set se_info to null. It is only relevant for secondary dex files, which we won't
117 // receive from a v1 A side.
118 se_info = nullptr;
119
120 // Set downgrade to false. It is only relevant when downgrading compiler
121 // filter, which is not the case during ota.
122 downgrade = false;
123
124 // Set target_sdk_version to 0, ie the platform SDK version. This is
125 // conservative and may force some classes to verify at runtime.
126 target_sdk_version = 0;
127
128 // Set the profile name to the primary apk profile.
129 profile_name = "primary.prof";
130
131 // By default we don't have a dex metadata file.
132 dex_metadata_path = nullptr;
133
134 // The compilation reason is ab-ota (match the system property pm.dexopt.ab-ota)
135 compilation_reason = "ab-ota";
136
137 // Flag is enabled by default for A/B otas.
138 dexopt_flags = DEXOPT_GENERATE_COMPACT_DEX;
139 }
140
ReadArgumentsV1(const char ** argv)141 bool OTAPreoptParameters::ReadArgumentsV1(const char** argv) {
142 // Check for "dexopt".
143 if (argv[2] == nullptr) {
144 LOG(ERROR) << "Missing parameters";
145 return false;
146 }
147 if (std::string("dexopt").compare(argv[2]) != 0) {
148 LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[2];
149 return false;
150 }
151
152 SetDefaultsForPostV1Arguments();
153
154 size_t param_index = 0;
155 for (;; ++param_index) {
156 const char* param = argv[3 + param_index];
157 if (param == nullptr) {
158 break;
159 }
160
161 switch (param_index) {
162 case 0:
163 apk_path = param;
164 break;
165
166 case 1:
167 uid = atoi(param);
168 break;
169
170 case 2:
171 pkgName = param;
172 break;
173
174 case 3:
175 instruction_set = param;
176 break;
177
178 case 4: {
179 // Version 1 had:
180 // DEXOPT_DEX2OAT_NEEDED = 1
181 // DEXOPT_PATCHOAT_NEEDED = 2
182 // DEXOPT_SELF_PATCHOAT_NEEDED = 3
183 // We will simply use DEX2OAT_FROM_SCRATCH.
184 dexopt_needed = DEX2OAT_FROM_SCRATCH;
185 break;
186 }
187
188 case 5:
189 oat_dir = param;
190 break;
191
192 case 6: {
193 // Version 1 had:
194 constexpr int OLD_DEXOPT_PUBLIC = 1 << 1;
195 // Note: DEXOPT_SAFEMODE has been removed.
196 // constexpr int OLD_DEXOPT_SAFEMODE = 1 << 2;
197 constexpr int OLD_DEXOPT_DEBUGGABLE = 1 << 3;
198 constexpr int OLD_DEXOPT_BOOTCOMPLETE = 1 << 4;
199 constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
200 constexpr int OLD_DEXOPT_OTA = 1 << 6;
201 static_assert(DEXOPT_GENERATE_COMPACT_DEX > OLD_DEXOPT_OTA, "must not overlap");
202 int input = atoi(param);
203 dexopt_flags |=
204 ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
205 ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
206 ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
207 ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
208 ReplaceMask(input, OLD_DEXOPT_OTA, 0);
209 break;
210 }
211
212 case 7:
213 compiler_filter = param;
214 break;
215
216 case 8:
217 volume_uuid = ParseNull(param);
218 break;
219
220 case 9:
221 shared_libraries = ParseNull(param);
222 break;
223
224 default:
225 LOG(ERROR) << "Too many arguments, got " << param;
226 return false;
227 }
228 }
229
230 if (param_index != 10) {
231 LOG(ERROR) << "Not enough parameters";
232 return false;
233 }
234
235 return true;
236 }
237
ReadArgumentsPostV1(uint32_t version,const char ** argv,bool versioned)238 bool OTAPreoptParameters::ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned) {
239 size_t num_args_expected = 0;
240 switch (version) {
241 case 2: num_args_expected = 11; break;
242 case 3: num_args_expected = 12; break;
243 case 4: num_args_expected = 13; break;
244 case 5: num_args_expected = 14; break;
245 case 6: num_args_expected = 15; break;
246 case 7:
247 // Version 8 adds a new dexopt flag: DEXOPT_GENERATE_COMPACT_DEX
248 case 8: num_args_expected = 16; break;
249 // Version 9 adds a new dexopt flag: DEXOPT_GENERATE_APP_IMAGE
250 case 9: num_args_expected = 16; break;
251 default:
252 LOG(ERROR) << "Don't know how to read arguments for version " << version;
253 return false;
254 }
255 size_t dexopt_index = versioned ? 3 : 2;
256
257 // Check for "dexopt".
258 if (argv[dexopt_index] == nullptr) {
259 LOG(ERROR) << "Missing parameters";
260 return false;
261 }
262 if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
263 LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[dexopt_index];
264 return false;
265 }
266
267 // Validate the number of arguments.
268 size_t num_args_actual = 0;
269 while (argv[dexopt_index + 1 + num_args_actual] != nullptr) {
270 num_args_actual++;
271 }
272
273 if (num_args_actual != num_args_expected) {
274 LOG(ERROR) << "Invalid number of arguments. expected="
275 << num_args_expected << " actual=" << num_args_actual;
276 return false;
277 }
278
279 // The number of arguments is OK.
280 // Configure the default values for the parameters that were added after V1.
281 // The default values will be overwritten in case they are passed as arguments.
282 SetDefaultsForPostV1Arguments();
283
284 for (size_t param_index = 0; param_index < num_args_actual; ++param_index) {
285 const char* param = argv[dexopt_index + 1 + param_index];
286 switch (param_index) {
287 case 0:
288 apk_path = param;
289 break;
290
291 case 1:
292 uid = atoi(param);
293 break;
294
295 case 2:
296 pkgName = param;
297 break;
298
299 case 3:
300 instruction_set = param;
301 break;
302
303 case 4:
304 dexopt_needed = atoi(param);
305 break;
306
307 case 5:
308 oat_dir = param;
309 break;
310
311 case 6:
312 dexopt_flags = atoi(param);
313 // Add CompactDex generation flag for versions less than 8 since it wasn't passed
314 // from the package manager. Only conditionally set the flag here so that it can
315 // be fully controlled by the package manager.
316 dexopt_flags |= (version < 8) ? DEXOPT_GENERATE_COMPACT_DEX : 0u;
317 break;
318
319 case 7:
320 compiler_filter = param;
321 break;
322
323 case 8:
324 volume_uuid = ParseNull(param);
325 break;
326
327 case 9:
328 shared_libraries = ParseNull(param);
329 break;
330
331 case 10:
332 se_info = ParseNull(param);
333 break;
334
335 case 11:
336 downgrade = ParseBool(param);
337 break;
338
339 case 12:
340 target_sdk_version = atoi(param);
341 break;
342
343 case 13:
344 profile_name = ParseNull(param);
345 break;
346
347 case 14:
348 dex_metadata_path = ParseNull(param);
349 break;
350
351 case 15:
352 compilation_reason = ParseNull(param);
353 break;
354
355 default:
356 LOG(FATAL) << "Should not get here. Did you call ReadArguments "
357 << "with the right expectation? index=" << param_index
358 << " num_args=" << num_args_actual;
359 return false;
360 }
361 }
362
363 return true;
364 }
365
366 } // namespace installd
367 } // namespace android
368