blob: 0cfaab8a26536abdb4c2572e01add1c4928d86b5 [file] [log] [blame]
Calin Juravlec9e76792018-02-01 14:44:56 +00001/*
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
29namespace android {
30namespace installd {
31
32static bool ParseBool(const char* in) {
33 if (strcmp(in, "true") == 0) {
34 return true;
35 }
36 return false;
37}
38
39static const char* ParseNull(const char* arg) {
40 return (strcmp(arg, "!") == 0) ? nullptr : arg;
41}
42
43static 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
57bool 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 ReadArgumentsV2(argc, argv, false);
97 } else {
98 return ReadArgumentsV1(argc, 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 switch (version) {
109 case 2:
110 return ReadArgumentsV2(argc, argv, true);
111 case 3:
112 return ReadArgumentsV3(argc, argv);
113 case 4:
114 return ReadArgumentsV4(argc, argv);
115 case 5:
116 return ReadArgumentsV5(argc, argv);
117
118 default:
119 LOG(ERROR) << "Unsupported version " << version;
120 return false;
121 }
122}
123
124bool OTAPreoptParameters::ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, const char** argv, bool versioned) {
125 size_t dexopt_index = versioned ? 3 : 2;
126
127 // Check for "dexopt".
128 if (argv[dexopt_index] == nullptr) {
129 LOG(ERROR) << "Missing parameters";
130 return false;
131 }
132 if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
133 LOG(ERROR) << "Expected \"dexopt\"";
134 return false;
135 }
136
137 size_t param_index = 0;
138 for (;; ++param_index) {
139 const char* param = argv[dexopt_index + 1 + param_index];
140 if (param == nullptr) {
141 break;
142 }
143
144 switch (param_index) {
145 case 0:
146 apk_path = param;
147 break;
148
149 case 1:
150 uid = atoi(param);
151 break;
152
153 case 2:
154 pkgName = param;
155 break;
156
157 case 3:
158 instruction_set = param;
159 break;
160
161 case 4:
162 dexopt_needed = atoi(param);
163 break;
164
165 case 5:
166 oat_dir = param;
167 break;
168
169 case 6:
170 dexopt_flags = atoi(param);
171 break;
172
173 case 7:
174 compiler_filter = param;
175 break;
176
177 case 8:
178 volume_uuid = ParseNull(param);
179 break;
180
181 case 9:
182 shared_libraries = ParseNull(param);
183 break;
184
185 case 10:
186 se_info = ParseNull(param);
187 break;
188
189 default:
190 LOG(ERROR) << "Too many arguments, got " << param;
191 return false;
192 }
193 }
194
195 // Set downgrade to false. It is only relevant when downgrading compiler
196 // filter, which is not the case during ota.
197 downgrade = false;
198
199 // Set target_sdk_version to 0, ie the platform SDK version. This is
200 // conservative and may force some classes to verify at runtime.
201 target_sdk_version = 0;
202
203 // Set the profile name to the primary apk profile.
204 profile_name = "primary.prof";
205
206 if (param_index != 11) {
207 LOG(ERROR) << "Not enough parameters";
208 return false;
209 }
210
211 return true;
212}
213
214bool OTAPreoptParameters::ReadArgumentsV3(int argc ATTRIBUTE_UNUSED, const char** argv) {
215 size_t dexopt_index = 3;
216
217 // Check for "dexopt".
218 if (argv[dexopt_index] == nullptr) {
219 LOG(ERROR) << "Missing parameters";
220 return false;
221 }
222 if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
223 LOG(ERROR) << "Expected \"dexopt\"";
224 return false;
225 }
226
227 size_t param_index = 0;
228 for (;; ++param_index) {
229 const char* param = argv[dexopt_index + 1 + param_index];
230 if (param == nullptr) {
231 break;
232 }
233
234 switch (param_index) {
235 case 0:
236 apk_path = param;
237 break;
238
239 case 1:
240 uid = atoi(param);
241 break;
242
243 case 2:
244 pkgName = param;
245 break;
246
247 case 3:
248 instruction_set = param;
249 break;
250
251 case 4:
252 dexopt_needed = atoi(param);
253 break;
254
255 case 5:
256 oat_dir = param;
257 break;
258
259 case 6:
260 dexopt_flags = atoi(param);
261 break;
262
263 case 7:
264 compiler_filter = param;
265 break;
266
267 case 8:
268 volume_uuid = ParseNull(param);
269 break;
270
271 case 9:
272 shared_libraries = ParseNull(param);
273 break;
274
275 case 10:
276 se_info = ParseNull(param);
277 break;
278
279 case 11:
280 downgrade = ParseBool(param);
281 break;
282
283 default:
284 LOG(ERROR) << "Too many arguments, got " << param;
285 return false;
286 }
287 }
288
289 // Set target_sdk_version to 0, ie the platform SDK version. This is
290 // conservative and may force some classes to verify at runtime.
291 target_sdk_version = 0;
292
293 // Set the profile name to the primary apk profile.
294 profile_name = "primary.prof";
295
296 if (param_index != 12) {
297 LOG(ERROR) << "Not enough parameters";
298 return false;
299 }
300
301 return true;
302}
303
304bool OTAPreoptParameters::ReadArgumentsV4(int argc ATTRIBUTE_UNUSED, const char** argv) {
305 size_t dexopt_index = 3;
306
307 // Check for "dexopt".
308 if (argv[dexopt_index] == nullptr) {
309 LOG(ERROR) << "Missing parameters";
310 return false;
311 }
312 if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
313 LOG(ERROR) << "Expected \"dexopt\"";
314 return false;
315 }
316
317 size_t param_index = 0;
318 for (;; ++param_index) {
319 const char* param = argv[dexopt_index + 1 + param_index];
320 if (param == nullptr) {
321 break;
322 }
323
324 switch (param_index) {
325 case 0:
326 apk_path = param;
327 break;
328
329 case 1:
330 uid = atoi(param);
331 break;
332
333 case 2:
334 pkgName = param;
335 break;
336
337 case 3:
338 instruction_set = param;
339 break;
340
341 case 4:
342 dexopt_needed = atoi(param);
343 break;
344
345 case 5:
346 oat_dir = param;
347 break;
348
349 case 6:
350 dexopt_flags = atoi(param);
351 break;
352
353 case 7:
354 compiler_filter = param;
355 break;
356
357 case 8:
358 volume_uuid = ParseNull(param);
359 break;
360
361 case 9:
362 shared_libraries = ParseNull(param);
363 break;
364
365 case 10:
366 se_info = ParseNull(param);
367 break;
368
369 case 11:
370 downgrade = ParseBool(param);
371 break;
372
373 case 12:
374 target_sdk_version = atoi(param);
375 break;
376
377 default:
378 LOG(ERROR) << "Too many arguments, got " << param;
379 return false;
380 }
381 }
382
383 // Set the profile name to the primary apk profile.
384 profile_name = "primary.prof";
385
386 if (param_index != 13) {
387 LOG(ERROR) << "Not enough parameters";
388 return false;
389 }
390
391 return true;
392}
393
394// TODO: this pattern does not scale and result in a lot of code duplication.
395// Either find a better pattern or refactor the code to eliminate the duplication.
396bool OTAPreoptParameters::ReadArgumentsV5(int argc ATTRIBUTE_UNUSED, const char** argv) {
397 size_t dexopt_index = 3;
398
399 // Check for "dexopt".
400 if (argv[dexopt_index] == nullptr) {
401 LOG(ERROR) << "Missing parameters";
402 return false;
403 }
404 if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
405 LOG(ERROR) << "Expected \"dexopt\"";
406 return false;
407 }
408
409 size_t param_index = 0;
410 for (;; ++param_index) {
411 const char* param = argv[dexopt_index + 1 + param_index];
412 if (param == nullptr) {
413 break;
414 }
415
416 switch (param_index) {
417 case 0:
418 apk_path = param;
419 break;
420
421 case 1:
422 uid = atoi(param);
423 break;
424
425 case 2:
426 pkgName = param;
427 break;
428
429 case 3:
430 instruction_set = param;
431 break;
432
433 case 4:
434 dexopt_needed = atoi(param);
435 break;
436
437 case 5:
438 oat_dir = param;
439 break;
440
441 case 6:
442 dexopt_flags = atoi(param);
443 break;
444
445 case 7:
446 compiler_filter = param;
447 break;
448
449 case 8:
450 volume_uuid = ParseNull(param);
451 break;
452
453 case 9:
454 shared_libraries = ParseNull(param);
455 break;
456
457 case 10:
458 se_info = ParseNull(param);
459 break;
460
461 case 11:
462 downgrade = ParseBool(param);
463 break;
464
465 case 12:
466 target_sdk_version = atoi(param);
467 break;
468
469 case 13:
470 profile_name = ParseNull(param);
471 break;
472
473 default:
474 LOG(ERROR) << "Too many arguments, got " << param;
475 return false;
476 }
477 }
478
479 if (param_index != 14) {
480 LOG(ERROR) << "Not enough parameters";
481 return false;
482 }
483
484 return true;
485}
486
487static int ReplaceMask(int input, int old_mask, int new_mask) {
488 return (input & old_mask) != 0 ? new_mask : 0;
489}
490
491bool OTAPreoptParameters::ReadArgumentsV1(int argc ATTRIBUTE_UNUSED, const char** argv) {
492 // Check for "dexopt".
493 if (argv[2] == nullptr) {
494 LOG(ERROR) << "Missing parameters";
495 return false;
496 }
497 if (std::string("dexopt").compare(argv[2]) != 0) {
498 LOG(ERROR) << "Expected \"dexopt\"";
499 return false;
500 }
501
502 size_t param_index = 0;
503 for (;; ++param_index) {
504 const char* param = argv[3 + param_index];
505 if (param == nullptr) {
506 break;
507 }
508
509 switch (param_index) {
510 case 0:
511 apk_path = param;
512 break;
513
514 case 1:
515 uid = atoi(param);
516 break;
517
518 case 2:
519 pkgName = param;
520 break;
521
522 case 3:
523 instruction_set = param;
524 break;
525
526 case 4: {
527 // Version 1 had:
528 // DEXOPT_DEX2OAT_NEEDED = 1
529 // DEXOPT_PATCHOAT_NEEDED = 2
530 // DEXOPT_SELF_PATCHOAT_NEEDED = 3
531 // We will simply use DEX2OAT_FROM_SCRATCH.
532 dexopt_needed = DEX2OAT_FROM_SCRATCH;
533 break;
534 }
535
536 case 5:
537 oat_dir = param;
538 break;
539
540 case 6: {
541 // Version 1 had:
542 constexpr int OLD_DEXOPT_PUBLIC = 1 << 1;
543 // Note: DEXOPT_SAFEMODE has been removed.
544 // constexpr int OLD_DEXOPT_SAFEMODE = 1 << 2;
545 constexpr int OLD_DEXOPT_DEBUGGABLE = 1 << 3;
546 constexpr int OLD_DEXOPT_BOOTCOMPLETE = 1 << 4;
547 constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
548 constexpr int OLD_DEXOPT_OTA = 1 << 6;
549 int input = atoi(param);
550 dexopt_flags =
551 ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
552 ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
553 ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
554 ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
555 ReplaceMask(input, OLD_DEXOPT_OTA, 0);
556 break;
557 }
558
559 case 7:
560 compiler_filter = param;
561 break;
562
563 case 8:
564 volume_uuid = ParseNull(param);
565 break;
566
567 case 9:
568 shared_libraries = ParseNull(param);
569 break;
570
571 default:
572 LOG(ERROR) << "Too many arguments, got " << param;
573 return false;
574 }
575 }
576
577 if (param_index != 10) {
578 LOG(ERROR) << "Not enough parameters";
579 return false;
580 }
581
582 // Set se_info to null. It is only relevant for secondary dex files, which we won't
583 // receive from a v1 A side.
584 se_info = nullptr;
585
586 // Set downgrade to false. It is only relevant when downgrading compiler
587 // filter, which is not the case during ota.
588 downgrade = false;
589
590 // Set target_sdk_version to 0, ie the platform SDK version. This is
591 // conservative and may force some classes to verify at runtime.
592 target_sdk_version = 0;
593
594 // Set the profile name to the primary apk profile.
595 profile_name = "primary.prof";
596
597 return true;
598}
599
600} // namespace installd
601} // namespace android