otapreopt.cpp revision 54e1a402610d7f392f7e421dcafcf6b017a99d88
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 <algorithm>
18#include <inttypes.h>
19#include <random>
20#include <regex>
21#include <selinux/android.h>
22#include <selinux/avc.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/capability.h>
26#include <sys/prctl.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29
30#include <android-base/logging.h>
31#include <android-base/macros.h>
32#include <android-base/stringprintf.h>
33#include <android-base/strings.h>
34#include <cutils/fs.h>
35#include <cutils/properties.h>
36#include <dex2oat_return_codes.h>
37#include <log/log.h>
38#include <private/android_filesystem_config.h>
39
40#include "dexopt.h"
41#include "file_parsing.h"
42#include "globals.h"
43#include "installd_deps.h"  // Need to fill in requirements of commands.
44#include "otapreopt_utils.h"
45#include "system_properties.h"
46#include "utils.h"
47
48#ifndef LOG_TAG
49#define LOG_TAG "otapreopt"
50#endif
51
52#define BUFFER_MAX    1024  /* input buffer for commands */
53#define TOKEN_MAX     16    /* max number of arguments in buffer */
54#define REPLY_MAX     256   /* largest reply allowed */
55
56using android::base::EndsWith;
57using android::base::Join;
58using android::base::Split;
59using android::base::StartsWith;
60using android::base::StringPrintf;
61
62namespace android {
63namespace installd {
64
65template<typename T>
66static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
67    return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
68}
69
70template<typename T>
71static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
72    return RoundDown(x + n - 1, n);
73}
74
75class OTAPreoptService {
76 public:
77    // Main driver. Performs the following steps.
78    //
79    // 1) Parse options (read system properties etc from B partition).
80    //
81    // 2) Read in package data.
82    //
83    // 3) Prepare environment variables.
84    //
85    // 4) Prepare(compile) boot image, if necessary.
86    //
87    // 5) Run update.
88    int Main(int argc, char** argv) {
89        if (!ReadArguments(argc, argv)) {
90            LOG(ERROR) << "Failed reading command line.";
91            return 1;
92        }
93
94        if (!ReadSystemProperties()) {
95            LOG(ERROR)<< "Failed reading system properties.";
96            return 2;
97        }
98
99        if (!ReadEnvironment()) {
100            LOG(ERROR) << "Failed reading environment properties.";
101            return 3;
102        }
103
104        if (!CheckAndInitializeInstalldGlobals()) {
105            LOG(ERROR) << "Failed initializing globals.";
106            return 4;
107        }
108
109        PrepareEnvironment();
110
111        if (!PrepareBootImage(/* force */ false)) {
112            LOG(ERROR) << "Failed preparing boot image.";
113            return 5;
114        }
115
116        int dexopt_retcode = RunPreopt();
117
118        return dexopt_retcode;
119    }
120
121    int GetProperty(const char* key, char* value, const char* default_value) const {
122        const std::string* prop_value = system_properties_.GetProperty(key);
123        if (prop_value == nullptr) {
124            if (default_value == nullptr) {
125                return 0;
126            }
127            // Copy in the default value.
128            strncpy(value, default_value, kPropertyValueMax - 1);
129            value[kPropertyValueMax - 1] = 0;
130            return strlen(default_value);// TODO: Need to truncate?
131        }
132        size_t size = std::min(kPropertyValueMax - 1, prop_value->length());
133        strncpy(value, prop_value->data(), size);
134        value[size] = 0;
135        return static_cast<int>(size);
136    }
137
138    std::string GetOTADataDirectory() const {
139        return StringPrintf("%s/%s", GetOtaDirectoryPrefix().c_str(), target_slot_.c_str());
140    }
141
142    const std::string& GetTargetSlot() const {
143        return target_slot_;
144    }
145
146private:
147
148    bool ReadSystemProperties() {
149        static constexpr const char* kPropertyFiles[] = {
150                "/default.prop", "/system/build.prop"
151        };
152
153        for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
154            if (!system_properties_.Load(kPropertyFiles[i])) {
155                return false;
156            }
157        }
158
159        return true;
160    }
161
162    bool ReadEnvironment() {
163        // Parse the environment variables from init.environ.rc, which have the form
164        //   export NAME VALUE
165        // For simplicity, don't respect string quotation. The values we are interested in can be
166        // encoded without them.
167        std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
168        bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
169            std::smatch export_match;
170            if (!std::regex_match(line, export_match, export_regex)) {
171                return true;
172            }
173
174            if (export_match.size() != 3) {
175                return true;
176            }
177
178            std::string name = export_match[1].str();
179            std::string value = export_match[2].str();
180
181            system_properties_.SetProperty(name, value);
182
183            return true;
184        });
185        if (!parse_result) {
186            return false;
187        }
188
189        if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) {
190            return false;
191        }
192        android_data_ = *system_properties_.GetProperty(kAndroidDataPathPropertyName);
193
194        if (system_properties_.GetProperty(kAndroidRootPathPropertyName) == nullptr) {
195            return false;
196        }
197        android_root_ = *system_properties_.GetProperty(kAndroidRootPathPropertyName);
198
199        if (system_properties_.GetProperty(kBootClassPathPropertyName) == nullptr) {
200            return false;
201        }
202        boot_classpath_ = *system_properties_.GetProperty(kBootClassPathPropertyName);
203
204        if (system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) == nullptr) {
205            return false;
206        }
207        asec_mountpoint_ = *system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME);
208
209        return true;
210    }
211
212    const std::string& GetAndroidData() const {
213        return android_data_;
214    }
215
216    const std::string& GetAndroidRoot() const {
217        return android_root_;
218    }
219
220    const std::string GetOtaDirectoryPrefix() const {
221        return GetAndroidData() + "/ota";
222    }
223
224    bool CheckAndInitializeInstalldGlobals() {
225        // init_globals_from_data_and_root requires "ASEC_MOUNTPOINT" in the environment. We
226        // do not use any datapath that includes this, but we'll still have to set it.
227        CHECK(system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) != nullptr);
228        int result = setenv(ASEC_MOUNTPOINT_ENV_NAME, asec_mountpoint_.c_str(), 0);
229        if (result != 0) {
230            LOG(ERROR) << "Could not set ASEC_MOUNTPOINT environment variable";
231            return false;
232        }
233
234        if (!init_globals_from_data_and_root(GetAndroidData().c_str(), GetAndroidRoot().c_str())) {
235            LOG(ERROR) << "Could not initialize globals; exiting.";
236            return false;
237        }
238
239        // This is different from the normal installd. We only do the base
240        // directory, the rest will be created on demand when each app is compiled.
241        if (access(GetOtaDirectoryPrefix().c_str(), R_OK) < 0) {
242            LOG(ERROR) << "Could not access " << GetOtaDirectoryPrefix();
243            return false;
244        }
245
246        return true;
247    }
248
249    bool ReadArguments(int argc ATTRIBUTE_UNUSED, char** argv) {
250        // Expected command line:
251        //   target-slot dexopt {DEXOPT_PARAMETERS}
252        // The DEXOPT_PARAMETERS are passed on to dexopt(), so we expect DEXOPT_PARAM_COUNT
253        // of them. We store them in package_parameters_ (size checks are done when
254        // parsing the special parameters and when copying into package_parameters_.
255
256        static_assert(DEXOPT_PARAM_COUNT == ARRAY_SIZE(package_parameters_),
257                      "Unexpected dexopt param count");
258
259        const char* target_slot_arg = argv[1];
260        if (target_slot_arg == nullptr) {
261            LOG(ERROR) << "Missing parameters";
262            return false;
263        }
264        // Sanitize value. Only allow (a-zA-Z0-9_)+.
265        target_slot_ = target_slot_arg;
266        if (!ValidateTargetSlotSuffix(target_slot_)) {
267            LOG(ERROR) << "Target slot suffix not legal: " << target_slot_;
268            return false;
269        }
270
271        // Check for "dexopt" next.
272        if (argv[2] == nullptr) {
273            LOG(ERROR) << "Missing parameters";
274            return false;
275        }
276        if (std::string("dexopt").compare(argv[2]) != 0) {
277            LOG(ERROR) << "Second parameter not dexopt: " << argv[2];
278            return false;
279        }
280
281        // Copy the rest into package_parameters_, but be careful about over- and underflow.
282        size_t index = 0;
283        while (index < DEXOPT_PARAM_COUNT &&
284                argv[index + 3] != nullptr) {
285            package_parameters_[index] = argv[index + 3];
286            index++;
287        }
288        if (index != ARRAY_SIZE(package_parameters_) || argv[index + 3] != nullptr) {
289            LOG(ERROR) << "Wrong number of parameters";
290            return false;
291        }
292
293        return true;
294    }
295
296    void PrepareEnvironment() {
297        environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_classpath_.c_str()));
298        environ_.push_back(StringPrintf("ANDROID_DATA=%s", GetOTADataDirectory().c_str()));
299        environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root_.c_str()));
300
301        for (const std::string& e : environ_) {
302            putenv(const_cast<char*>(e.c_str()));
303        }
304    }
305
306    // Ensure that we have the right boot image. The first time any app is
307    // compiled, we'll try to generate it.
308    bool PrepareBootImage(bool force) const {
309        if (package_parameters_[kISAIndex] == nullptr) {
310            LOG(ERROR) << "Instruction set missing.";
311            return false;
312        }
313        const char* isa = package_parameters_[kISAIndex];
314
315        // Check whether the file exists where expected.
316        std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
317        std::string isa_path = dalvik_cache + "/" + isa;
318        std::string art_path = isa_path + "/system@framework@boot.art";
319        std::string oat_path = isa_path + "/system@framework@boot.oat";
320        bool cleared = false;
321        if (access(art_path.c_str(), F_OK) == 0 && access(oat_path.c_str(), F_OK) == 0) {
322            // Files exist, assume everything is alright if not forced. Otherwise clean up.
323            if (!force) {
324                return true;
325            }
326            ClearDirectory(isa_path);
327            cleared = true;
328        }
329
330        // Reset umask in otapreopt, so that we control the the access for the files we create.
331        umask(0);
332
333        // Create the directories, if necessary.
334        if (access(dalvik_cache.c_str(), F_OK) != 0) {
335            if (!CreatePath(dalvik_cache)) {
336                PLOG(ERROR) << "Could not create dalvik-cache dir " << dalvik_cache;
337                return false;
338            }
339        }
340        if (access(isa_path.c_str(), F_OK) != 0) {
341            if (!CreatePath(isa_path)) {
342                PLOG(ERROR) << "Could not create dalvik-cache isa dir";
343                return false;
344            }
345        }
346
347        // Prepare to create.
348        if (!cleared) {
349            ClearDirectory(isa_path);
350        }
351
352        std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
353        if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
354          return PatchoatBootImage(art_path, isa);
355        } else {
356          // No preopted boot image. Try to compile.
357          return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
358        }
359    }
360
361    static bool CreatePath(const std::string& path) {
362        // Create the given path. Use string processing instead of dirname, as dirname's need for
363        // a writable char buffer is painful.
364
365        // First, try to use the full path.
366        if (mkdir(path.c_str(), 0711) == 0) {
367            return true;
368        }
369        if (errno != ENOENT) {
370            PLOG(ERROR) << "Could not create path " << path;
371            return false;
372        }
373
374        // Now find the parent and try that first.
375        size_t last_slash = path.find_last_of('/');
376        if (last_slash == std::string::npos || last_slash == 0) {
377            PLOG(ERROR) << "Could not create " << path;
378            return false;
379        }
380
381        if (!CreatePath(path.substr(0, last_slash))) {
382            return false;
383        }
384
385        if (mkdir(path.c_str(), 0711) == 0) {
386            return true;
387        }
388        PLOG(ERROR) << "Could not create " << path;
389        return false;
390    }
391
392    static void ClearDirectory(const std::string& dir) {
393        DIR* c_dir = opendir(dir.c_str());
394        if (c_dir == nullptr) {
395            PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents";
396            return;
397        }
398
399        for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
400            const char* name = de->d_name;
401            if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
402                continue;
403            }
404            // We only want to delete regular files and symbolic links.
405            std::string file = StringPrintf("%s/%s", dir.c_str(), name);
406            if (de->d_type != DT_REG && de->d_type != DT_LNK) {
407                LOG(WARNING) << "Unexpected file "
408                             << file
409                             << " of type "
410                             << std::hex
411                             << de->d_type
412                             << " encountered.";
413            } else {
414                // Try to unlink the file.
415                if (unlink(file.c_str()) != 0) {
416                    PLOG(ERROR) << "Unable to unlink " << file;
417                }
418            }
419        }
420        CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
421    }
422
423    bool PatchoatBootImage(const std::string& art_path, const char* isa) const {
424        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
425
426        std::vector<std::string> cmd;
427        cmd.push_back("/system/bin/patchoat");
428
429        cmd.push_back("--input-image-location=/system/framework/boot.art");
430        cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str()));
431
432        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
433
434        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
435                                                          ART_BASE_ADDRESS_MAX_DELTA);
436        cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
437
438        std::string error_msg;
439        bool result = Exec(cmd, &error_msg);
440        if (!result) {
441            LOG(ERROR) << "Could not generate boot image: " << error_msg;
442        }
443        return result;
444    }
445
446    bool Dex2oatBootImage(const std::string& boot_cp,
447                          const std::string& art_path,
448                          const std::string& oat_path,
449                          const char* isa) const {
450        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
451        std::vector<std::string> cmd;
452        cmd.push_back("/system/bin/dex2oat");
453        cmd.push_back(StringPrintf("--image=%s", art_path.c_str()));
454        for (const std::string& boot_part : Split(boot_cp, ":")) {
455            cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str()));
456        }
457        cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
458
459        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
460                ART_BASE_ADDRESS_MAX_DELTA);
461        cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
462
463        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
464
465        // These things are pushed by AndroidRuntime, see frameworks/base/core/jni/AndroidRuntime.cpp.
466        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xms",
467                "-Xms",
468                true,
469                cmd);
470        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xmx",
471                "-Xmx",
472                true,
473                cmd);
474        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-filter",
475                "--compiler-filter=",
476                false,
477                cmd);
478        cmd.push_back("--image-classes=/system/etc/preloaded-classes");
479        // TODO: Compiled-classes.
480        const std::string* extra_opts =
481                system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
482        if (extra_opts != nullptr) {
483            std::vector<std::string> extra_vals = Split(*extra_opts, " ");
484            cmd.insert(cmd.end(), extra_vals.begin(), extra_vals.end());
485        }
486        // TODO: Should we lower this? It's usually set close to max, because
487        //       normally there's not much else going on at boot.
488        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-threads",
489                "-j",
490                false,
491                cmd);
492        AddCompilerOptionFromSystemProperty(
493                StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
494                "--instruction-set-variant=",
495                false,
496                cmd);
497        AddCompilerOptionFromSystemProperty(
498                StringPrintf("dalvik.vm.isa.%s.features", isa).c_str(),
499                "--instruction-set-features=",
500                false,
501                cmd);
502
503        std::string error_msg;
504        bool result = Exec(cmd, &error_msg);
505        if (!result) {
506            LOG(ERROR) << "Could not generate boot image: " << error_msg;
507        }
508        return result;
509    }
510
511    static const char* ParseNull(const char* arg) {
512        return (strcmp(arg, "!") == 0) ? nullptr : arg;
513    }
514
515    bool ShouldSkipPreopt() const {
516        // There's one thing we have to be careful about: we may/will be asked to compile an app
517        // living in the system image. This may be a valid request - if the app wasn't compiled,
518        // e.g., if the system image wasn't large enough to include preopted files. However, the
519        // data we have is from the old system, so the driver (the OTA service) can't actually
520        // know. Thus, we will get requests for apps that have preopted components. To avoid
521        // duplication (we'd generate files that are not used and are *not* cleaned up), do two
522        // simple checks:
523        //
524        // 1) Does the apk_path start with the value of ANDROID_ROOT? (~in the system image)
525        //    (For simplicity, assume the value of ANDROID_ROOT does not contain a symlink.)
526        //
527        // 2) If you replace the name in the apk_path with "oat," does the path exist?
528        //    (=have a subdirectory for preopted files)
529        //
530        // If the answer to both is yes, skip the dexopt.
531        //
532        // Note: while one may think it's OK to call dexopt and it will fail (because APKs should
533        //       be stripped), that's not true for APKs signed outside the build system (so the
534        //       jar content must be exactly the same).
535
536        //       (This is ugly as it's the only thing where we need to understand the contents
537        //        of package_parameters_, but it beats postponing the decision or using the call-
538        //        backs to do weird things.)
539        constexpr size_t kApkPathIndex = 0;
540        CHECK_GT(DEXOPT_PARAM_COUNT, kApkPathIndex);
541        CHECK(package_parameters_[kApkPathIndex] != nullptr);
542        if (StartsWith(package_parameters_[kApkPathIndex], android_root_.c_str())) {
543            const char* last_slash = strrchr(package_parameters_[kApkPathIndex], '/');
544            if (last_slash != nullptr) {
545                std::string path(package_parameters_[kApkPathIndex],
546                                 last_slash - package_parameters_[kApkPathIndex] + 1);
547                CHECK(EndsWith(path, "/"));
548                path = path + "oat";
549                if (access(path.c_str(), F_OK) == 0) {
550                    return true;
551                }
552            }
553        }
554
555        // Another issue is unavailability of files in the new system. If the partition
556        // layout changes, otapreopt_chroot may not know about this. Then files from that
557        // partition will not be available and fail to build. This is problematic, as
558        // this tool will wipe the OTA artifact cache and try again (for robustness after
559        // a failed OTA with remaining cache artifacts).
560        if (access(package_parameters_[kApkPathIndex], F_OK) != 0) {
561            LOG(WARNING) << "Skipping preopt of non-existing package "
562                         << package_parameters_[kApkPathIndex];
563            return true;
564        }
565
566        return false;
567    }
568
569    int RunPreopt() {
570        if (ShouldSkipPreopt()) {
571            return 0;
572        }
573
574        int dexopt_result = dexopt(package_parameters_);
575        if (dexopt_result == 0) {
576            return 0;
577        }
578
579        // If the dexopt failed, we may have a stale boot image from a previous OTA run.
580        // Then regenerate and retry.
581        if (WEXITSTATUS(dexopt_result) !=
582                static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
583            return dexopt_result;
584        }
585
586        if (!PrepareBootImage(/* force */ true)) {
587            LOG(ERROR) << "Forced boot image creating failed. Original error return was "
588                         << dexopt_result;
589            return dexopt_result;
590        }
591
592        LOG(WARNING) << "Original dexopt failed, re-trying after boot image was regenerated.";
593        return dexopt(package_parameters_);
594    }
595
596    ////////////////////////////////////
597    // Helpers, mostly taken from ART //
598    ////////////////////////////////////
599
600    // Wrapper on fork/execv to run a command in a subprocess.
601    static bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) {
602        const std::string command_line = Join(arg_vector, ' ');
603
604        CHECK_GE(arg_vector.size(), 1U) << command_line;
605
606        // Convert the args to char pointers.
607        const char* program = arg_vector[0].c_str();
608        std::vector<char*> args;
609        for (size_t i = 0; i < arg_vector.size(); ++i) {
610            const std::string& arg = arg_vector[i];
611            char* arg_str = const_cast<char*>(arg.c_str());
612            CHECK(arg_str != nullptr) << i;
613            args.push_back(arg_str);
614        }
615        args.push_back(nullptr);
616
617        // Fork and exec.
618        pid_t pid = fork();
619        if (pid == 0) {
620            // No allocation allowed between fork and exec.
621
622            // Change process groups, so we don't get reaped by ProcessManager.
623            setpgid(0, 0);
624
625            execv(program, &args[0]);
626
627            PLOG(ERROR) << "Failed to execv(" << command_line << ")";
628            // _exit to avoid atexit handlers in child.
629            _exit(1);
630        } else {
631            if (pid == -1) {
632                *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
633                        command_line.c_str(), strerror(errno));
634                return false;
635            }
636
637            // wait for subprocess to finish
638            int status;
639            pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
640            if (got_pid != pid) {
641                *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
642                        "wanted %d, got %d: %s",
643                        command_line.c_str(), pid, got_pid, strerror(errno));
644                return false;
645            }
646            if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
647                *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
648                        command_line.c_str());
649                return false;
650            }
651        }
652        return true;
653    }
654
655    // Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc.
656    static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
657        constexpr size_t kPageSize = PAGE_SIZE;
658        CHECK_EQ(min_delta % kPageSize, 0u);
659        CHECK_EQ(max_delta % kPageSize, 0u);
660        CHECK_LT(min_delta, max_delta);
661
662        std::default_random_engine generator;
663        generator.seed(GetSeed());
664        std::uniform_int_distribution<int32_t> distribution(min_delta, max_delta);
665        int32_t r = distribution(generator);
666        if (r % 2 == 0) {
667            r = RoundUp(r, kPageSize);
668        } else {
669            r = RoundDown(r, kPageSize);
670        }
671        CHECK_LE(min_delta, r);
672        CHECK_GE(max_delta, r);
673        CHECK_EQ(r % kPageSize, 0u);
674        return r;
675    }
676
677    static uint64_t GetSeed() {
678#ifdef __BIONIC__
679        // Bionic exposes arc4random, use it.
680        uint64_t random_data;
681        arc4random_buf(&random_data, sizeof(random_data));
682        return random_data;
683#else
684#error "This is only supposed to run with bionic. Otherwise, implement..."
685#endif
686    }
687
688    void AddCompilerOptionFromSystemProperty(const char* system_property,
689            const char* prefix,
690            bool runtime,
691            std::vector<std::string>& out) const {
692        const std::string* value = system_properties_.GetProperty(system_property);
693        if (value != nullptr) {
694            if (runtime) {
695                out.push_back("--runtime-arg");
696            }
697            if (prefix != nullptr) {
698                out.push_back(StringPrintf("%s%s", prefix, value->c_str()));
699            } else {
700                out.push_back(*value);
701            }
702        }
703    }
704
705    static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH";
706    static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT";
707    static constexpr const char* kAndroidDataPathPropertyName = "ANDROID_DATA";
708    // The index of the instruction-set string inside the package parameters. Needed for
709    // some special-casing that requires knowledge of the instruction-set.
710    static constexpr size_t kISAIndex = 3;
711
712    // Stores the system properties read out of the B partition. We need to use these properties
713    // to compile, instead of the A properties we could get from init/get_property.
714    SystemProperties system_properties_;
715
716    // Some select properties that are always needed.
717    std::string target_slot_;
718    std::string android_root_;
719    std::string android_data_;
720    std::string boot_classpath_;
721    std::string asec_mountpoint_;
722
723    const char* package_parameters_[DEXOPT_PARAM_COUNT];
724
725    // Store environment values we need to set.
726    std::vector<std::string> environ_;
727};
728
729OTAPreoptService gOps;
730
731////////////////////////
732// Plug-in functions. //
733////////////////////////
734
735int get_property(const char *key, char *value, const char *default_value) {
736    return gOps.GetProperty(key, value, default_value);
737}
738
739// Compute the output path of
740bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir,
741                             const char *apk_path,
742                             const char *instruction_set) {
743    const char *file_name_start;
744    const char *file_name_end;
745
746    file_name_start = strrchr(apk_path, '/');
747    if (file_name_start == nullptr) {
748        ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
749        return false;
750    }
751    file_name_end = strrchr(file_name_start, '.');
752    if (file_name_end == nullptr) {
753        ALOGE("apk_path '%s' has no extension\n", apk_path);
754        return false;
755    }
756
757    // Calculate file_name
758    file_name_start++;  // Move past '/', is valid as file_name_end is valid.
759    size_t file_name_len = file_name_end - file_name_start;
760    std::string file_name(file_name_start, file_name_len);
761
762    // <apk_parent_dir>/oat/<isa>/<file_name>.odex.b
763    snprintf(path,
764             PKG_PATH_MAX,
765             "%s/%s/%s.odex.%s",
766             oat_dir,
767             instruction_set,
768             file_name.c_str(),
769             gOps.GetTargetSlot().c_str());
770    return true;
771}
772
773/*
774 * Computes the odex file for the given apk_path and instruction_set.
775 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
776 *
777 * Returns false if it failed to determine the odex file path.
778 */
779bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
780                              const char *instruction_set) {
781    const char *path_end = strrchr(apk_path, '/');
782    if (path_end == nullptr) {
783        ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
784        return false;
785    }
786    std::string path_component(apk_path, path_end - apk_path);
787
788    const char *name_begin = path_end + 1;
789    const char *extension_start = strrchr(name_begin, '.');
790    if (extension_start == nullptr) {
791        ALOGE("apk_path '%s' has no extension.\n", apk_path);
792        return false;
793    }
794    std::string name_component(name_begin, extension_start - name_begin);
795
796    std::string new_path = StringPrintf("%s/oat/%s/%s.odex.%s",
797                                        path_component.c_str(),
798                                        instruction_set,
799                                        name_component.c_str(),
800                                        gOps.GetTargetSlot().c_str());
801    if (new_path.length() >= PKG_PATH_MAX) {
802        LOG(ERROR) << "apk_path of " << apk_path << " is too long: " << new_path;
803        return false;
804    }
805    strcpy(path, new_path.c_str());
806    return true;
807}
808
809bool create_cache_path(char path[PKG_PATH_MAX],
810                       const char *src,
811                       const char *instruction_set) {
812    size_t srclen = strlen(src);
813
814        /* demand that we are an absolute path */
815    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
816        return false;
817    }
818
819    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
820        return false;
821    }
822
823    std::string from_src = std::string(src + 1);
824    std::replace(from_src.begin(), from_src.end(), '/', '@');
825
826    std::string assembled_path = StringPrintf("%s/%s/%s/%s%s",
827                                              gOps.GetOTADataDirectory().c_str(),
828                                              DALVIK_CACHE,
829                                              instruction_set,
830                                              from_src.c_str(),
831                                              DALVIK_CACHE_POSTFIX);
832
833    if (assembled_path.length() + 1 > PKG_PATH_MAX) {
834        return false;
835    }
836    strcpy(path, assembled_path.c_str());
837
838    return true;
839}
840
841static int log_callback(int type, const char *fmt, ...) {
842    va_list ap;
843    int priority;
844
845    switch (type) {
846        case SELINUX_WARNING:
847            priority = ANDROID_LOG_WARN;
848            break;
849        case SELINUX_INFO:
850            priority = ANDROID_LOG_INFO;
851            break;
852        default:
853            priority = ANDROID_LOG_ERROR;
854            break;
855    }
856    va_start(ap, fmt);
857    LOG_PRI_VA(priority, "SELinux", fmt, ap);
858    va_end(ap);
859    return 0;
860}
861
862static int otapreopt_main(const int argc, char *argv[]) {
863    int selinux_enabled = (is_selinux_enabled() > 0);
864
865    setenv("ANDROID_LOG_TAGS", "*:v", 1);
866    android::base::InitLogging(argv);
867
868    if (argc < 2) {
869        ALOGE("Expecting parameters");
870        exit(1);
871    }
872
873    union selinux_callback cb;
874    cb.func_log = log_callback;
875    selinux_set_callback(SELINUX_CB_LOG, cb);
876
877    if (selinux_enabled && selinux_status_open(true) < 0) {
878        ALOGE("Could not open selinux status; exiting.\n");
879        exit(1);
880    }
881
882    int ret = android::installd::gOps.Main(argc, argv);
883
884    return ret;
885}
886
887}  // namespace installd
888}  // namespace android
889
890int main(const int argc, char *argv[]) {
891    return android::installd::otapreopt_main(argc, argv);
892}
893