Home | History | Annotate | Download | only in installd
      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