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