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 32 static bool ParseBool(const char* in) { 33 if (strcmp(in, "true") == 0) { 34 return true; 35 } 36 return false; 37 } 38 39 static const char* ParseNull(const char* arg) { 40 return (strcmp(arg, "!") == 0) ? nullptr : arg; 41 } 42 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 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 111 static int ReplaceMask(int input, int old_mask, int new_mask) { 112 return (input & old_mask) != 0 ? new_mask : 0; 113 } 114 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 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 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