blob: 5b5f5223aae8d3eb2af585b7aac780411fa75dfc [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) {
Calin Juravle7707aea2018-02-01 14:56:14 +000096 return ReadArgumentsPostV1(2, argv, false);
Calin Juravlec9e76792018-02-01 14:44:56 +000097 } else {
Calin Juravle7707aea2018-02-01 14:56:14 +000098 return ReadArgumentsV1(argv);
Calin Juravlec9e76792018-02-01 14:44:56 +000099 }
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
Calin Juravle7707aea2018-02-01 14:56:14 +0000108 return ReadArgumentsPostV1(version, argv, true);
Calin Juravlec9e76792018-02-01 14:44:56 +0000109}
110
111static int ReplaceMask(int input, int old_mask, int new_mask) {
112 return (input & old_mask) != 0 ? new_mask : 0;
113}
114
Calin Juravle7707aea2018-02-01 14:56:14 +0000115bool OTAPreoptParameters::ReadArgumentsV1(const char** argv) {
Calin Juravlec9e76792018-02-01 14:44:56 +0000116 // Check for "dexopt".
117 if (argv[2] == nullptr) {
118 LOG(ERROR) << "Missing parameters";
119 return false;
120 }
121 if (std::string("dexopt").compare(argv[2]) != 0) {
Calin Juravle7707aea2018-02-01 14:56:14 +0000122 LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[2];
Calin Juravlec9e76792018-02-01 14:44:56 +0000123 return false;
124 }
125
126 size_t param_index = 0;
127 for (;; ++param_index) {
128 const char* param = argv[3 + param_index];
129 if (param == nullptr) {
130 break;
131 }
132
133 switch (param_index) {
134 case 0:
135 apk_path = param;
136 break;
137
138 case 1:
139 uid = atoi(param);
140 break;
141
142 case 2:
143 pkgName = param;
144 break;
145
146 case 3:
147 instruction_set = param;
148 break;
149
150 case 4: {
151 // Version 1 had:
152 // DEXOPT_DEX2OAT_NEEDED = 1
153 // DEXOPT_PATCHOAT_NEEDED = 2
154 // DEXOPT_SELF_PATCHOAT_NEEDED = 3
155 // We will simply use DEX2OAT_FROM_SCRATCH.
156 dexopt_needed = DEX2OAT_FROM_SCRATCH;
157 break;
158 }
159
160 case 5:
161 oat_dir = param;
162 break;
163
164 case 6: {
165 // Version 1 had:
166 constexpr int OLD_DEXOPT_PUBLIC = 1 << 1;
167 // Note: DEXOPT_SAFEMODE has been removed.
168 // constexpr int OLD_DEXOPT_SAFEMODE = 1 << 2;
169 constexpr int OLD_DEXOPT_DEBUGGABLE = 1 << 3;
170 constexpr int OLD_DEXOPT_BOOTCOMPLETE = 1 << 4;
171 constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
172 constexpr int OLD_DEXOPT_OTA = 1 << 6;
173 int input = atoi(param);
174 dexopt_flags =
175 ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
176 ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
177 ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
178 ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
179 ReplaceMask(input, OLD_DEXOPT_OTA, 0);
180 break;
181 }
182
183 case 7:
184 compiler_filter = param;
185 break;
186
187 case 8:
188 volume_uuid = ParseNull(param);
189 break;
190
191 case 9:
192 shared_libraries = ParseNull(param);
193 break;
194
195 default:
196 LOG(ERROR) << "Too many arguments, got " << param;
197 return false;
198 }
199 }
200
201 if (param_index != 10) {
202 LOG(ERROR) << "Not enough parameters";
203 return false;
204 }
205
206 // Set se_info to null. It is only relevant for secondary dex files, which we won't
207 // receive from a v1 A side.
208 se_info = nullptr;
209
210 // Set downgrade to false. It is only relevant when downgrading compiler
211 // filter, which is not the case during ota.
212 downgrade = false;
213
214 // Set target_sdk_version to 0, ie the platform SDK version. This is
215 // conservative and may force some classes to verify at runtime.
216 target_sdk_version = 0;
217
218 // Set the profile name to the primary apk profile.
219 profile_name = "primary.prof";
220
221 return true;
222}
223
Calin Juravle7707aea2018-02-01 14:56:14 +0000224bool OTAPreoptParameters::ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned) {
225 size_t num_args_expected = 0;
226 switch (version) {
227 case 2: num_args_expected = 11; break;
228 case 3: num_args_expected = 12; break;
229 case 4: num_args_expected = 13; break;
230 case 5: num_args_expected = 14; break;
Calin Juravlecc3b8ae2018-02-01 17:03:23 +0000231 case 6: num_args_expected = 15; break;
Calin Juravle7707aea2018-02-01 14:56:14 +0000232 default:
233 LOG(ERROR) << "Don't know how to read arguments for version " << version;
234 return false;
235 }
236 size_t dexopt_index = versioned ? 3 : 2;
237
238 // Check for "dexopt".
239 if (argv[dexopt_index] == nullptr) {
240 LOG(ERROR) << "Missing parameters";
241 return false;
242 }
243 if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
244 LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[dexopt_index];
245 return false;
246 }
247
248 // Validate the number of arguments.
249 size_t num_args_actual = 0;
250 while (argv[dexopt_index + 1 + num_args_actual] != nullptr) {
251 num_args_actual++;
252 }
253
254 if (num_args_actual != num_args_expected) {
255 LOG(ERROR) << "Invalid number of arguments. expected="
256 << num_args_expected << " actual=" << num_args_actual;
257 return false;
258 }
259
260 // The number of arguments is OK.
261 // Configure the default values for the parameters that were added after V1.
262 // The default values will be overwritten in case they are passed as arguments.
263
264 // Set downgrade to false. It is only relevant when downgrading compiler
265 // filter, which is not the case during ota.
266 downgrade = false;
267
268 // Set target_sdk_version to 0, ie the platform SDK version. This is
269 // conservative and may force some classes to verify at runtime.
270 target_sdk_version = 0;
271
272 // Set the profile name to the primary apk profile.
273 profile_name = "primary.prof";
274
275 for (size_t param_index = 0; param_index < num_args_actual; ++param_index) {
276 const char* param = argv[dexopt_index + 1 + param_index];
277 switch (param_index) {
278 case 0:
279 apk_path = param;
280 break;
281
282 case 1:
283 uid = atoi(param);
284 break;
285
286 case 2:
287 pkgName = param;
288 break;
289
290 case 3:
291 instruction_set = param;
292 break;
293
294 case 4:
295 dexopt_needed = atoi(param);
296 break;
297
298 case 5:
299 oat_dir = param;
300 break;
301
302 case 6:
303 dexopt_flags = atoi(param);
304 break;
305
306 case 7:
307 compiler_filter = param;
308 break;
309
310 case 8:
311 volume_uuid = ParseNull(param);
312 break;
313
314 case 9:
315 shared_libraries = ParseNull(param);
316 break;
317
318 case 10:
319 se_info = ParseNull(param);
320 break;
321
322 case 11:
323 downgrade = ParseBool(param);
324 break;
325
326 case 12:
327 target_sdk_version = atoi(param);
328 break;
329
330 case 13:
331 profile_name = ParseNull(param);
332 break;
333
Calin Juravlecc3b8ae2018-02-01 17:03:23 +0000334 case 14:
335 dex_metadata_path = ParseNull(param);
336
Calin Juravle7707aea2018-02-01 14:56:14 +0000337 default:
338 CHECK(false) << "Should not get here. Did you call ReadArguments "
339 << "with the right expectation?";
340 }
341 }
342
343 return true;
344}
345
Calin Juravlec9e76792018-02-01 14:44:56 +0000346} // namespace installd
347} // namespace android