xref: /aosp_15_r20/frameworks/native/cmds/installd/otapreopt.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  ** Copyright 2016, The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  **
4*38e8c45fSAndroid Build Coastguard Worker  ** Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  ** you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  ** You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  **
8*38e8c45fSAndroid Build Coastguard Worker  **     http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  **
10*38e8c45fSAndroid Build Coastguard Worker  ** Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  ** distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  ** See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  ** limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
18*38e8c45fSAndroid Build Coastguard Worker #include <selinux/android.h>
19*38e8c45fSAndroid Build Coastguard Worker #include <selinux/avc.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <stdlib.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <string.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <sys/capability.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <sys/mman.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <sys/prctl.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <sys/stat.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <sys/wait.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <algorithm>
28*38e8c45fSAndroid Build Coastguard Worker #include <iterator>
29*38e8c45fSAndroid Build Coastguard Worker #include <limits>
30*38e8c45fSAndroid Build Coastguard Worker #include <random>
31*38e8c45fSAndroid Build Coastguard Worker #include <regex>
32*38e8c45fSAndroid Build Coastguard Worker 
33*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
34*38e8c45fSAndroid Build Coastguard Worker #include <android-base/macros.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <android-base/strings.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <cutils/fs.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
39*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
40*38e8c45fSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
41*38e8c45fSAndroid Build Coastguard Worker 
42*38e8c45fSAndroid Build Coastguard Worker #include "android-base/file.h"
43*38e8c45fSAndroid Build Coastguard Worker #include "dexopt.h"
44*38e8c45fSAndroid Build Coastguard Worker #include "file_parsing.h"
45*38e8c45fSAndroid Build Coastguard Worker #include "globals.h"
46*38e8c45fSAndroid Build Coastguard Worker #include "installd_constants.h"
47*38e8c45fSAndroid Build Coastguard Worker #include "installd_deps.h"  // Need to fill in requirements of commands.
48*38e8c45fSAndroid Build Coastguard Worker #include "otapreopt_parameters.h"
49*38e8c45fSAndroid Build Coastguard Worker #include "otapreopt_utils.h"
50*38e8c45fSAndroid Build Coastguard Worker #include "system_properties.h"
51*38e8c45fSAndroid Build Coastguard Worker #include "unique_file.h"
52*38e8c45fSAndroid Build Coastguard Worker #include "utils.h"
53*38e8c45fSAndroid Build Coastguard Worker 
54*38e8c45fSAndroid Build Coastguard Worker #ifndef LOG_TAG
55*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "otapreopt"
56*38e8c45fSAndroid Build Coastguard Worker #endif
57*38e8c45fSAndroid Build Coastguard Worker 
58*38e8c45fSAndroid Build Coastguard Worker #define BUFFER_MAX    1024  /* input buffer for commands */
59*38e8c45fSAndroid Build Coastguard Worker #define TOKEN_MAX     16    /* max number of arguments in buffer */
60*38e8c45fSAndroid Build Coastguard Worker #define REPLY_MAX     256   /* largest reply allowed */
61*38e8c45fSAndroid Build Coastguard Worker 
62*38e8c45fSAndroid Build Coastguard Worker using android::base::EndsWith;
63*38e8c45fSAndroid Build Coastguard Worker using android::base::Split;
64*38e8c45fSAndroid Build Coastguard Worker using android::base::StartsWith;
65*38e8c45fSAndroid Build Coastguard Worker using android::base::StringPrintf;
66*38e8c45fSAndroid Build Coastguard Worker 
67*38e8c45fSAndroid Build Coastguard Worker namespace android {
68*38e8c45fSAndroid Build Coastguard Worker namespace installd {
69*38e8c45fSAndroid Build Coastguard Worker 
70*38e8c45fSAndroid Build Coastguard Worker // Check expected values for dexopt flags. If you need to change this:
71*38e8c45fSAndroid Build Coastguard Worker //
72*38e8c45fSAndroid Build Coastguard Worker //   RUN AN A/B OTA TO MAKE SURE THINGS STILL WORK!
73*38e8c45fSAndroid Build Coastguard Worker //
74*38e8c45fSAndroid Build Coastguard Worker // You most likely need to increase the protocol version and all that entails!
75*38e8c45fSAndroid Build Coastguard Worker 
76*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_PUBLIC         == 1 << 1, "DEXOPT_PUBLIC unexpected.");
77*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_DEBUGGABLE     == 1 << 2, "DEXOPT_DEBUGGABLE unexpected.");
78*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_BOOTCOMPLETE   == 1 << 3, "DEXOPT_BOOTCOMPLETE unexpected.");
79*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_PROFILE_GUIDED == 1 << 4, "DEXOPT_PROFILE_GUIDED unexpected.");
80*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_SECONDARY_DEX  == 1 << 5, "DEXOPT_SECONDARY_DEX unexpected.");
81*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_FORCE          == 1 << 6, "DEXOPT_FORCE unexpected.");
82*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_STORAGE_CE     == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
83*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_STORAGE_DE     == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
84*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_ENABLE_HIDDEN_API_CHECKS == 1 << 10,
85*38e8c45fSAndroid Build Coastguard Worker         "DEXOPT_ENABLE_HIDDEN_API_CHECKS unexpected");
86*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_GENERATE_COMPACT_DEX == 1 << 11, "DEXOPT_GENERATE_COMPACT_DEX unexpected");
87*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_GENERATE_APP_IMAGE == 1 << 12, "DEXOPT_GENERATE_APP_IMAGE unexpected");
88*38e8c45fSAndroid Build Coastguard Worker 
89*38e8c45fSAndroid Build Coastguard Worker static_assert(DEXOPT_MASK           == (0x3dfe | DEXOPT_IDLE_BACKGROUND_JOB),
90*38e8c45fSAndroid Build Coastguard Worker               "DEXOPT_MASK unexpected.");
91*38e8c45fSAndroid Build Coastguard Worker 
92*38e8c45fSAndroid Build Coastguard Worker constexpr const char* kAotCompilerFilters[]{
93*38e8c45fSAndroid Build Coastguard Worker         "space-profile", "space", "speed-profile", "speed", "everything-profile", "everything",
94*38e8c45fSAndroid Build Coastguard Worker };
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker template<typename T>
IsPowerOfTwo(T x)97*38e8c45fSAndroid Build Coastguard Worker static constexpr bool IsPowerOfTwo(T x) {
98*38e8c45fSAndroid Build Coastguard Worker   static_assert(std::is_integral<T>::value, "T must be integral");
99*38e8c45fSAndroid Build Coastguard Worker   // TODO: assert unsigned. There is currently many uses with signed values.
100*38e8c45fSAndroid Build Coastguard Worker   return (x & (x - 1)) == 0;
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker 
103*38e8c45fSAndroid Build Coastguard Worker template<typename T>
RoundDown(T x,typename std::decay<T>::type n)104*38e8c45fSAndroid Build Coastguard Worker static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
105*38e8c45fSAndroid Build Coastguard Worker     return (x & -n);
106*38e8c45fSAndroid Build Coastguard Worker }
107*38e8c45fSAndroid Build Coastguard Worker 
108*38e8c45fSAndroid Build Coastguard Worker template<typename T>
RoundUp(T x,typename std::remove_reference<T>::type n)109*38e8c45fSAndroid Build Coastguard Worker static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
110*38e8c45fSAndroid Build Coastguard Worker     return RoundDown(x + n - 1, n);
111*38e8c45fSAndroid Build Coastguard Worker }
112*38e8c45fSAndroid Build Coastguard Worker 
113*38e8c45fSAndroid Build Coastguard Worker class OTAPreoptService {
114*38e8c45fSAndroid Build Coastguard Worker  public:
115*38e8c45fSAndroid Build Coastguard Worker     // Main driver. Performs the following steps.
116*38e8c45fSAndroid Build Coastguard Worker     //
117*38e8c45fSAndroid Build Coastguard Worker     // 1) Parse options (read system properties etc from B partition).
118*38e8c45fSAndroid Build Coastguard Worker     //
119*38e8c45fSAndroid Build Coastguard Worker     // 2) Read in package data.
120*38e8c45fSAndroid Build Coastguard Worker     //
121*38e8c45fSAndroid Build Coastguard Worker     // 3) Prepare environment variables.
122*38e8c45fSAndroid Build Coastguard Worker     //
123*38e8c45fSAndroid Build Coastguard Worker     // 4) Prepare(compile) boot image, if necessary.
124*38e8c45fSAndroid Build Coastguard Worker     //
125*38e8c45fSAndroid Build Coastguard Worker     // 5) Run update.
Main(int argc,char ** argv)126*38e8c45fSAndroid Build Coastguard Worker     int Main(int argc, char** argv) {
127*38e8c45fSAndroid Build Coastguard Worker         if (!ReadArguments(argc, argv)) {
128*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Failed reading command line.";
129*38e8c45fSAndroid Build Coastguard Worker             return 1;
130*38e8c45fSAndroid Build Coastguard Worker         }
131*38e8c45fSAndroid Build Coastguard Worker 
132*38e8c45fSAndroid Build Coastguard Worker         if (!ReadSystemProperties()) {
133*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR)<< "Failed reading system properties.";
134*38e8c45fSAndroid Build Coastguard Worker             return 2;
135*38e8c45fSAndroid Build Coastguard Worker         }
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker         if (!ReadEnvironment()) {
138*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Failed reading environment properties.";
139*38e8c45fSAndroid Build Coastguard Worker             return 3;
140*38e8c45fSAndroid Build Coastguard Worker         }
141*38e8c45fSAndroid Build Coastguard Worker 
142*38e8c45fSAndroid Build Coastguard Worker         if (!CheckAndInitializeInstalldGlobals()) {
143*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Failed initializing globals.";
144*38e8c45fSAndroid Build Coastguard Worker             return 4;
145*38e8c45fSAndroid Build Coastguard Worker         }
146*38e8c45fSAndroid Build Coastguard Worker 
147*38e8c45fSAndroid Build Coastguard Worker         PrepareEnvironmentVariables();
148*38e8c45fSAndroid Build Coastguard Worker 
149*38e8c45fSAndroid Build Coastguard Worker         if (!EnsureDalvikCache()) {
150*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Bad dalvik cache.";
151*38e8c45fSAndroid Build Coastguard Worker             return 5;
152*38e8c45fSAndroid Build Coastguard Worker         }
153*38e8c45fSAndroid Build Coastguard Worker 
154*38e8c45fSAndroid Build Coastguard Worker         int dexopt_retcode = RunPreopt();
155*38e8c45fSAndroid Build Coastguard Worker 
156*38e8c45fSAndroid Build Coastguard Worker         return dexopt_retcode;
157*38e8c45fSAndroid Build Coastguard Worker     }
158*38e8c45fSAndroid Build Coastguard Worker 
GetProperty(const char * key,char * value,const char * default_value) const159*38e8c45fSAndroid Build Coastguard Worker     int GetProperty(const char* key, char* value, const char* default_value) const {
160*38e8c45fSAndroid Build Coastguard Worker         const std::string* prop_value = system_properties_.GetProperty(key);
161*38e8c45fSAndroid Build Coastguard Worker         if (prop_value == nullptr) {
162*38e8c45fSAndroid Build Coastguard Worker             if (default_value == nullptr) {
163*38e8c45fSAndroid Build Coastguard Worker                 return 0;
164*38e8c45fSAndroid Build Coastguard Worker             }
165*38e8c45fSAndroid Build Coastguard Worker             // Copy in the default value.
166*38e8c45fSAndroid Build Coastguard Worker             strlcpy(value, default_value, kPropertyValueMax - 1);
167*38e8c45fSAndroid Build Coastguard Worker             value[kPropertyValueMax - 1] = 0;
168*38e8c45fSAndroid Build Coastguard Worker             return strlen(default_value);// TODO: Need to truncate?
169*38e8c45fSAndroid Build Coastguard Worker         }
170*38e8c45fSAndroid Build Coastguard Worker         size_t size = std::min(kPropertyValueMax - 1, prop_value->length()) + 1;
171*38e8c45fSAndroid Build Coastguard Worker         strlcpy(value, prop_value->data(), size);
172*38e8c45fSAndroid Build Coastguard Worker         return static_cast<int>(size - 1);
173*38e8c45fSAndroid Build Coastguard Worker     }
174*38e8c45fSAndroid Build Coastguard Worker 
GetOTADataDirectory() const175*38e8c45fSAndroid Build Coastguard Worker     std::string GetOTADataDirectory() const {
176*38e8c45fSAndroid Build Coastguard Worker         return StringPrintf("%s/%s", GetOtaDirectoryPrefix().c_str(), GetTargetSlot().c_str());
177*38e8c45fSAndroid Build Coastguard Worker     }
178*38e8c45fSAndroid Build Coastguard Worker 
GetTargetSlot() const179*38e8c45fSAndroid Build Coastguard Worker     const std::string& GetTargetSlot() const {
180*38e8c45fSAndroid Build Coastguard Worker         return parameters_.target_slot;
181*38e8c45fSAndroid Build Coastguard Worker     }
182*38e8c45fSAndroid Build Coastguard Worker 
183*38e8c45fSAndroid Build Coastguard Worker private:
184*38e8c45fSAndroid Build Coastguard Worker 
ReadSystemProperties()185*38e8c45fSAndroid Build Coastguard Worker     bool ReadSystemProperties() {
186*38e8c45fSAndroid Build Coastguard Worker         // TODO This file does not have a stable format. It should be read by
187*38e8c45fSAndroid Build Coastguard Worker         // code shared by init and otapreopt. See b/181182967#comment80
188*38e8c45fSAndroid Build Coastguard Worker         static constexpr const char* kPropertyFiles[] = {
189*38e8c45fSAndroid Build Coastguard Worker                 "/system/build.prop"
190*38e8c45fSAndroid Build Coastguard Worker         };
191*38e8c45fSAndroid Build Coastguard Worker 
192*38e8c45fSAndroid Build Coastguard Worker         for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
193*38e8c45fSAndroid Build Coastguard Worker             if (!system_properties_.Load(kPropertyFiles[i])) {
194*38e8c45fSAndroid Build Coastguard Worker                 return false;
195*38e8c45fSAndroid Build Coastguard Worker             }
196*38e8c45fSAndroid Build Coastguard Worker         }
197*38e8c45fSAndroid Build Coastguard Worker 
198*38e8c45fSAndroid Build Coastguard Worker         return true;
199*38e8c45fSAndroid Build Coastguard Worker     }
200*38e8c45fSAndroid Build Coastguard Worker 
ReadEnvironment()201*38e8c45fSAndroid Build Coastguard Worker     bool ReadEnvironment() {
202*38e8c45fSAndroid Build Coastguard Worker         // Parse the environment variables from init.environ.rc, which have the form
203*38e8c45fSAndroid Build Coastguard Worker         //   export NAME VALUE
204*38e8c45fSAndroid Build Coastguard Worker         // For simplicity, don't respect string quotation. The values we are interested in can be
205*38e8c45fSAndroid Build Coastguard Worker         // encoded without them.
206*38e8c45fSAndroid Build Coastguard Worker         //
207*38e8c45fSAndroid Build Coastguard Worker         // init.environ.rc and derive_classpath all have the same format for
208*38e8c45fSAndroid Build Coastguard Worker         // environment variable exports (since they are all meant to be read by
209*38e8c45fSAndroid Build Coastguard Worker         // init) and can be matched by the same regex.
210*38e8c45fSAndroid Build Coastguard Worker 
211*38e8c45fSAndroid Build Coastguard Worker         std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
212*38e8c45fSAndroid Build Coastguard Worker         auto parse_results = [&](auto& input) {
213*38e8c45fSAndroid Build Coastguard Worker           ParseFile(input, [&](const std::string& line) {
214*38e8c45fSAndroid Build Coastguard Worker               std::smatch export_match;
215*38e8c45fSAndroid Build Coastguard Worker               if (!std::regex_match(line, export_match, export_regex)) {
216*38e8c45fSAndroid Build Coastguard Worker                   return true;
217*38e8c45fSAndroid Build Coastguard Worker               }
218*38e8c45fSAndroid Build Coastguard Worker 
219*38e8c45fSAndroid Build Coastguard Worker               if (export_match.size() != 3) {
220*38e8c45fSAndroid Build Coastguard Worker                   return true;
221*38e8c45fSAndroid Build Coastguard Worker               }
222*38e8c45fSAndroid Build Coastguard Worker 
223*38e8c45fSAndroid Build Coastguard Worker               std::string name = export_match[1].str();
224*38e8c45fSAndroid Build Coastguard Worker               std::string value = export_match[2].str();
225*38e8c45fSAndroid Build Coastguard Worker 
226*38e8c45fSAndroid Build Coastguard Worker               system_properties_.SetProperty(name, value);
227*38e8c45fSAndroid Build Coastguard Worker 
228*38e8c45fSAndroid Build Coastguard Worker               return true;
229*38e8c45fSAndroid Build Coastguard Worker           });
230*38e8c45fSAndroid Build Coastguard Worker         };
231*38e8c45fSAndroid Build Coastguard Worker 
232*38e8c45fSAndroid Build Coastguard Worker         // TODO Just like with the system-properties above we really should have
233*38e8c45fSAndroid Build Coastguard Worker         // common code between init and otapreopt to deal with reading these
234*38e8c45fSAndroid Build Coastguard Worker         // things. See b/181182967
235*38e8c45fSAndroid Build Coastguard Worker         // There have been a variety of places the various env-vars have been
236*38e8c45fSAndroid Build Coastguard Worker         // over the years.  Expand or reduce this list as needed.
237*38e8c45fSAndroid Build Coastguard Worker         static constexpr const char* kEnvironmentVariableSources[] = {
238*38e8c45fSAndroid Build Coastguard Worker                 "/init.environ.rc",
239*38e8c45fSAndroid Build Coastguard Worker         };
240*38e8c45fSAndroid Build Coastguard Worker         // First get everything from the static files.
241*38e8c45fSAndroid Build Coastguard Worker         for (const char* env_vars_file : kEnvironmentVariableSources) {
242*38e8c45fSAndroid Build Coastguard Worker           parse_results(env_vars_file);
243*38e8c45fSAndroid Build Coastguard Worker         }
244*38e8c45fSAndroid Build Coastguard Worker 
245*38e8c45fSAndroid Build Coastguard Worker         // Next get everything from derive_classpath, since we're already in the
246*38e8c45fSAndroid Build Coastguard Worker         // chroot it will get the new versions of any dependencies.
247*38e8c45fSAndroid Build Coastguard Worker         {
248*38e8c45fSAndroid Build Coastguard Worker           android::base::unique_fd fd(memfd_create("derive_classpath_temp", MFD_CLOEXEC));
249*38e8c45fSAndroid Build Coastguard Worker           if (!fd.ok()) {
250*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Unable to create fd for derive_classpath";
251*38e8c45fSAndroid Build Coastguard Worker             return false;
252*38e8c45fSAndroid Build Coastguard Worker           }
253*38e8c45fSAndroid Build Coastguard Worker           std::string memfd_file = StringPrintf("/proc/%d/fd/%d", getpid(), fd.get());
254*38e8c45fSAndroid Build Coastguard Worker           std::string error_msg;
255*38e8c45fSAndroid Build Coastguard Worker           if (!Exec({"/apex/com.android.sdkext/bin/derive_classpath", memfd_file}, &error_msg)) {
256*38e8c45fSAndroid Build Coastguard Worker             PLOG(ERROR) << "Running derive_classpath failed: " << error_msg;
257*38e8c45fSAndroid Build Coastguard Worker             return false;
258*38e8c45fSAndroid Build Coastguard Worker           }
259*38e8c45fSAndroid Build Coastguard Worker           std::ifstream ifs(memfd_file);
260*38e8c45fSAndroid Build Coastguard Worker           parse_results(ifs);
261*38e8c45fSAndroid Build Coastguard Worker         }
262*38e8c45fSAndroid Build Coastguard Worker 
263*38e8c45fSAndroid Build Coastguard Worker         if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) {
264*38e8c45fSAndroid Build Coastguard Worker             return false;
265*38e8c45fSAndroid Build Coastguard Worker         }
266*38e8c45fSAndroid Build Coastguard Worker         android_data_ = *system_properties_.GetProperty(kAndroidDataPathPropertyName);
267*38e8c45fSAndroid Build Coastguard Worker 
268*38e8c45fSAndroid Build Coastguard Worker         if (system_properties_.GetProperty(kAndroidRootPathPropertyName) == nullptr) {
269*38e8c45fSAndroid Build Coastguard Worker             return false;
270*38e8c45fSAndroid Build Coastguard Worker         }
271*38e8c45fSAndroid Build Coastguard Worker         android_root_ = *system_properties_.GetProperty(kAndroidRootPathPropertyName);
272*38e8c45fSAndroid Build Coastguard Worker 
273*38e8c45fSAndroid Build Coastguard Worker         if (system_properties_.GetProperty(kBootClassPathPropertyName) == nullptr) {
274*38e8c45fSAndroid Build Coastguard Worker             return false;
275*38e8c45fSAndroid Build Coastguard Worker         }
276*38e8c45fSAndroid Build Coastguard Worker         boot_classpath_ = *system_properties_.GetProperty(kBootClassPathPropertyName);
277*38e8c45fSAndroid Build Coastguard Worker 
278*38e8c45fSAndroid Build Coastguard Worker         if (system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) == nullptr) {
279*38e8c45fSAndroid Build Coastguard Worker             return false;
280*38e8c45fSAndroid Build Coastguard Worker         }
281*38e8c45fSAndroid Build Coastguard Worker         asec_mountpoint_ = *system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME);
282*38e8c45fSAndroid Build Coastguard Worker 
283*38e8c45fSAndroid Build Coastguard Worker         return true;
284*38e8c45fSAndroid Build Coastguard Worker     }
285*38e8c45fSAndroid Build Coastguard Worker 
GetAndroidData() const286*38e8c45fSAndroid Build Coastguard Worker     const std::string& GetAndroidData() const {
287*38e8c45fSAndroid Build Coastguard Worker         return android_data_;
288*38e8c45fSAndroid Build Coastguard Worker     }
289*38e8c45fSAndroid Build Coastguard Worker 
GetAndroidRoot() const290*38e8c45fSAndroid Build Coastguard Worker     const std::string& GetAndroidRoot() const {
291*38e8c45fSAndroid Build Coastguard Worker         return android_root_;
292*38e8c45fSAndroid Build Coastguard Worker     }
293*38e8c45fSAndroid Build Coastguard Worker 
GetOtaDirectoryPrefix() const294*38e8c45fSAndroid Build Coastguard Worker     const std::string GetOtaDirectoryPrefix() const {
295*38e8c45fSAndroid Build Coastguard Worker         return GetAndroidData() + "/ota";
296*38e8c45fSAndroid Build Coastguard Worker     }
297*38e8c45fSAndroid Build Coastguard Worker 
CheckAndInitializeInstalldGlobals()298*38e8c45fSAndroid Build Coastguard Worker     bool CheckAndInitializeInstalldGlobals() {
299*38e8c45fSAndroid Build Coastguard Worker         // init_globals_from_data_and_root requires "ASEC_MOUNTPOINT" in the environment. We
300*38e8c45fSAndroid Build Coastguard Worker         // do not use any datapath that includes this, but we'll still have to set it.
301*38e8c45fSAndroid Build Coastguard Worker         CHECK(system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) != nullptr);
302*38e8c45fSAndroid Build Coastguard Worker         int result = setenv(ASEC_MOUNTPOINT_ENV_NAME, asec_mountpoint_.c_str(), 0);
303*38e8c45fSAndroid Build Coastguard Worker         if (result != 0) {
304*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Could not set ASEC_MOUNTPOINT environment variable";
305*38e8c45fSAndroid Build Coastguard Worker             return false;
306*38e8c45fSAndroid Build Coastguard Worker         }
307*38e8c45fSAndroid Build Coastguard Worker 
308*38e8c45fSAndroid Build Coastguard Worker         if (!init_globals_from_data_and_root(GetAndroidData().c_str(), GetAndroidRoot().c_str())) {
309*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Could not initialize globals; exiting.";
310*38e8c45fSAndroid Build Coastguard Worker             return false;
311*38e8c45fSAndroid Build Coastguard Worker         }
312*38e8c45fSAndroid Build Coastguard Worker 
313*38e8c45fSAndroid Build Coastguard Worker         // This is different from the normal installd. We only do the base
314*38e8c45fSAndroid Build Coastguard Worker         // directory, the rest will be created on demand when each app is compiled.
315*38e8c45fSAndroid Build Coastguard Worker         if (access(GetOtaDirectoryPrefix().c_str(), R_OK) < 0) {
316*38e8c45fSAndroid Build Coastguard Worker             PLOG(ERROR) << "Could not access " << GetOtaDirectoryPrefix();
317*38e8c45fSAndroid Build Coastguard Worker             return false;
318*38e8c45fSAndroid Build Coastguard Worker         }
319*38e8c45fSAndroid Build Coastguard Worker 
320*38e8c45fSAndroid Build Coastguard Worker         return true;
321*38e8c45fSAndroid Build Coastguard Worker     }
322*38e8c45fSAndroid Build Coastguard Worker 
ParseBool(const char * in)323*38e8c45fSAndroid Build Coastguard Worker     bool ParseBool(const char* in) {
324*38e8c45fSAndroid Build Coastguard Worker         if (strcmp(in, "true") == 0) {
325*38e8c45fSAndroid Build Coastguard Worker             return true;
326*38e8c45fSAndroid Build Coastguard Worker         }
327*38e8c45fSAndroid Build Coastguard Worker         return false;
328*38e8c45fSAndroid Build Coastguard Worker     }
329*38e8c45fSAndroid Build Coastguard Worker 
ParseUInt(const char * in,uint32_t * out)330*38e8c45fSAndroid Build Coastguard Worker     bool ParseUInt(const char* in, uint32_t* out) {
331*38e8c45fSAndroid Build Coastguard Worker         char* end;
332*38e8c45fSAndroid Build Coastguard Worker         long long int result = strtoll(in, &end, 0);
333*38e8c45fSAndroid Build Coastguard Worker         if (in == end || *end != '\0') {
334*38e8c45fSAndroid Build Coastguard Worker             return false;
335*38e8c45fSAndroid Build Coastguard Worker         }
336*38e8c45fSAndroid Build Coastguard Worker         if (result < std::numeric_limits<uint32_t>::min() ||
337*38e8c45fSAndroid Build Coastguard Worker                 std::numeric_limits<uint32_t>::max() < result) {
338*38e8c45fSAndroid Build Coastguard Worker             return false;
339*38e8c45fSAndroid Build Coastguard Worker         }
340*38e8c45fSAndroid Build Coastguard Worker         *out = static_cast<uint32_t>(result);
341*38e8c45fSAndroid Build Coastguard Worker         return true;
342*38e8c45fSAndroid Build Coastguard Worker     }
343*38e8c45fSAndroid Build Coastguard Worker 
ReadArguments(int argc,char ** argv)344*38e8c45fSAndroid Build Coastguard Worker     bool ReadArguments(int argc, char** argv) {
345*38e8c45fSAndroid Build Coastguard Worker         return parameters_.ReadArguments(argc, const_cast<const char**>(argv));
346*38e8c45fSAndroid Build Coastguard Worker     }
347*38e8c45fSAndroid Build Coastguard Worker 
PrepareEnvironmentVariables()348*38e8c45fSAndroid Build Coastguard Worker     void PrepareEnvironmentVariables() {
349*38e8c45fSAndroid Build Coastguard Worker         environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_classpath_.c_str()));
350*38e8c45fSAndroid Build Coastguard Worker         environ_.push_back(StringPrintf("ANDROID_DATA=%s", GetOTADataDirectory().c_str()));
351*38e8c45fSAndroid Build Coastguard Worker         environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root_.c_str()));
352*38e8c45fSAndroid Build Coastguard Worker 
353*38e8c45fSAndroid Build Coastguard Worker         for (const std::string& e : environ_) {
354*38e8c45fSAndroid Build Coastguard Worker             putenv(const_cast<char*>(e.c_str()));
355*38e8c45fSAndroid Build Coastguard Worker         }
356*38e8c45fSAndroid Build Coastguard Worker     }
357*38e8c45fSAndroid Build Coastguard Worker 
358*38e8c45fSAndroid Build Coastguard Worker     // Ensure that we have the right cache file structures.
EnsureDalvikCache() const359*38e8c45fSAndroid Build Coastguard Worker     bool EnsureDalvikCache() const {
360*38e8c45fSAndroid Build Coastguard Worker         if (parameters_.instruction_set == nullptr) {
361*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "Instruction set missing.";
362*38e8c45fSAndroid Build Coastguard Worker             return false;
363*38e8c45fSAndroid Build Coastguard Worker         }
364*38e8c45fSAndroid Build Coastguard Worker         const char* isa = parameters_.instruction_set;
365*38e8c45fSAndroid Build Coastguard Worker         std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
366*38e8c45fSAndroid Build Coastguard Worker         std::string isa_path = dalvik_cache + "/" + isa;
367*38e8c45fSAndroid Build Coastguard Worker 
368*38e8c45fSAndroid Build Coastguard Worker         // Reset umask in otapreopt, so that we control the the access for the files we create.
369*38e8c45fSAndroid Build Coastguard Worker         umask(0);
370*38e8c45fSAndroid Build Coastguard Worker 
371*38e8c45fSAndroid Build Coastguard Worker         // Create the directories, if necessary.
372*38e8c45fSAndroid Build Coastguard Worker         if (access(dalvik_cache.c_str(), F_OK) != 0) {
373*38e8c45fSAndroid Build Coastguard Worker             if (!CreatePath(dalvik_cache)) {
374*38e8c45fSAndroid Build Coastguard Worker                 PLOG(ERROR) << "Could not create dalvik-cache dir " << dalvik_cache;
375*38e8c45fSAndroid Build Coastguard Worker                 return false;
376*38e8c45fSAndroid Build Coastguard Worker             }
377*38e8c45fSAndroid Build Coastguard Worker         }
378*38e8c45fSAndroid Build Coastguard Worker         if (access(isa_path.c_str(), F_OK) != 0) {
379*38e8c45fSAndroid Build Coastguard Worker             if (!CreatePath(isa_path)) {
380*38e8c45fSAndroid Build Coastguard Worker                 PLOG(ERROR) << "Could not create dalvik-cache isa dir";
381*38e8c45fSAndroid Build Coastguard Worker                 return false;
382*38e8c45fSAndroid Build Coastguard Worker             }
383*38e8c45fSAndroid Build Coastguard Worker         }
384*38e8c45fSAndroid Build Coastguard Worker 
385*38e8c45fSAndroid Build Coastguard Worker         return true;
386*38e8c45fSAndroid Build Coastguard Worker     }
387*38e8c45fSAndroid Build Coastguard Worker 
CreatePath(const std::string & path)388*38e8c45fSAndroid Build Coastguard Worker     static bool CreatePath(const std::string& path) {
389*38e8c45fSAndroid Build Coastguard Worker         // Create the given path. Use string processing instead of dirname, as dirname's need for
390*38e8c45fSAndroid Build Coastguard Worker         // a writable char buffer is painful.
391*38e8c45fSAndroid Build Coastguard Worker 
392*38e8c45fSAndroid Build Coastguard Worker         // First, try to use the full path.
393*38e8c45fSAndroid Build Coastguard Worker         if (mkdir(path.c_str(), 0711) == 0) {
394*38e8c45fSAndroid Build Coastguard Worker             return true;
395*38e8c45fSAndroid Build Coastguard Worker         }
396*38e8c45fSAndroid Build Coastguard Worker         if (errno != ENOENT) {
397*38e8c45fSAndroid Build Coastguard Worker             PLOG(ERROR) << "Could not create path " << path;
398*38e8c45fSAndroid Build Coastguard Worker             return false;
399*38e8c45fSAndroid Build Coastguard Worker         }
400*38e8c45fSAndroid Build Coastguard Worker 
401*38e8c45fSAndroid Build Coastguard Worker         // Now find the parent and try that first.
402*38e8c45fSAndroid Build Coastguard Worker         size_t last_slash = path.find_last_of('/');
403*38e8c45fSAndroid Build Coastguard Worker         if (last_slash == std::string::npos || last_slash == 0) {
404*38e8c45fSAndroid Build Coastguard Worker             PLOG(ERROR) << "Could not create " << path;
405*38e8c45fSAndroid Build Coastguard Worker             return false;
406*38e8c45fSAndroid Build Coastguard Worker         }
407*38e8c45fSAndroid Build Coastguard Worker 
408*38e8c45fSAndroid Build Coastguard Worker         if (!CreatePath(path.substr(0, last_slash))) {
409*38e8c45fSAndroid Build Coastguard Worker             return false;
410*38e8c45fSAndroid Build Coastguard Worker         }
411*38e8c45fSAndroid Build Coastguard Worker 
412*38e8c45fSAndroid Build Coastguard Worker         if (mkdir(path.c_str(), 0711) == 0) {
413*38e8c45fSAndroid Build Coastguard Worker             return true;
414*38e8c45fSAndroid Build Coastguard Worker         }
415*38e8c45fSAndroid Build Coastguard Worker         PLOG(ERROR) << "Could not create " << path;
416*38e8c45fSAndroid Build Coastguard Worker         return false;
417*38e8c45fSAndroid Build Coastguard Worker     }
418*38e8c45fSAndroid Build Coastguard Worker 
ParseNull(const char * arg)419*38e8c45fSAndroid Build Coastguard Worker     static const char* ParseNull(const char* arg) {
420*38e8c45fSAndroid Build Coastguard Worker         return (strcmp(arg, "!") == 0) ? nullptr : arg;
421*38e8c45fSAndroid Build Coastguard Worker     }
422*38e8c45fSAndroid Build Coastguard Worker 
IsAotCompilation() const423*38e8c45fSAndroid Build Coastguard Worker     bool IsAotCompilation() const {
424*38e8c45fSAndroid Build Coastguard Worker         if (std::find(std::begin(kAotCompilerFilters), std::end(kAotCompilerFilters),
425*38e8c45fSAndroid Build Coastguard Worker                       std::string_view(parameters_.compiler_filter)) ==
426*38e8c45fSAndroid Build Coastguard Worker             std::end(kAotCompilerFilters)) {
427*38e8c45fSAndroid Build Coastguard Worker             return false;
428*38e8c45fSAndroid Build Coastguard Worker         }
429*38e8c45fSAndroid Build Coastguard Worker 
430*38e8c45fSAndroid Build Coastguard Worker         int dexopt_flags = parameters_.dexopt_flags;
431*38e8c45fSAndroid Build Coastguard Worker         bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
432*38e8c45fSAndroid Build Coastguard Worker         bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
433*38e8c45fSAndroid Build Coastguard Worker         bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
434*38e8c45fSAndroid Build Coastguard Worker 
435*38e8c45fSAndroid Build Coastguard Worker         if (profile_guided) {
436*38e8c45fSAndroid Build Coastguard Worker             UniqueFile reference_profile =
437*38e8c45fSAndroid Build Coastguard Worker                     maybe_open_reference_profile(parameters_.pkgName, parameters_.apk_path,
438*38e8c45fSAndroid Build Coastguard Worker                                                  parameters_.profile_name, profile_guided,
439*38e8c45fSAndroid Build Coastguard Worker                                                  is_public, parameters_.uid, is_secondary_dex);
440*38e8c45fSAndroid Build Coastguard Worker             // `maybe_open_reference_profile` installs a hook that clears the profile on
441*38e8c45fSAndroid Build Coastguard Worker             // destruction. Disable it.
442*38e8c45fSAndroid Build Coastguard Worker             reference_profile.DisableCleanup();
443*38e8c45fSAndroid Build Coastguard Worker             struct stat sbuf;
444*38e8c45fSAndroid Build Coastguard Worker             if (reference_profile.fd() == -1 ||
445*38e8c45fSAndroid Build Coastguard Worker                 (fstat(reference_profile.fd(), &sbuf) != -1 && sbuf.st_size == 0)) {
446*38e8c45fSAndroid Build Coastguard Worker                 return false;
447*38e8c45fSAndroid Build Coastguard Worker             }
448*38e8c45fSAndroid Build Coastguard Worker         }
449*38e8c45fSAndroid Build Coastguard Worker 
450*38e8c45fSAndroid Build Coastguard Worker         return true;
451*38e8c45fSAndroid Build Coastguard Worker     }
452*38e8c45fSAndroid Build Coastguard Worker 
ShouldSkipPreopt() const453*38e8c45fSAndroid Build Coastguard Worker     bool ShouldSkipPreopt() const {
454*38e8c45fSAndroid Build Coastguard Worker         // There's one thing we have to be careful about: we may/will be asked to compile an app
455*38e8c45fSAndroid Build Coastguard Worker         // living in the system image. This may be a valid request - if the app wasn't compiled,
456*38e8c45fSAndroid Build Coastguard Worker         // e.g., if the system image wasn't large enough to include preopted files. However, the
457*38e8c45fSAndroid Build Coastguard Worker         // data we have is from the old system, so the driver (the OTA service) can't actually
458*38e8c45fSAndroid Build Coastguard Worker         // know. Thus, we will get requests for apps that have preopted components. To avoid
459*38e8c45fSAndroid Build Coastguard Worker         // duplication (we'd generate files that are not used and are *not* cleaned up), do two
460*38e8c45fSAndroid Build Coastguard Worker         // simple checks:
461*38e8c45fSAndroid Build Coastguard Worker         //
462*38e8c45fSAndroid Build Coastguard Worker         // 1) Does the apk_path start with the value of ANDROID_ROOT? (~in the system image)
463*38e8c45fSAndroid Build Coastguard Worker         //    (For simplicity, assume the value of ANDROID_ROOT does not contain a symlink.)
464*38e8c45fSAndroid Build Coastguard Worker         //
465*38e8c45fSAndroid Build Coastguard Worker         // 2) If you replace the name in the apk_path with "oat," does the path exist?
466*38e8c45fSAndroid Build Coastguard Worker         //    (=have a subdirectory for preopted files)
467*38e8c45fSAndroid Build Coastguard Worker         //
468*38e8c45fSAndroid Build Coastguard Worker         // If the answer to both is yes, skip the dexopt.
469*38e8c45fSAndroid Build Coastguard Worker         //
470*38e8c45fSAndroid Build Coastguard Worker         // Note: while one may think it's OK to call dexopt and it will fail (because APKs should
471*38e8c45fSAndroid Build Coastguard Worker         //       be stripped), that's not true for APKs signed outside the build system (so the
472*38e8c45fSAndroid Build Coastguard Worker         //       jar content must be exactly the same).
473*38e8c45fSAndroid Build Coastguard Worker 
474*38e8c45fSAndroid Build Coastguard Worker         //       (This is ugly as it's the only thing where we need to understand the contents
475*38e8c45fSAndroid Build Coastguard Worker         //        of parameters_, but it beats postponing the decision or using the call-
476*38e8c45fSAndroid Build Coastguard Worker         //        backs to do weird things.)
477*38e8c45fSAndroid Build Coastguard Worker 
478*38e8c45fSAndroid Build Coastguard Worker         // In addition, no need to preopt for "verify". The existing vdex files in the OTA package
479*38e8c45fSAndroid Build Coastguard Worker         // and the /data partition will still be usable after the OTA update is applied.
480*38e8c45fSAndroid Build Coastguard Worker         const char* apk_path = parameters_.apk_path;
481*38e8c45fSAndroid Build Coastguard Worker         CHECK(apk_path != nullptr);
482*38e8c45fSAndroid Build Coastguard Worker         if (StartsWith(apk_path, android_root_) || !IsAotCompilation()) {
483*38e8c45fSAndroid Build Coastguard Worker             const char* last_slash = strrchr(apk_path, '/');
484*38e8c45fSAndroid Build Coastguard Worker             if (last_slash != nullptr) {
485*38e8c45fSAndroid Build Coastguard Worker                 std::string path(apk_path, last_slash - apk_path + 1);
486*38e8c45fSAndroid Build Coastguard Worker                 CHECK(EndsWith(path, "/"));
487*38e8c45fSAndroid Build Coastguard Worker                 path = path + "oat";
488*38e8c45fSAndroid Build Coastguard Worker                 if (access(path.c_str(), F_OK) == 0) {
489*38e8c45fSAndroid Build Coastguard Worker                     LOG(INFO) << "Skipping A/B OTA preopt of already preopted package " << apk_path;
490*38e8c45fSAndroid Build Coastguard Worker                     return true;
491*38e8c45fSAndroid Build Coastguard Worker                 }
492*38e8c45fSAndroid Build Coastguard Worker             }
493*38e8c45fSAndroid Build Coastguard Worker         }
494*38e8c45fSAndroid Build Coastguard Worker 
495*38e8c45fSAndroid Build Coastguard Worker         // Another issue is unavailability of files in the new system. If the partition
496*38e8c45fSAndroid Build Coastguard Worker         // layout changes, otapreopt_chroot may not know about this. Then files from that
497*38e8c45fSAndroid Build Coastguard Worker         // partition will not be available and fail to build. This is problematic, as
498*38e8c45fSAndroid Build Coastguard Worker         // this tool will wipe the OTA artifact cache and try again (for robustness after
499*38e8c45fSAndroid Build Coastguard Worker         // a failed OTA with remaining cache artifacts).
500*38e8c45fSAndroid Build Coastguard Worker         if (access(apk_path, F_OK) != 0) {
501*38e8c45fSAndroid Build Coastguard Worker             PLOG(WARNING) << "Skipping A/B OTA preopt of non-existing package " << apk_path;
502*38e8c45fSAndroid Build Coastguard Worker             return true;
503*38e8c45fSAndroid Build Coastguard Worker         }
504*38e8c45fSAndroid Build Coastguard Worker 
505*38e8c45fSAndroid Build Coastguard Worker         return false;
506*38e8c45fSAndroid Build Coastguard Worker     }
507*38e8c45fSAndroid Build Coastguard Worker 
508*38e8c45fSAndroid Build Coastguard Worker     // Run dexopt with the parameters of parameters_.
509*38e8c45fSAndroid Build Coastguard Worker     // TODO(calin): embed the profile name in the parameters.
Dexopt()510*38e8c45fSAndroid Build Coastguard Worker     int Dexopt() {
511*38e8c45fSAndroid Build Coastguard Worker         std::string error;
512*38e8c45fSAndroid Build Coastguard Worker 
513*38e8c45fSAndroid Build Coastguard Worker         int dexopt_flags = parameters_.dexopt_flags;
514*38e8c45fSAndroid Build Coastguard Worker         // Make sure dex2oat is run with background priority.
515*38e8c45fSAndroid Build Coastguard Worker         dexopt_flags |= DEXOPT_BOOTCOMPLETE | DEXOPT_IDLE_BACKGROUND_JOB;
516*38e8c45fSAndroid Build Coastguard Worker 
517*38e8c45fSAndroid Build Coastguard Worker         parameters_.compilation_reason = "ab-ota";
518*38e8c45fSAndroid Build Coastguard Worker 
519*38e8c45fSAndroid Build Coastguard Worker         int res = dexopt(parameters_.apk_path,
520*38e8c45fSAndroid Build Coastguard Worker                          parameters_.uid,
521*38e8c45fSAndroid Build Coastguard Worker                          parameters_.pkgName,
522*38e8c45fSAndroid Build Coastguard Worker                          parameters_.instruction_set,
523*38e8c45fSAndroid Build Coastguard Worker                          parameters_.dexopt_needed,
524*38e8c45fSAndroid Build Coastguard Worker                          parameters_.oat_dir,
525*38e8c45fSAndroid Build Coastguard Worker                          dexopt_flags,
526*38e8c45fSAndroid Build Coastguard Worker                          parameters_.compiler_filter,
527*38e8c45fSAndroid Build Coastguard Worker                          parameters_.volume_uuid,
528*38e8c45fSAndroid Build Coastguard Worker                          parameters_.shared_libraries,
529*38e8c45fSAndroid Build Coastguard Worker                          parameters_.se_info,
530*38e8c45fSAndroid Build Coastguard Worker                          parameters_.downgrade,
531*38e8c45fSAndroid Build Coastguard Worker                          parameters_.target_sdk_version,
532*38e8c45fSAndroid Build Coastguard Worker                          parameters_.profile_name,
533*38e8c45fSAndroid Build Coastguard Worker                          parameters_.dex_metadata_path,
534*38e8c45fSAndroid Build Coastguard Worker                          parameters_.compilation_reason,
535*38e8c45fSAndroid Build Coastguard Worker                          &error);
536*38e8c45fSAndroid Build Coastguard Worker         if (res != 0) {
537*38e8c45fSAndroid Build Coastguard Worker             LOG(ERROR) << "During preopt of " << parameters_.apk_path << " got result " << res
538*38e8c45fSAndroid Build Coastguard Worker                        << " error: " << error;
539*38e8c45fSAndroid Build Coastguard Worker         }
540*38e8c45fSAndroid Build Coastguard Worker         return res;
541*38e8c45fSAndroid Build Coastguard Worker     }
542*38e8c45fSAndroid Build Coastguard Worker 
RunPreopt()543*38e8c45fSAndroid Build Coastguard Worker     int RunPreopt() {
544*38e8c45fSAndroid Build Coastguard Worker         if (ShouldSkipPreopt()) {
545*38e8c45fSAndroid Build Coastguard Worker             return 0;
546*38e8c45fSAndroid Build Coastguard Worker         }
547*38e8c45fSAndroid Build Coastguard Worker 
548*38e8c45fSAndroid Build Coastguard Worker         int dexopt_result = Dexopt();
549*38e8c45fSAndroid Build Coastguard Worker         if (dexopt_result == 0) {
550*38e8c45fSAndroid Build Coastguard Worker             return 0;
551*38e8c45fSAndroid Build Coastguard Worker         }
552*38e8c45fSAndroid Build Coastguard Worker 
553*38e8c45fSAndroid Build Coastguard Worker         if (WIFSIGNALED(dexopt_result)) {
554*38e8c45fSAndroid Build Coastguard Worker             LOG(WARNING) << "Interrupted by signal " << WTERMSIG(dexopt_result) ;
555*38e8c45fSAndroid Build Coastguard Worker             return dexopt_result;
556*38e8c45fSAndroid Build Coastguard Worker         }
557*38e8c45fSAndroid Build Coastguard Worker 
558*38e8c45fSAndroid Build Coastguard Worker         // If this was a profile-guided run, we may have profile version issues. Try to downgrade,
559*38e8c45fSAndroid Build Coastguard Worker         // if possible.
560*38e8c45fSAndroid Build Coastguard Worker         if ((parameters_.dexopt_flags & DEXOPT_PROFILE_GUIDED) == 0) {
561*38e8c45fSAndroid Build Coastguard Worker             return dexopt_result;
562*38e8c45fSAndroid Build Coastguard Worker         }
563*38e8c45fSAndroid Build Coastguard Worker 
564*38e8c45fSAndroid Build Coastguard Worker         LOG(WARNING) << "Downgrading compiler filter in an attempt to progress compilation";
565*38e8c45fSAndroid Build Coastguard Worker         parameters_.dexopt_flags &= ~DEXOPT_PROFILE_GUIDED;
566*38e8c45fSAndroid Build Coastguard Worker         return Dexopt();
567*38e8c45fSAndroid Build Coastguard Worker     }
568*38e8c45fSAndroid Build Coastguard Worker 
569*38e8c45fSAndroid Build Coastguard Worker     static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH";
570*38e8c45fSAndroid Build Coastguard Worker     static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT";
571*38e8c45fSAndroid Build Coastguard Worker     static constexpr const char* kAndroidDataPathPropertyName = "ANDROID_DATA";
572*38e8c45fSAndroid Build Coastguard Worker     // The index of the instruction-set string inside the package parameters. Needed for
573*38e8c45fSAndroid Build Coastguard Worker     // some special-casing that requires knowledge of the instruction-set.
574*38e8c45fSAndroid Build Coastguard Worker     static constexpr size_t kISAIndex = 3;
575*38e8c45fSAndroid Build Coastguard Worker 
576*38e8c45fSAndroid Build Coastguard Worker     // Stores the system properties read out of the B partition. We need to use these properties
577*38e8c45fSAndroid Build Coastguard Worker     // to compile, instead of the A properties we could get from init/get_property.
578*38e8c45fSAndroid Build Coastguard Worker     SystemProperties system_properties_;
579*38e8c45fSAndroid Build Coastguard Worker 
580*38e8c45fSAndroid Build Coastguard Worker     // Some select properties that are always needed.
581*38e8c45fSAndroid Build Coastguard Worker     std::string android_root_;
582*38e8c45fSAndroid Build Coastguard Worker     std::string android_data_;
583*38e8c45fSAndroid Build Coastguard Worker     std::string boot_classpath_;
584*38e8c45fSAndroid Build Coastguard Worker     std::string asec_mountpoint_;
585*38e8c45fSAndroid Build Coastguard Worker 
586*38e8c45fSAndroid Build Coastguard Worker     OTAPreoptParameters parameters_;
587*38e8c45fSAndroid Build Coastguard Worker 
588*38e8c45fSAndroid Build Coastguard Worker     // Store environment values we need to set.
589*38e8c45fSAndroid Build Coastguard Worker     std::vector<std::string> environ_;
590*38e8c45fSAndroid Build Coastguard Worker };
591*38e8c45fSAndroid Build Coastguard Worker 
592*38e8c45fSAndroid Build Coastguard Worker OTAPreoptService gOps;
593*38e8c45fSAndroid Build Coastguard Worker 
594*38e8c45fSAndroid Build Coastguard Worker ////////////////////////
595*38e8c45fSAndroid Build Coastguard Worker // Plug-in functions. //
596*38e8c45fSAndroid Build Coastguard Worker ////////////////////////
597*38e8c45fSAndroid Build Coastguard Worker 
get_property(const char * key,char * value,const char * default_value)598*38e8c45fSAndroid Build Coastguard Worker int get_property(const char *key, char *value, const char *default_value) {
599*38e8c45fSAndroid Build Coastguard Worker     return gOps.GetProperty(key, value, default_value);
600*38e8c45fSAndroid Build Coastguard Worker }
601*38e8c45fSAndroid Build Coastguard Worker 
602*38e8c45fSAndroid Build Coastguard Worker // Compute the output path of
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)603*38e8c45fSAndroid Build Coastguard Worker bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir,
604*38e8c45fSAndroid Build Coastguard Worker                              const char *apk_path,
605*38e8c45fSAndroid Build Coastguard Worker                              const char *instruction_set) {
606*38e8c45fSAndroid Build Coastguard Worker     const char *file_name_start;
607*38e8c45fSAndroid Build Coastguard Worker     const char *file_name_end;
608*38e8c45fSAndroid Build Coastguard Worker 
609*38e8c45fSAndroid Build Coastguard Worker     file_name_start = strrchr(apk_path, '/');
610*38e8c45fSAndroid Build Coastguard Worker     if (file_name_start == nullptr) {
611*38e8c45fSAndroid Build Coastguard Worker         ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
612*38e8c45fSAndroid Build Coastguard Worker         return false;
613*38e8c45fSAndroid Build Coastguard Worker     }
614*38e8c45fSAndroid Build Coastguard Worker     file_name_end = strrchr(file_name_start, '.');
615*38e8c45fSAndroid Build Coastguard Worker     if (file_name_end == nullptr) {
616*38e8c45fSAndroid Build Coastguard Worker         ALOGE("apk_path '%s' has no extension\n", apk_path);
617*38e8c45fSAndroid Build Coastguard Worker         return false;
618*38e8c45fSAndroid Build Coastguard Worker     }
619*38e8c45fSAndroid Build Coastguard Worker 
620*38e8c45fSAndroid Build Coastguard Worker     // Calculate file_name
621*38e8c45fSAndroid Build Coastguard Worker     file_name_start++;  // Move past '/', is valid as file_name_end is valid.
622*38e8c45fSAndroid Build Coastguard Worker     size_t file_name_len = file_name_end - file_name_start;
623*38e8c45fSAndroid Build Coastguard Worker     std::string file_name(file_name_start, file_name_len);
624*38e8c45fSAndroid Build Coastguard Worker 
625*38e8c45fSAndroid Build Coastguard Worker     // <apk_parent_dir>/oat/<isa>/<file_name>.odex.b
626*38e8c45fSAndroid Build Coastguard Worker     snprintf(path,
627*38e8c45fSAndroid Build Coastguard Worker              PKG_PATH_MAX,
628*38e8c45fSAndroid Build Coastguard Worker              "%s/%s/%s.odex.%s",
629*38e8c45fSAndroid Build Coastguard Worker              oat_dir,
630*38e8c45fSAndroid Build Coastguard Worker              instruction_set,
631*38e8c45fSAndroid Build Coastguard Worker              file_name.c_str(),
632*38e8c45fSAndroid Build Coastguard Worker              gOps.GetTargetSlot().c_str());
633*38e8c45fSAndroid Build Coastguard Worker     return true;
634*38e8c45fSAndroid Build Coastguard Worker }
635*38e8c45fSAndroid Build Coastguard Worker 
636*38e8c45fSAndroid Build Coastguard Worker /*
637*38e8c45fSAndroid Build Coastguard Worker  * Computes the odex file for the given apk_path and instruction_set.
638*38e8c45fSAndroid Build Coastguard Worker  * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
639*38e8c45fSAndroid Build Coastguard Worker  *
640*38e8c45fSAndroid Build Coastguard Worker  * Returns false if it failed to determine the odex file path.
641*38e8c45fSAndroid Build Coastguard Worker  */
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)642*38e8c45fSAndroid Build Coastguard Worker bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
643*38e8c45fSAndroid Build Coastguard Worker                               const char *instruction_set) {
644*38e8c45fSAndroid Build Coastguard Worker     const char *path_end = strrchr(apk_path, '/');
645*38e8c45fSAndroid Build Coastguard Worker     if (path_end == nullptr) {
646*38e8c45fSAndroid Build Coastguard Worker         ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
647*38e8c45fSAndroid Build Coastguard Worker         return false;
648*38e8c45fSAndroid Build Coastguard Worker     }
649*38e8c45fSAndroid Build Coastguard Worker     std::string path_component(apk_path, path_end - apk_path);
650*38e8c45fSAndroid Build Coastguard Worker 
651*38e8c45fSAndroid Build Coastguard Worker     const char *name_begin = path_end + 1;
652*38e8c45fSAndroid Build Coastguard Worker     const char *extension_start = strrchr(name_begin, '.');
653*38e8c45fSAndroid Build Coastguard Worker     if (extension_start == nullptr) {
654*38e8c45fSAndroid Build Coastguard Worker         ALOGE("apk_path '%s' has no extension.\n", apk_path);
655*38e8c45fSAndroid Build Coastguard Worker         return false;
656*38e8c45fSAndroid Build Coastguard Worker     }
657*38e8c45fSAndroid Build Coastguard Worker     std::string name_component(name_begin, extension_start - name_begin);
658*38e8c45fSAndroid Build Coastguard Worker 
659*38e8c45fSAndroid Build Coastguard Worker     std::string new_path = StringPrintf("%s/oat/%s/%s.odex.%s",
660*38e8c45fSAndroid Build Coastguard Worker                                         path_component.c_str(),
661*38e8c45fSAndroid Build Coastguard Worker                                         instruction_set,
662*38e8c45fSAndroid Build Coastguard Worker                                         name_component.c_str(),
663*38e8c45fSAndroid Build Coastguard Worker                                         gOps.GetTargetSlot().c_str());
664*38e8c45fSAndroid Build Coastguard Worker     if (new_path.length() >= PKG_PATH_MAX) {
665*38e8c45fSAndroid Build Coastguard Worker         LOG(ERROR) << "apk_path of " << apk_path << " is too long: " << new_path;
666*38e8c45fSAndroid Build Coastguard Worker         return false;
667*38e8c45fSAndroid Build Coastguard Worker     }
668*38e8c45fSAndroid Build Coastguard Worker     strcpy(path, new_path.c_str());
669*38e8c45fSAndroid Build Coastguard Worker     return true;
670*38e8c45fSAndroid Build Coastguard Worker }
671*38e8c45fSAndroid Build Coastguard Worker 
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)672*38e8c45fSAndroid Build Coastguard Worker bool create_cache_path(char path[PKG_PATH_MAX],
673*38e8c45fSAndroid Build Coastguard Worker                        const char *src,
674*38e8c45fSAndroid Build Coastguard Worker                        const char *instruction_set) {
675*38e8c45fSAndroid Build Coastguard Worker     size_t srclen = strlen(src);
676*38e8c45fSAndroid Build Coastguard Worker 
677*38e8c45fSAndroid Build Coastguard Worker         /* demand that we are an absolute path */
678*38e8c45fSAndroid Build Coastguard Worker     if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
679*38e8c45fSAndroid Build Coastguard Worker         return false;
680*38e8c45fSAndroid Build Coastguard Worker     }
681*38e8c45fSAndroid Build Coastguard Worker 
682*38e8c45fSAndroid Build Coastguard Worker     if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
683*38e8c45fSAndroid Build Coastguard Worker         return false;
684*38e8c45fSAndroid Build Coastguard Worker     }
685*38e8c45fSAndroid Build Coastguard Worker 
686*38e8c45fSAndroid Build Coastguard Worker     std::string from_src = std::string(src + 1);
687*38e8c45fSAndroid Build Coastguard Worker     std::replace(from_src.begin(), from_src.end(), '/', '@');
688*38e8c45fSAndroid Build Coastguard Worker 
689*38e8c45fSAndroid Build Coastguard Worker     std::string assembled_path = StringPrintf("%s/%s/%s/%s%s",
690*38e8c45fSAndroid Build Coastguard Worker                                               gOps.GetOTADataDirectory().c_str(),
691*38e8c45fSAndroid Build Coastguard Worker                                               DALVIK_CACHE,
692*38e8c45fSAndroid Build Coastguard Worker                                               instruction_set,
693*38e8c45fSAndroid Build Coastguard Worker                                               from_src.c_str(),
694*38e8c45fSAndroid Build Coastguard Worker                                               DALVIK_CACHE_POSTFIX);
695*38e8c45fSAndroid Build Coastguard Worker 
696*38e8c45fSAndroid Build Coastguard Worker     if (assembled_path.length() + 1 > PKG_PATH_MAX) {
697*38e8c45fSAndroid Build Coastguard Worker         return false;
698*38e8c45fSAndroid Build Coastguard Worker     }
699*38e8c45fSAndroid Build Coastguard Worker     strcpy(path, assembled_path.c_str());
700*38e8c45fSAndroid Build Coastguard Worker 
701*38e8c45fSAndroid Build Coastguard Worker     return true;
702*38e8c45fSAndroid Build Coastguard Worker }
703*38e8c45fSAndroid Build Coastguard Worker 
force_compile_without_image()704*38e8c45fSAndroid Build Coastguard Worker bool force_compile_without_image() {
705*38e8c45fSAndroid Build Coastguard Worker     // We don't have a boot image anyway. Compile without a boot image.
706*38e8c45fSAndroid Build Coastguard Worker     return true;
707*38e8c45fSAndroid Build Coastguard Worker }
708*38e8c45fSAndroid Build Coastguard Worker 
log_callback(int type,const char * fmt,...)709*38e8c45fSAndroid Build Coastguard Worker static int log_callback(int type, const char *fmt, ...) {
710*38e8c45fSAndroid Build Coastguard Worker     va_list ap;
711*38e8c45fSAndroid Build Coastguard Worker     int priority;
712*38e8c45fSAndroid Build Coastguard Worker 
713*38e8c45fSAndroid Build Coastguard Worker     switch (type) {
714*38e8c45fSAndroid Build Coastguard Worker         case SELINUX_WARNING:
715*38e8c45fSAndroid Build Coastguard Worker             priority = ANDROID_LOG_WARN;
716*38e8c45fSAndroid Build Coastguard Worker             break;
717*38e8c45fSAndroid Build Coastguard Worker         case SELINUX_INFO:
718*38e8c45fSAndroid Build Coastguard Worker             priority = ANDROID_LOG_INFO;
719*38e8c45fSAndroid Build Coastguard Worker             break;
720*38e8c45fSAndroid Build Coastguard Worker         default:
721*38e8c45fSAndroid Build Coastguard Worker             priority = ANDROID_LOG_ERROR;
722*38e8c45fSAndroid Build Coastguard Worker             break;
723*38e8c45fSAndroid Build Coastguard Worker     }
724*38e8c45fSAndroid Build Coastguard Worker     va_start(ap, fmt);
725*38e8c45fSAndroid Build Coastguard Worker     LOG_PRI_VA(priority, "SELinux", fmt, ap);
726*38e8c45fSAndroid Build Coastguard Worker     va_end(ap);
727*38e8c45fSAndroid Build Coastguard Worker     return 0;
728*38e8c45fSAndroid Build Coastguard Worker }
729*38e8c45fSAndroid Build Coastguard Worker 
otapreopt_main(const int argc,char * argv[])730*38e8c45fSAndroid Build Coastguard Worker static int otapreopt_main(const int argc, char *argv[]) {
731*38e8c45fSAndroid Build Coastguard Worker     int selinux_enabled = (is_selinux_enabled() > 0);
732*38e8c45fSAndroid Build Coastguard Worker 
733*38e8c45fSAndroid Build Coastguard Worker     setenv("ANDROID_LOG_TAGS", "*:v", 1);
734*38e8c45fSAndroid Build Coastguard Worker     android::base::InitLogging(argv);
735*38e8c45fSAndroid Build Coastguard Worker 
736*38e8c45fSAndroid Build Coastguard Worker     if (argc < 2) {
737*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Expecting parameters");
738*38e8c45fSAndroid Build Coastguard Worker         exit(1);
739*38e8c45fSAndroid Build Coastguard Worker     }
740*38e8c45fSAndroid Build Coastguard Worker 
741*38e8c45fSAndroid Build Coastguard Worker     union selinux_callback cb;
742*38e8c45fSAndroid Build Coastguard Worker     cb.func_log = log_callback;
743*38e8c45fSAndroid Build Coastguard Worker     selinux_set_callback(SELINUX_CB_LOG, cb);
744*38e8c45fSAndroid Build Coastguard Worker 
745*38e8c45fSAndroid Build Coastguard Worker     if (selinux_enabled && selinux_status_open(true) < 0) {
746*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Could not open selinux status; exiting.\n");
747*38e8c45fSAndroid Build Coastguard Worker         exit(1);
748*38e8c45fSAndroid Build Coastguard Worker     }
749*38e8c45fSAndroid Build Coastguard Worker 
750*38e8c45fSAndroid Build Coastguard Worker     int ret = android::installd::gOps.Main(argc, argv);
751*38e8c45fSAndroid Build Coastguard Worker 
752*38e8c45fSAndroid Build Coastguard Worker     return ret;
753*38e8c45fSAndroid Build Coastguard Worker }
754*38e8c45fSAndroid Build Coastguard Worker 
755*38e8c45fSAndroid Build Coastguard Worker }  // namespace installd
756*38e8c45fSAndroid Build Coastguard Worker }  // namespace android
757*38e8c45fSAndroid Build Coastguard Worker 
main(const int argc,char * argv[])758*38e8c45fSAndroid Build Coastguard Worker int main(const int argc, char *argv[]) {
759*38e8c45fSAndroid Build Coastguard Worker     return android::installd::otapreopt_main(argc, argv);
760*38e8c45fSAndroid Build Coastguard Worker }
761