blob: 2cce2779757e6fc28e833ea46c44c2b79e0ed0d2 [file] [log] [blame]
Jeff Sharkey6c2c0562016-12-07 12:12:00 -07001/*
2 * Copyright (C) 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 */
Mark Salyzyna5e161b2016-09-29 08:08:05 -070016#define LOG_TAG "installed"
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070017
Jeff Sharkey90aff262016-12-12 14:28:24 -070018#include <fcntl.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070019#include <stdlib.h>
20#include <string.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070021#include <sys/capability.h>
22#include <sys/file.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070023#include <sys/stat.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070024#include <sys/time.h>
25#include <sys/types.h>
26#include <sys/resource.h>
27#include <sys/wait.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070028#include <unistd.h>
29
30#include <android-base/logging.h>
Andreas Gampe6a9cf722017-07-24 16:49:10 -070031#include <android-base/properties.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070032#include <android-base/stringprintf.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070033#include <android-base/strings.h>
34#include <android-base/unique_fd.h>
Calin Juravle80a21252017-01-17 14:43:25 -080035#include <cutils/fs.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070036#include <cutils/properties.h>
37#include <cutils/sched_policy.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070038#include <log/log.h> // TODO: Move everything to base/logging.
Jeff Sharkey90aff262016-12-12 14:28:24 -070039#include <private/android_filesystem_config.h>
Calin Juravlecb556e32017-04-04 20:22:50 -070040#include <selinux/android.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070041#include <system/thread_defs.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070042
43#include "dexopt.h"
Jeff Sharkeyc1149c92017-09-21 14:51:09 -060044#include "globals.h"
Jeff Sharkey90aff262016-12-12 14:28:24 -070045#include "installd_deps.h"
46#include "otapreopt_utils.h"
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070047#include "utils.h"
48
49using android::base::StringPrintf;
Jeff Sharkey90aff262016-12-12 14:28:24 -070050using android::base::EndsWith;
Calin Juravle1a0af3b2017-03-09 14:33:33 -080051using android::base::unique_fd;
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070052
53namespace android {
54namespace installd {
55
Calin Juravle114f0812017-03-08 19:05:07 -080056// Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
57struct FreeDelete {
58 // NOTE: Deleting a const object is valid but free() takes a non-const pointer.
59 void operator()(const void* ptr) const {
60 free(const_cast<void*>(ptr));
61 }
62};
63
64// Alias for std::unique_ptr<> that uses the C function free() to delete objects.
65template <typename T>
66using UniqueCPtr = std::unique_ptr<T, FreeDelete>;
67
Calin Juravle1a0af3b2017-03-09 14:33:33 -080068static unique_fd invalid_unique_fd() {
69 return unique_fd(-1);
70}
71
Andreas Gampe6a9cf722017-07-24 16:49:10 -070072static bool is_debug_runtime() {
73 return android::base::GetProperty("persist.sys.dalvik.vm.lib.2", "") == "libartd.so";
74}
75
David Sehra3b5ab62017-10-25 14:27:29 -070076static bool is_debuggable_build() {
77 return android::base::GetBoolProperty("ro.debuggable", false);
78}
79
Jeff Sharkey90aff262016-12-12 14:28:24 -070080static bool clear_profile(const std::string& profile) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -080081 unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
Jeff Sharkey90aff262016-12-12 14:28:24 -070082 if (ufd.get() < 0) {
83 if (errno != ENOENT) {
84 PLOG(WARNING) << "Could not open profile " << profile;
85 return false;
86 } else {
87 // Nothing to clear. That's ok.
88 return true;
89 }
90 }
91
92 if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
93 if (errno != EWOULDBLOCK) {
94 PLOG(WARNING) << "Error locking profile " << profile;
95 }
96 // This implies that the app owning this profile is running
97 // (and has acquired the lock).
98 //
99 // If we can't acquire the lock bail out since clearing is useless anyway
100 // (the app will write again to the profile).
101 //
102 // Note:
103 // This does not impact the this is not an issue for the profiling correctness.
104 // In case this is needed because of an app upgrade, profiles will still be
105 // eventually cleared by the app itself due to checksum mismatch.
106 // If this is needed because profman advised, then keeping the data around
107 // until the next run is again not an issue.
108 //
109 // If the app attempts to acquire a lock while we've held one here,
110 // it will simply skip the current write cycle.
111 return false;
112 }
113
114 bool truncated = ftruncate(ufd.get(), 0) == 0;
115 if (!truncated) {
116 PLOG(WARNING) << "Could not truncate " << profile;
117 }
118 if (flock(ufd.get(), LOCK_UN) != 0) {
119 PLOG(WARNING) << "Error unlocking profile " << profile;
120 }
121 return truncated;
122}
123
Calin Juravle114f0812017-03-08 19:05:07 -0800124// Clear the reference profile for the given location.
125// The location is the package name for primary apks or the dex path for secondary dex files.
126static bool clear_reference_profile(const std::string& location, bool is_secondary_dex) {
127 return clear_profile(create_reference_profile_path(location, is_secondary_dex));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700128}
129
Calin Juravle114f0812017-03-08 19:05:07 -0800130// Clear the reference profile for the given location.
131// The location is the package name for primary apks or the dex path for secondary dex files.
132static bool clear_current_profile(const std::string& pkgname, userid_t user,
133 bool is_secondary_dex) {
134 return clear_profile(create_current_profile_path(user, pkgname, is_secondary_dex));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700135}
136
Calin Juravle114f0812017-03-08 19:05:07 -0800137// Clear the reference profile for the primary apk of the given package.
138bool clear_primary_reference_profile(const std::string& pkgname) {
139 return clear_reference_profile(pkgname, /*is_secondary_dex*/false);
140}
141
142// Clear all current profile for the primary apk of the given package.
143bool clear_primary_current_profiles(const std::string& pkgname) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700144 bool success = true;
Calin Juravle114f0812017-03-08 19:05:07 -0800145 // For secondary dex files, we don't really need the user but we use it for sanity checks.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700146 std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
147 for (auto user : users) {
Calin Juravle114f0812017-03-08 19:05:07 -0800148 success &= clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700149 }
150 return success;
151}
152
Calin Juravle114f0812017-03-08 19:05:07 -0800153// Clear the current profile for the primary apk of the given package and user.
154bool clear_primary_current_profile(const std::string& pkgname, userid_t user) {
155 return clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
156}
157
Jeff Sharkey90aff262016-12-12 14:28:24 -0700158static int split_count(const char *str)
159{
160 char *ctx;
161 int count = 0;
162 char buf[kPropertyValueMax];
163
Jeff Sharkeyc1149c92017-09-21 14:51:09 -0600164 strlcpy(buf, str, sizeof(buf));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700165 char *pBuf = buf;
166
167 while(strtok_r(pBuf, " ", &ctx) != NULL) {
168 count++;
169 pBuf = NULL;
170 }
171
172 return count;
173}
174
175static int split(char *buf, const char **argv)
176{
177 char *ctx;
178 int count = 0;
179 char *tok;
180 char *pBuf = buf;
181
182 while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) {
183 argv[count++] = tok;
184 pBuf = NULL;
185 }
186
187 return count;
188}
189
Jeff Hao10b8a6e2017-04-05 17:11:39 -0700190static const char* get_location_from_path(const char* path) {
191 static constexpr char kLocationSeparator = '/';
192 const char *location = strrchr(path, kLocationSeparator);
193 if (location == NULL) {
194 return path;
195 } else {
196 // Skip the separator character.
197 return location + 1;
198 }
199}
200
Jeff Sharkey90aff262016-12-12 14:28:24 -0700201static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
202 const char* input_file_name, const char* output_file_name, int swap_fd,
Nicolas Geoffraybe6ecd62017-05-03 13:21:37 +0100203 const char* instruction_set, const char* compiler_filter,
Andreas Gampea73a0cb2017-11-02 18:14:42 -0700204 bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd,
David Sehra3b5ab62017-10-25 14:27:29 -0700205 const char* class_loader_context) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700206 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
207
208 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
209 ALOGE("Instruction set %s longer than max length of %d",
210 instruction_set, MAX_INSTRUCTION_SET_LEN);
211 return;
212 }
213
Jeff Hao10b8a6e2017-04-05 17:11:39 -0700214 // Get the relative path to the input file.
215 const char* relative_input_file_name = get_location_from_path(input_file_name);
216
Jeff Sharkey90aff262016-12-12 14:28:24 -0700217 char dex2oat_Xms_flag[kPropertyValueMax];
218 bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
219
220 char dex2oat_Xmx_flag[kPropertyValueMax];
221 bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
222
223 char dex2oat_threads_buf[kPropertyValueMax];
224 bool have_dex2oat_threads_flag = get_property(post_bootcomplete
225 ? "dalvik.vm.dex2oat-threads"
226 : "dalvik.vm.boot-dex2oat-threads",
227 dex2oat_threads_buf,
228 NULL) > 0;
229 char dex2oat_threads_arg[kPropertyValueMax + 2];
230 if (have_dex2oat_threads_flag) {
231 sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
232 }
233
234 char dex2oat_isa_features_key[kPropertyKeyMax];
235 sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
236 char dex2oat_isa_features[kPropertyValueMax];
237 bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key,
238 dex2oat_isa_features, NULL) > 0;
239
240 char dex2oat_isa_variant_key[kPropertyKeyMax];
241 sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
242 char dex2oat_isa_variant[kPropertyValueMax];
243 bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key,
244 dex2oat_isa_variant, NULL) > 0;
245
246 const char *dex2oat_norelocation = "-Xnorelocate";
247 bool have_dex2oat_relocation_skip_flag = false;
248
249 char dex2oat_flags[kPropertyValueMax];
250 int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags",
251 dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
252 ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
253
Nicolas Geoffraybe6ecd62017-05-03 13:21:37 +0100254 // If we are booting without the real /data, don't spend time compiling.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700255 char vold_decrypt[kPropertyValueMax];
256 bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
257 bool skip_compilation = (have_vold_decrypt &&
258 (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
259 (strcmp(vold_decrypt, "1") == 0)));
260
261 bool generate_debug_info = property_get_bool("debug.generate-debug-info", false);
262
263 char app_image_format[kPropertyValueMax];
264 char image_format_arg[strlen("--image-format=") + kPropertyValueMax];
265 bool have_app_image_format =
266 image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
267 if (have_app_image_format) {
268 sprintf(image_format_arg, "--image-format=%s", app_image_format);
269 }
270
271 char dex2oat_large_app_threshold[kPropertyValueMax];
272 bool have_dex2oat_large_app_threshold =
273 get_property("dalvik.vm.dex2oat-very-large", dex2oat_large_app_threshold, NULL) > 0;
274 char dex2oat_large_app_threshold_arg[strlen("--very-large-app-threshold=") + kPropertyValueMax];
275 if (have_dex2oat_large_app_threshold) {
276 sprintf(dex2oat_large_app_threshold_arg,
277 "--very-large-app-threshold=%s",
278 dex2oat_large_app_threshold);
279 }
280
Andreas Gampe6a9cf722017-07-24 16:49:10 -0700281 // If the runtime was requested to use libartd.so, we'll run dex2oatd, otherwise dex2oat.
David Sehra3b5ab62017-10-25 14:27:29 -0700282 const char* dex2oat_bin = "/system/bin/dex2oat";
283 static const char* kDex2oatDebugPath = "/system/bin/dex2oatd";
Andreas Gampea73a0cb2017-11-02 18:14:42 -0700284 if (is_debug_runtime() || (background_job_compile && is_debuggable_build())) {
David Sehra3b5ab62017-10-25 14:27:29 -0700285 DCHECK(access(kDex2oatDebugPath, X_OK) == 0);
286 dex2oat_bin = kDex2oatDebugPath;
287 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700288
289 static const char* RUNTIME_ARG = "--runtime-arg";
290
291 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
292
George Burgess IV36cebe772017-01-25 11:52:01 -0800293 // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
294 // use arraysize instead.
295 char zip_fd_arg[arraysize("--zip-fd=") + MAX_INT_LEN];
296 char zip_location_arg[arraysize("--zip-location=") + PKG_PATH_MAX];
297 char input_vdex_fd_arg[arraysize("--input-vdex-fd=") + MAX_INT_LEN];
298 char output_vdex_fd_arg[arraysize("--output-vdex-fd=") + MAX_INT_LEN];
299 char oat_fd_arg[arraysize("--oat-fd=") + MAX_INT_LEN];
300 char oat_location_arg[arraysize("--oat-location=") + PKG_PATH_MAX];
301 char instruction_set_arg[arraysize("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
302 char instruction_set_variant_arg[arraysize("--instruction-set-variant=") + kPropertyValueMax];
303 char instruction_set_features_arg[arraysize("--instruction-set-features=") + kPropertyValueMax];
304 char dex2oat_Xms_arg[arraysize("-Xms") + kPropertyValueMax];
305 char dex2oat_Xmx_arg[arraysize("-Xmx") + kPropertyValueMax];
306 char dex2oat_compiler_filter_arg[arraysize("--compiler-filter=") + kPropertyValueMax];
Jeff Sharkey90aff262016-12-12 14:28:24 -0700307 bool have_dex2oat_swap_fd = false;
George Burgess IV36cebe772017-01-25 11:52:01 -0800308 char dex2oat_swap_fd[arraysize("--swap-fd=") + MAX_INT_LEN];
Jeff Sharkey90aff262016-12-12 14:28:24 -0700309 bool have_dex2oat_image_fd = false;
George Burgess IV36cebe772017-01-25 11:52:01 -0800310 char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
Calin Juravle52c45822017-07-13 22:50:21 -0700311 size_t class_loader_context_size = arraysize("--class-loader-context=") + PKG_PATH_MAX;
312 char class_loader_context_arg[class_loader_context_size];
313 if (class_loader_context != nullptr) {
314 snprintf(class_loader_context_arg, class_loader_context_size, "--class-loader-context=%s",
315 class_loader_context);
316 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700317
318 sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
Jeff Hao10b8a6e2017-04-05 17:11:39 -0700319 sprintf(zip_location_arg, "--zip-location=%s", relative_input_file_name);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700320 sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
321 sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
322 sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
323 sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
324 sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
325 sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
326 sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
327 if (swap_fd >= 0) {
328 have_dex2oat_swap_fd = true;
329 sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
330 }
331 if (image_fd >= 0) {
332 have_dex2oat_image_fd = true;
333 sprintf(dex2oat_image_fd, "--app-image-fd=%d", image_fd);
334 }
335
336 if (have_dex2oat_Xms_flag) {
337 sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
338 }
339 if (have_dex2oat_Xmx_flag) {
340 sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
341 }
342
343 // Compute compiler filter.
344
Nicolas Geoffraybe6ecd62017-05-03 13:21:37 +0100345 bool have_dex2oat_compiler_filter_flag = false;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700346 if (skip_compilation) {
Jeff Sharkeyc1149c92017-09-21 14:51:09 -0600347 strlcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract",
348 sizeof(dex2oat_compiler_filter_arg));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700349 have_dex2oat_compiler_filter_flag = true;
350 have_dex2oat_relocation_skip_flag = true;
Nicolas Geoffraybe6ecd62017-05-03 13:21:37 +0100351 } else if (compiler_filter != nullptr) {
352 if (strlen(compiler_filter) + strlen("--compiler-filter=") <
Jeff Sharkey90aff262016-12-12 14:28:24 -0700353 arraysize(dex2oat_compiler_filter_arg)) {
Nicolas Geoffraybe6ecd62017-05-03 13:21:37 +0100354 sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
355 have_dex2oat_compiler_filter_flag = true;
356 } else {
357 ALOGW("Compiler filter name '%s' is too large (max characters is %zu)",
358 compiler_filter,
359 kPropertyValueMax);
360 }
361 }
362
363 if (!have_dex2oat_compiler_filter_flag) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700364 char dex2oat_compiler_filter_flag[kPropertyValueMax];
365 have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
366 dex2oat_compiler_filter_flag, NULL) > 0;
367 if (have_dex2oat_compiler_filter_flag) {
368 sprintf(dex2oat_compiler_filter_arg,
369 "--compiler-filter=%s",
370 dex2oat_compiler_filter_flag);
371 }
372 }
373
374 // Check whether all apps should be compiled debuggable.
375 if (!debuggable) {
376 char prop_buf[kPropertyValueMax];
377 debuggable =
378 (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
379 (prop_buf[0] == '1');
380 }
381 char profile_arg[strlen("--profile-file-fd=") + MAX_INT_LEN];
382 if (profile_fd != -1) {
383 sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
384 }
385
Jeff Hao10b8a6e2017-04-05 17:11:39 -0700386 // Get the directory of the apk to pass as a base classpath directory.
387 char base_dir[arraysize("--classpath-dir=") + PKG_PATH_MAX];
388 std::string apk_dir(input_file_name);
389 unsigned long dir_index = apk_dir.rfind('/');
390 bool has_base_dir = dir_index != std::string::npos;
391 if (has_base_dir) {
392 apk_dir = apk_dir.substr(0, dir_index);
393 sprintf(base_dir, "--classpath-dir=%s", apk_dir.c_str());
394 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700395
Jeff Hao10b8a6e2017-04-05 17:11:39 -0700396
Andreas Gampe6a9cf722017-07-24 16:49:10 -0700397 ALOGV("Running %s in=%s out=%s\n", dex2oat_bin, relative_input_file_name, output_file_name);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700398
399 const char* argv[9 // program name, mandatory arguments and the final NULL
400 + (have_dex2oat_isa_variant ? 1 : 0)
401 + (have_dex2oat_isa_features ? 1 : 0)
402 + (have_dex2oat_Xms_flag ? 2 : 0)
403 + (have_dex2oat_Xmx_flag ? 2 : 0)
404 + (have_dex2oat_compiler_filter_flag ? 1 : 0)
405 + (have_dex2oat_threads_flag ? 1 : 0)
406 + (have_dex2oat_swap_fd ? 1 : 0)
407 + (have_dex2oat_image_fd ? 1 : 0)
408 + (have_dex2oat_relocation_skip_flag ? 2 : 0)
409 + (generate_debug_info ? 1 : 0)
410 + (debuggable ? 1 : 0)
411 + (have_app_image_format ? 1 : 0)
412 + dex2oat_flags_count
413 + (profile_fd == -1 ? 0 : 1)
Calin Juravle52c45822017-07-13 22:50:21 -0700414 + (class_loader_context != nullptr ? 1 : 0)
Jeff Hao10b8a6e2017-04-05 17:11:39 -0700415 + (has_base_dir ? 1 : 0)
Jeff Sharkey90aff262016-12-12 14:28:24 -0700416 + (have_dex2oat_large_app_threshold ? 1 : 0)];
417 int i = 0;
Andreas Gampe6a9cf722017-07-24 16:49:10 -0700418 argv[i++] = dex2oat_bin;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700419 argv[i++] = zip_fd_arg;
420 argv[i++] = zip_location_arg;
421 argv[i++] = input_vdex_fd_arg;
422 argv[i++] = output_vdex_fd_arg;
423 argv[i++] = oat_fd_arg;
424 argv[i++] = oat_location_arg;
425 argv[i++] = instruction_set_arg;
426 if (have_dex2oat_isa_variant) {
427 argv[i++] = instruction_set_variant_arg;
428 }
429 if (have_dex2oat_isa_features) {
430 argv[i++] = instruction_set_features_arg;
431 }
432 if (have_dex2oat_Xms_flag) {
433 argv[i++] = RUNTIME_ARG;
434 argv[i++] = dex2oat_Xms_arg;
435 }
436 if (have_dex2oat_Xmx_flag) {
437 argv[i++] = RUNTIME_ARG;
438 argv[i++] = dex2oat_Xmx_arg;
439 }
440 if (have_dex2oat_compiler_filter_flag) {
441 argv[i++] = dex2oat_compiler_filter_arg;
442 }
443 if (have_dex2oat_threads_flag) {
444 argv[i++] = dex2oat_threads_arg;
445 }
446 if (have_dex2oat_swap_fd) {
447 argv[i++] = dex2oat_swap_fd;
448 }
449 if (have_dex2oat_image_fd) {
450 argv[i++] = dex2oat_image_fd;
451 }
452 if (generate_debug_info) {
453 argv[i++] = "--generate-debug-info";
454 }
455 if (debuggable) {
456 argv[i++] = "--debuggable";
457 }
458 if (have_app_image_format) {
459 argv[i++] = image_format_arg;
460 }
461 if (have_dex2oat_large_app_threshold) {
462 argv[i++] = dex2oat_large_app_threshold_arg;
463 }
464 if (dex2oat_flags_count) {
465 i += split(dex2oat_flags, argv + i);
466 }
467 if (have_dex2oat_relocation_skip_flag) {
468 argv[i++] = RUNTIME_ARG;
469 argv[i++] = dex2oat_norelocation;
470 }
471 if (profile_fd != -1) {
472 argv[i++] = profile_arg;
473 }
Jeff Hao10b8a6e2017-04-05 17:11:39 -0700474 if (has_base_dir) {
475 argv[i++] = base_dir;
476 }
Calin Juravle52c45822017-07-13 22:50:21 -0700477 if (class_loader_context != nullptr) {
478 argv[i++] = class_loader_context_arg;
479 }
480
Jeff Sharkey90aff262016-12-12 14:28:24 -0700481 // Do not add after dex2oat_flags, they should override others for debugging.
482 argv[i] = NULL;
483
Andreas Gampe6a9cf722017-07-24 16:49:10 -0700484 execv(dex2oat_bin, (char * const *)argv);
485 ALOGE("execv(%s) failed: %s\n", dex2oat_bin, strerror(errno));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700486}
487
488/*
489 * Whether dexopt should use a swap file when compiling an APK.
490 *
491 * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
492 * itself, anyways).
493 *
494 * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
495 *
496 * Otherwise, return true if this is a low-mem device.
497 *
498 * Otherwise, return default value.
499 */
500static bool kAlwaysProvideSwapFile = false;
501static bool kDefaultProvideSwapFile = true;
502
503static bool ShouldUseSwapFileForDexopt() {
504 if (kAlwaysProvideSwapFile) {
505 return true;
506 }
507
508 // Check the "override" property. If it exists, return value == "true".
509 char dex2oat_prop_buf[kPropertyValueMax];
510 if (get_property("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
511 if (strcmp(dex2oat_prop_buf, "true") == 0) {
512 return true;
513 } else {
514 return false;
515 }
516 }
517
518 // Shortcut for default value. This is an implementation optimization for the process sketched
519 // above. If the default value is true, we can avoid to check whether this is a low-mem device,
520 // as low-mem is never returning false. The compiler will optimize this away if it can.
521 if (kDefaultProvideSwapFile) {
522 return true;
523 }
524
525 bool is_low_mem = property_get_bool("ro.config.low_ram", false);
526 if (is_low_mem) {
527 return true;
528 }
529
530 // Default value must be false here.
531 return kDefaultProvideSwapFile;
532}
533
Richard Uhler76cc0272016-12-08 10:46:35 +0000534static void SetDex2OatScheduling(bool set_to_bg) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700535 if (set_to_bg) {
536 if (set_sched_policy(0, SP_BACKGROUND) < 0) {
537 ALOGE("set_sched_policy failed: %s\n", strerror(errno));
538 exit(70);
539 }
540 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
541 ALOGE("setpriority failed: %s\n", strerror(errno));
542 exit(71);
543 }
544 }
545}
546
Calin Juravle114f0812017-03-08 19:05:07 -0800547static bool create_profile(int uid, const std::string& profile) {
548 unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), O_CREAT | O_NOFOLLOW, 0600)));
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800549 if (fd.get() < 0) {
Calin Juravle114f0812017-03-08 19:05:07 -0800550 if (errno == EEXIST) {
551 return true;
552 } else {
553 PLOG(ERROR) << "Failed to create profile " << profile;
554 return false;
555 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700556 }
Calin Juravle114f0812017-03-08 19:05:07 -0800557 // Profiles should belong to the app; make sure of that by giving ownership to
558 // the app uid. If we cannot do that, there's no point in returning the fd
559 // since dex2oat/profman will fail with SElinux denials.
560 if (fchown(fd.get(), uid, uid) < 0) {
561 PLOG(ERROR) << "Could not chwon profile " << profile;
562 return false;
563 }
564 return true;
565}
566
567static unique_fd open_profile(int uid, const std::string& profile, bool read_write) {
568 // Check if we need to open the profile for a read-write operation. If so, we
569 // might need to create the profile since the file might not be there. Reference
570 // profiles are created on the fly so they might not exist beforehand.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700571 if (read_write) {
Calin Juravle114f0812017-03-08 19:05:07 -0800572 if (!create_profile(uid, profile)) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800573 return invalid_unique_fd();
Jeff Sharkey90aff262016-12-12 14:28:24 -0700574 }
575 }
Calin Juravle114f0812017-03-08 19:05:07 -0800576 int flags = read_write ? O_RDWR : O_RDONLY;
577 // Do not follow symlinks when opening a profile:
578 // - primary profiles should not contain symlinks in their paths
579 // - secondary dex paths should have been already resolved and validated
580 flags |= O_NOFOLLOW;
581
582 unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
583 if (fd.get() < 0) {
584 if (errno != ENOENT) {
585 // Profiles might be missing for various reasons. For example, in a
586 // multi-user environment, the profile directory for one user can be created
587 // after we start a merge. In this case the current profile for that user
588 // will not be found.
589 // Also, the secondary dex profiles might be deleted by the app at any time,
590 // so we can't we need to prepare if they are missing.
591 PLOG(ERROR) << "Failed to open profile " << profile;
592 }
593 return invalid_unique_fd();
594 }
595
Jeff Sharkey90aff262016-12-12 14:28:24 -0700596 return fd;
597}
598
Calin Juravle114f0812017-03-08 19:05:07 -0800599static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location,
600 bool is_secondary_dex) {
601 std::string profile = create_current_profile_path(user, location, is_secondary_dex);
602 return open_profile(uid, profile, /*read_write*/false);
603}
604
605static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write,
606 bool is_secondary_dex) {
607 std::string profile = create_reference_profile_path(location, is_secondary_dex);
608 return open_profile(uid, profile, read_write);
609}
610
611static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex,
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800612 /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700613 // Open the reference profile in read-write mode as profman might need to save the merge.
Calin Juravle114f0812017-03-08 19:05:07 -0800614 *reference_profile_fd = open_reference_profile(uid, location, /*read_write*/ true,
615 is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700616
Calin Juravle114f0812017-03-08 19:05:07 -0800617 // For secondary dex files, we don't really need the user but we use it for sanity checks.
618 // Note: the user owning the dex file should be the current user.
619 std::vector<userid_t> users;
620 if (is_secondary_dex){
621 users.push_back(multiuser_get_user_id(uid));
622 } else {
623 users = get_known_users(/*volume_uuid*/ nullptr);
624 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700625 for (auto user : users) {
Calin Juravle114f0812017-03-08 19:05:07 -0800626 unique_fd profile_fd = open_current_profile(uid, user, location, is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700627 // Add to the lists only if both fds are valid.
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800628 if (profile_fd.get() >= 0) {
629 profiles_fd->push_back(std::move(profile_fd));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700630 }
631 }
632}
633
634static void drop_capabilities(uid_t uid) {
635 if (setgid(uid) != 0) {
636 ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
637 exit(64);
638 }
639 if (setuid(uid) != 0) {
640 ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
641 exit(65);
642 }
643 // drop capabilities
644 struct __user_cap_header_struct capheader;
645 struct __user_cap_data_struct capdata[2];
646 memset(&capheader, 0, sizeof(capheader));
647 memset(&capdata, 0, sizeof(capdata));
648 capheader.version = _LINUX_CAPABILITY_VERSION_3;
649 if (capset(&capheader, &capdata[0]) < 0) {
650 ALOGE("capset failed: %s\n", strerror(errno));
651 exit(66);
652 }
653}
654
655static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
656static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
657static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
658static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
659static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
660
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800661static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
662 const unique_fd& reference_profile_fd) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700663 static const size_t MAX_INT_LEN = 32;
Andreas Gampe6a9cf722017-07-24 16:49:10 -0700664 const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman";
Jeff Sharkey90aff262016-12-12 14:28:24 -0700665
666 std::vector<std::string> profile_args(profiles_fd.size());
667 char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN];
668 for (size_t k = 0; k < profiles_fd.size(); k++) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800669 sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k].get());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700670 profile_args[k].assign(profile_buf);
671 }
672 char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800673 sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd.get());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700674
675 // program name, reference profile fd, the final NULL and the profile fds
676 const char* argv[3 + profiles_fd.size()];
677 int i = 0;
Andreas Gampe6a9cf722017-07-24 16:49:10 -0700678 argv[i++] = profman_bin;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700679 argv[i++] = reference_profile_arg;
680 for (size_t k = 0; k < profile_args.size(); k++) {
681 argv[i++] = profile_args[k].c_str();
682 }
683 // Do not add after dex2oat_flags, they should override others for debugging.
684 argv[i] = NULL;
685
Andreas Gampe6a9cf722017-07-24 16:49:10 -0700686 execv(profman_bin, (char * const *)argv);
687 ALOGE("execv(%s) failed: %s\n", profman_bin, strerror(errno));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700688 exit(68); /* only get here on exec failure */
689}
690
691// Decides if profile guided compilation is needed or not based on existing profiles.
Calin Juravle114f0812017-03-08 19:05:07 -0800692// The location is the package name for primary apks or the dex path for secondary dex files.
693// Returns true if there is enough information in the current profiles that makes it
694// worth to recompile the given location.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700695// If the return value is true all the current profiles would have been merged into
696// the reference profiles accessible with open_reference_profile().
Calin Juravle114f0812017-03-08 19:05:07 -0800697static bool analyze_profiles(uid_t uid, const std::string& location, bool is_secondary_dex) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800698 std::vector<unique_fd> profiles_fd;
699 unique_fd reference_profile_fd;
Calin Juravle114f0812017-03-08 19:05:07 -0800700 open_profile_files(uid, location, is_secondary_dex, &profiles_fd, &reference_profile_fd);
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800701 if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700702 // Skip profile guided compilation because no profiles were found.
703 // Or if the reference profile info couldn't be opened.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700704 return false;
705 }
706
Jeff Sharkey90aff262016-12-12 14:28:24 -0700707 pid_t pid = fork();
708 if (pid == 0) {
709 /* child -- drop privileges before continuing */
710 drop_capabilities(uid);
711 run_profman_merge(profiles_fd, reference_profile_fd);
712 exit(68); /* only get here on exec failure */
713 }
714 /* parent */
715 int return_code = wait_child(pid);
716 bool need_to_compile = false;
717 bool should_clear_current_profiles = false;
718 bool should_clear_reference_profile = false;
719 if (!WIFEXITED(return_code)) {
Calin Juravle114f0812017-03-08 19:05:07 -0800720 LOG(WARNING) << "profman failed for location " << location << ": " << return_code;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700721 } else {
722 return_code = WEXITSTATUS(return_code);
723 switch (return_code) {
724 case PROFMAN_BIN_RETURN_CODE_COMPILE:
725 need_to_compile = true;
726 should_clear_current_profiles = true;
727 should_clear_reference_profile = false;
728 break;
729 case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
730 need_to_compile = false;
731 should_clear_current_profiles = false;
732 should_clear_reference_profile = false;
733 break;
734 case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
Calin Juravle114f0812017-03-08 19:05:07 -0800735 LOG(WARNING) << "Bad profiles for location " << location;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700736 need_to_compile = false;
737 should_clear_current_profiles = true;
738 should_clear_reference_profile = true;
739 break;
740 case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall-through
741 case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
742 // Temporary IO problem (e.g. locking). Ignore but log a warning.
Calin Juravle114f0812017-03-08 19:05:07 -0800743 LOG(WARNING) << "IO error while reading profiles for location " << location;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700744 need_to_compile = false;
745 should_clear_current_profiles = false;
746 should_clear_reference_profile = false;
747 break;
748 default:
749 // Unknown return code or error. Unlink profiles.
Calin Juravle114f0812017-03-08 19:05:07 -0800750 LOG(WARNING) << "Unknown error code while processing profiles for location "
751 << location << ": " << return_code;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700752 need_to_compile = false;
753 should_clear_current_profiles = true;
754 should_clear_reference_profile = true;
755 break;
756 }
757 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800758
Jeff Sharkey90aff262016-12-12 14:28:24 -0700759 if (should_clear_current_profiles) {
Calin Juravle114f0812017-03-08 19:05:07 -0800760 if (is_secondary_dex) {
761 // For secondary dex files, the owning user is the current user.
762 clear_current_profile(location, multiuser_get_user_id(uid), is_secondary_dex);
763 } else {
764 clear_primary_current_profiles(location);
765 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700766 }
767 if (should_clear_reference_profile) {
Calin Juravle114f0812017-03-08 19:05:07 -0800768 clear_reference_profile(location, is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700769 }
770 return need_to_compile;
771}
772
Calin Juravle114f0812017-03-08 19:05:07 -0800773// Decides if profile guided compilation is needed or not based on existing profiles.
774// The analysis is done for the primary apks of the given package.
775// Returns true if there is enough information in the current profiles that makes it
776// worth to recompile the package.
777// If the return value is true all the current profiles would have been merged into
778// the reference profiles accessible with open_reference_profile().
779bool analyze_primary_profiles(uid_t uid, const std::string& pkgname) {
780 return analyze_profiles(uid, pkgname, /*is_secondary_dex*/false);
781}
782
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800783static void run_profman_dump(const std::vector<unique_fd>& profile_fds,
784 const unique_fd& reference_profile_fd,
Jeff Sharkey90aff262016-12-12 14:28:24 -0700785 const std::vector<std::string>& dex_locations,
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800786 const std::vector<unique_fd>& apk_fds,
787 const unique_fd& output_fd) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700788 std::vector<std::string> profman_args;
789 static const char* PROFMAN_BIN = "/system/bin/profman";
790 profman_args.push_back(PROFMAN_BIN);
791 profman_args.push_back("--dump-only");
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800792 profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700793 if (reference_profile_fd != -1) {
794 profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d",
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800795 reference_profile_fd.get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700796 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800797 for (size_t i = 0; i < profile_fds.size(); i++) {
798 profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700799 }
800 for (const std::string& dex_location : dex_locations) {
801 profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str()));
802 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800803 for (size_t i = 0; i < apk_fds.size(); i++) {
804 profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700805 }
806 const char **argv = new const char*[profman_args.size() + 1];
807 size_t i = 0;
808 for (const std::string& profman_arg : profman_args) {
809 argv[i++] = profman_arg.c_str();
810 }
811 argv[i] = NULL;
812
813 execv(PROFMAN_BIN, (char * const *)argv);
814 ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
815 exit(68); /* only get here on exec failure */
816}
817
Calin Juravle76268c52017-03-09 13:19:42 -0800818bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800819 std::vector<unique_fd> profile_fds;
820 unique_fd reference_profile_fd;
Calin Juravle76268c52017-03-09 13:19:42 -0800821 std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700822
Calin Juravle114f0812017-03-08 19:05:07 -0800823 open_profile_files(uid, pkgname, /*is_secondary_dex*/false,
824 &profile_fds, &reference_profile_fd);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700825
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800826 const bool has_reference_profile = (reference_profile_fd.get() != -1);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700827 const bool has_profiles = !profile_fds.empty();
828
829 if (!has_reference_profile && !has_profiles) {
Calin Juravle76268c52017-03-09 13:19:42 -0800830 LOG(ERROR) << "profman dump: no profiles to dump for " << pkgname;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700831 return false;
832 }
833
Calin Juravle114f0812017-03-08 19:05:07 -0800834 unique_fd output_fd(open(out_file_name.c_str(),
835 O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700836 if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
837 ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
838 return false;
839 }
840 std::vector<std::string> code_full_paths = base::Split(code_paths, ";");
841 std::vector<std::string> dex_locations;
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800842 std::vector<unique_fd> apk_fds;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700843 for (const std::string& code_full_path : code_full_paths) {
844 const char* full_path = code_full_path.c_str();
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800845 unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700846 if (apk_fd == -1) {
847 ALOGE("installd cannot open '%s'\n", full_path);
848 return false;
849 }
850 dex_locations.push_back(get_location_from_path(full_path));
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800851 apk_fds.push_back(std::move(apk_fd));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700852 }
853
854 pid_t pid = fork();
855 if (pid == 0) {
856 /* child -- drop privileges before continuing */
857 drop_capabilities(uid);
858 run_profman_dump(profile_fds, reference_profile_fd, dex_locations,
859 apk_fds, output_fd);
860 exit(68); /* only get here on exec failure */
861 }
862 /* parent */
Jeff Sharkey90aff262016-12-12 14:28:24 -0700863 int return_code = wait_child(pid);
864 if (!WIFEXITED(return_code)) {
865 LOG(WARNING) << "profman failed for package " << pkgname << ": "
866 << return_code;
867 return false;
868 }
869 return true;
870}
871
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700872bool copy_system_profile(const std::string& system_profile,
873 uid_t packageUid, const std::string& data_profile_location) {
874 unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
875 unique_fd out_fd(open_reference_profile(packageUid,
876 data_profile_location,
877 /*read_write*/ true,
878 /*secondary*/ false));
879 if (in_fd.get() < 0) {
880 PLOG(WARNING) << "Could not open profile " << system_profile;
881 return false;
882 }
883 if (out_fd.get() < 0) {
884 PLOG(WARNING) << "Could not open profile " << data_profile_location;
885 return false;
886 }
887
Mathieu Chartier78f71fe2017-06-14 13:02:26 -0700888 // As a security measure we want to write the profile information with the reduced capabilities
889 // of the package user id. So we fork and drop capabilities in the child.
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700890 pid_t pid = fork();
891 if (pid == 0) {
892 /* child -- drop privileges before continuing */
893 drop_capabilities(packageUid);
894
895 if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
896 if (errno != EWOULDBLOCK) {
897 PLOG(WARNING) << "Error locking profile " << data_profile_location;
898 }
899 // This implies that the app owning this profile is running
900 // (and has acquired the lock).
901 //
902 // The app never acquires the lock for the reference profiles of primary apks.
903 // Only dex2oat from installd will do that. Since installd is single threaded
904 // we should not see this case. Nevertheless be prepared for it.
905 PLOG(WARNING) << "Failed to flock " << data_profile_location;
906 return false;
907 }
908
909 bool truncated = ftruncate(out_fd.get(), 0) == 0;
910 if (!truncated) {
911 PLOG(WARNING) << "Could not truncate " << data_profile_location;
912 }
913
914 // Copy over data.
915 static constexpr size_t kBufferSize = 4 * 1024;
916 char buffer[kBufferSize];
917 while (true) {
918 ssize_t bytes = read(in_fd.get(), buffer, kBufferSize);
919 if (bytes == 0) {
920 break;
921 }
922 write(out_fd.get(), buffer, bytes);
923 }
924 if (flock(out_fd.get(), LOCK_UN) != 0) {
925 PLOG(WARNING) << "Error unlocking profile " << data_profile_location;
926 }
Mathieu Chartier78f71fe2017-06-14 13:02:26 -0700927 // Use _exit since we don't want to run the global destructors in the child.
928 // b/62597429
929 _exit(0);
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700930 }
931 /* parent */
932 int return_code = wait_child(pid);
933 return return_code == 0;
934}
935
Jeff Sharkey90aff262016-12-12 14:28:24 -0700936static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
937 // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
938 if (EndsWith(oat_path, ".dex")) {
939 std::string new_path = oat_path;
940 new_path.replace(new_path.length() - strlen(".dex"), strlen(".dex"), new_ext);
941 CHECK(EndsWith(new_path, new_ext.c_str()));
942 return new_path;
943 }
944
945 // An odex entry. Not that this may not be an extension, e.g., in the OTA
946 // case (where the base name will have an extension for the B artifact).
947 size_t odex_pos = oat_path.rfind(".odex");
948 if (odex_pos != std::string::npos) {
949 std::string new_path = oat_path;
950 new_path.replace(odex_pos, strlen(".odex"), new_ext);
951 CHECK_NE(new_path.find(new_ext), std::string::npos);
952 return new_path;
953 }
954
955 // Don't know how to handle this.
956 return "";
957}
958
959// Translate the given oat path to an art (app image) path. An empty string
960// denotes an error.
961static std::string create_image_filename(const std::string& oat_path) {
962 return replace_file_extension(oat_path, ".art");
963}
964
965// Translate the given oat path to a vdex path. An empty string denotes an error.
966static std::string create_vdex_filename(const std::string& oat_path) {
967 return replace_file_extension(oat_path, ".vdex");
968}
969
Jeff Sharkey90aff262016-12-12 14:28:24 -0700970static int open_output_file(const char* file_name, bool recreate, int permissions) {
971 int flags = O_RDWR | O_CREAT;
972 if (recreate) {
973 if (unlink(file_name) < 0) {
974 if (errno != ENOENT) {
975 PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
976 }
977 }
978 flags |= O_EXCL;
979 }
980 return open(file_name, flags, permissions);
981}
982
Calin Juravle2289c0a2017-02-15 12:44:14 -0800983static bool set_permissions_and_ownership(
984 int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) {
985 // Primary apks are owned by the system. Secondary dex files are owned by the app.
986 int owning_uid = is_secondary_dex ? uid : AID_SYSTEM;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700987 if (fchmod(fd,
988 S_IRUSR|S_IWUSR|S_IRGRP |
989 (is_public ? S_IROTH : 0)) < 0) {
990 ALOGE("installd cannot chmod '%s' during dexopt\n", path);
991 return false;
Calin Juravle2289c0a2017-02-15 12:44:14 -0800992 } else if (fchown(fd, owning_uid, uid) < 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700993 ALOGE("installd cannot chown '%s' during dexopt\n", path);
994 return false;
995 }
996 return true;
997}
998
999static bool IsOutputDalvikCache(const char* oat_dir) {
1000 // InstallerConnection.java (which invokes installd) transforms Java null arguments
1001 // into '!'. Play it safe by handling it both.
1002 // TODO: ensure we never get null.
1003 // TODO: pass a flag instead of inferring if the output is dalvik cache.
1004 return oat_dir == nullptr || oat_dir[0] == '!';
1005}
1006
Calin Juravled23dee72017-07-06 16:29:11 -07001007// Best-effort check whether we can fit the the path into our buffers.
1008// Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
1009// without a swap file, if necessary. Reference profiles file also add an extra ".prof"
1010// extension to the cache path (5 bytes).
1011// TODO(calin): move away from char* buffers and PKG_PATH_MAX.
1012static bool validate_dex_path_size(const std::string& dex_path) {
1013 if (dex_path.size() >= (PKG_PATH_MAX - 8)) {
1014 LOG(ERROR) << "dex_path too long: " << dex_path;
1015 return false;
1016 }
1017 return true;
1018}
1019
Jeff Sharkey90aff262016-12-12 14:28:24 -07001020static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
Calin Juravle80a21252017-01-17 14:43:25 -08001021 const char* oat_dir, bool is_secondary_dex, /*out*/ char* out_oat_path) {
Calin Juravled23dee72017-07-06 16:29:11 -07001022 if (!validate_dex_path_size(apk_path)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001023 return false;
1024 }
1025
1026 if (!IsOutputDalvikCache(oat_dir)) {
Calin Juravle80a21252017-01-17 14:43:25 -08001027 // Oat dirs for secondary dex files are already validated.
1028 if (!is_secondary_dex && validate_apk_path(oat_dir)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001029 ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir);
1030 return false;
1031 }
1032 if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
1033 return false;
1034 }
1035 } else {
1036 if (!create_cache_path(out_oat_path, apk_path, instruction_set)) {
1037 return false;
1038 }
1039 }
1040 return true;
1041}
1042
1043// Helper for fd management. This is similar to a unique_fd in that it closes the file descriptor
1044// on destruction. It will also run the given cleanup (unless told not to) after closing.
1045//
1046// Usage example:
1047//
Calin Juravle7a570e82017-01-14 16:23:30 -08001048// Dex2oatFileWrapper file(open(...),
Jeff Sharkey90aff262016-12-12 14:28:24 -07001049// [name]() {
1050// unlink(name.c_str());
1051// });
1052// // Note: care needs to be taken about name, as it needs to have a lifetime longer than the
1053// wrapper if captured as a reference.
1054//
1055// if (file.get() == -1) {
1056// // Error opening...
1057// }
1058//
1059// ...
1060// if (error) {
1061// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will run
1062// // and delete the file (after the fd is closed).
1063// return -1;
1064// }
1065//
1066// (Success case)
1067// file.SetCleanup(false);
1068// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will not run
1069// // (leaving the file around; after the fd is closed).
1070//
Jeff Sharkey90aff262016-12-12 14:28:24 -07001071class Dex2oatFileWrapper {
1072 public:
Calin Juravle7a570e82017-01-14 16:23:30 -08001073 Dex2oatFileWrapper() : value_(-1), cleanup_(), do_cleanup_(true), auto_close_(true) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001074 }
1075
Calin Juravle7a570e82017-01-14 16:23:30 -08001076 Dex2oatFileWrapper(int value, std::function<void ()> cleanup)
1077 : value_(value), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
1078
1079 Dex2oatFileWrapper(Dex2oatFileWrapper&& other) {
1080 value_ = other.value_;
1081 cleanup_ = other.cleanup_;
1082 do_cleanup_ = other.do_cleanup_;
1083 auto_close_ = other.auto_close_;
1084 other.release();
1085 }
1086
1087 Dex2oatFileWrapper& operator=(Dex2oatFileWrapper&& other) {
1088 value_ = other.value_;
1089 cleanup_ = other.cleanup_;
1090 do_cleanup_ = other.do_cleanup_;
1091 auto_close_ = other.auto_close_;
1092 other.release();
1093 return *this;
1094 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001095
1096 ~Dex2oatFileWrapper() {
1097 reset(-1);
1098 }
1099
1100 int get() {
1101 return value_;
1102 }
1103
1104 void SetCleanup(bool cleanup) {
1105 do_cleanup_ = cleanup;
1106 }
1107
1108 void reset(int new_value) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001109 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001110 close(value_);
1111 }
1112 if (do_cleanup_ && cleanup_ != nullptr) {
1113 cleanup_();
1114 }
1115
1116 value_ = new_value;
1117 }
1118
Calin Juravle7a570e82017-01-14 16:23:30 -08001119 void reset(int new_value, std::function<void ()> new_cleanup) {
1120 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001121 close(value_);
1122 }
1123 if (do_cleanup_ && cleanup_ != nullptr) {
1124 cleanup_();
1125 }
1126
1127 value_ = new_value;
1128 cleanup_ = new_cleanup;
1129 }
1130
Calin Juravle7a570e82017-01-14 16:23:30 -08001131 void DisableAutoClose() {
1132 auto_close_ = false;
1133 }
1134
Jeff Sharkey90aff262016-12-12 14:28:24 -07001135 private:
Calin Juravle7a570e82017-01-14 16:23:30 -08001136 void release() {
1137 value_ = -1;
1138 do_cleanup_ = false;
1139 cleanup_ = nullptr;
1140 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001141 int value_;
Calin Juravle7a570e82017-01-14 16:23:30 -08001142 std::function<void ()> cleanup_;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001143 bool do_cleanup_;
Calin Juravle7a570e82017-01-14 16:23:30 -08001144 bool auto_close_;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001145};
1146
Calin Juravle7a570e82017-01-14 16:23:30 -08001147// (re)Creates the app image if needed.
1148Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided,
Calin Juravle2289c0a2017-02-15 12:44:14 -08001149 bool is_public, int uid, bool is_secondary_dex) {
Nicolas Geoffrayaa17ab42017-08-15 14:51:05 +01001150
1151 // We don't create an image for secondary dex files.
1152 if (is_secondary_dex) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001153 return Dex2oatFileWrapper();
1154 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001155
Calin Juravle7a570e82017-01-14 16:23:30 -08001156 const std::string image_path = create_image_filename(out_oat_path);
1157 if (image_path.empty()) {
1158 // Happens when the out_oat_path has an unknown extension.
1159 return Dex2oatFileWrapper();
1160 }
Nicolas Geoffrayaa17ab42017-08-15 14:51:05 +01001161
1162 // Use app images only if it is enabled (by a set image format) and we are compiling
1163 // profile-guided (so the app image doesn't conservatively contain all classes).
1164 if (!profile_guided) {
1165 // In case there is a stale image, remove it now. Ignore any error.
1166 unlink(image_path.c_str());
1167 return Dex2oatFileWrapper();
1168 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001169 char app_image_format[kPropertyValueMax];
1170 bool have_app_image_format =
1171 get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
1172 if (!have_app_image_format) {
1173 return Dex2oatFileWrapper();
1174 }
1175 // Recreate is true since we do not want to modify a mapped image. If the app is
1176 // already running and we modify the image file, it can cause crashes (b/27493510).
1177 Dex2oatFileWrapper wrapper_fd(
1178 open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
1179 [image_path]() { unlink(image_path.c_str()); });
1180 if (wrapper_fd.get() < 0) {
1181 // Could not create application image file. Go on since we can compile without it.
1182 LOG(ERROR) << "installd could not create '" << image_path
1183 << "' for image file during dexopt";
1184 // If we have a valid image file path but no image fd, explicitly erase the image file.
1185 if (unlink(image_path.c_str()) < 0) {
1186 if (errno != ENOENT) {
1187 PLOG(ERROR) << "Couldn't unlink image file " << image_path;
1188 }
1189 }
1190 } else if (!set_permissions_and_ownership(
Calin Juravle2289c0a2017-02-15 12:44:14 -08001191 wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001192 ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
1193 wrapper_fd.reset(-1);
1194 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001195
Calin Juravle7a570e82017-01-14 16:23:30 -08001196 return wrapper_fd;
1197}
1198
1199// Creates the dexopt swap file if necessary and return its fd.
1200// Returns -1 if there's no need for a swap or in case of errors.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001201unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001202 if (!ShouldUseSwapFileForDexopt()) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001203 return invalid_unique_fd();
Calin Juravle7a570e82017-01-14 16:23:30 -08001204 }
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06001205 auto swap_file_name = std::string(out_oat_path) + ".swap";
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001206 unique_fd swap_fd(open_output_file(
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06001207 swap_file_name.c_str(), /*recreate*/true, /*permissions*/0600));
Calin Juravle7a570e82017-01-14 16:23:30 -08001208 if (swap_fd.get() < 0) {
1209 // Could not create swap file. Optimistically go on and hope that we can compile
1210 // without it.
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06001211 ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name.c_str());
Calin Juravle7a570e82017-01-14 16:23:30 -08001212 } else {
1213 // Immediately unlink. We don't really want to hit flash.
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06001214 if (unlink(swap_file_name.c_str()) < 0) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001215 PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
1216 }
1217 }
1218 return swap_fd;
1219}
1220
1221// Opens the reference profiles if needed.
1222// Note that the reference profile might not exist so it's OK if the fd will be -1.
Calin Juravle114f0812017-03-08 19:05:07 -08001223Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname,
1224 const std::string& dex_path, bool profile_guided, bool is_public, int uid,
1225 bool is_secondary_dex) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001226 // Public apps should not be compiled with profile information ever. Same goes for the special
1227 // package '*' used for the system server.
Calin Juravle114f0812017-03-08 19:05:07 -08001228 if (!profile_guided || is_public || (pkgname[0] == '*')) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001229 return Dex2oatFileWrapper();
Jeff Sharkey90aff262016-12-12 14:28:24 -07001230 }
Calin Juravle114f0812017-03-08 19:05:07 -08001231
1232 // Open reference profile in read only mode as dex2oat does not get write permissions.
1233 const std::string location = is_secondary_dex ? dex_path : pkgname;
1234 unique_fd ufd = open_reference_profile(uid, location, /*read_write*/false, is_secondary_dex);
1235 const auto& cleanup = [location, is_secondary_dex]() {
1236 clear_reference_profile(location.c_str(), is_secondary_dex);
1237 };
1238 return Dex2oatFileWrapper(ufd.release(), cleanup);
Calin Juravle7a570e82017-01-14 16:23:30 -08001239}
Jeff Sharkey90aff262016-12-12 14:28:24 -07001240
Calin Juravle7a570e82017-01-14 16:23:30 -08001241// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
1242// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001243bool open_vdex_files_for_dex2oat(const char* apk_path, const char* out_oat_path, int dexopt_needed,
Nicolas Geoffray3c95f2d2017-04-24 13:34:59 +00001244 const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001245 bool profile_guided, Dex2oatFileWrapper* in_vdex_wrapper_fd,
Calin Juravle7a570e82017-01-14 16:23:30 -08001246 Dex2oatFileWrapper* out_vdex_wrapper_fd) {
1247 CHECK(in_vdex_wrapper_fd != nullptr);
1248 CHECK(out_vdex_wrapper_fd != nullptr);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001249 // Open the existing VDEX. We do this before creating the new output VDEX, which will
1250 // unlink the old one.
Richard Uhler76cc0272016-12-08 10:46:35 +00001251 char in_odex_path[PKG_PATH_MAX];
1252 int dexopt_action = abs(dexopt_needed);
1253 bool is_odex_location = dexopt_needed < 0;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001254 std::string in_vdex_path_str;
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001255
1256 // Infer the name of the output VDEX.
1257 const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
1258 if (out_vdex_path_str.empty()) {
1259 return false;
1260 }
1261
1262 bool update_vdex_in_place = false;
Nicolas Geoffray3c95f2d2017-04-24 13:34:59 +00001263 if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001264 // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
1265 const char* path = nullptr;
1266 if (is_odex_location) {
1267 if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1268 path = in_odex_path;
1269 } else {
1270 ALOGE("installd cannot compute input vdex location for '%s'\n", apk_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001271 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001272 }
1273 } else {
1274 path = out_oat_path;
1275 }
1276 in_vdex_path_str = create_vdex_filename(path);
1277 if (in_vdex_path_str.empty()) {
1278 ALOGE("installd cannot compute input vdex location for '%s'\n", path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001279 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001280 }
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001281 // We can update in place when all these conditions are met:
1282 // 1) The vdex location to write to is the same as the vdex location to read (vdex files
1283 // on /system typically cannot be updated in place).
1284 // 2) We dex2oat due to boot image change, because we then know the existing vdex file
1285 // cannot be currently used by a running process.
1286 // 3) We are not doing a profile guided compilation, because dexlayout requires two
1287 // different vdex files to operate.
1288 update_vdex_in_place =
1289 (in_vdex_path_str == out_vdex_path_str) &&
1290 (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) &&
1291 !profile_guided;
1292 if (update_vdex_in_place) {
1293 // Open the file read-write to be able to update it.
1294 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
1295 if (in_vdex_wrapper_fd->get() == -1) {
1296 // If we failed to open the file, we cannot update it in place.
1297 update_vdex_in_place = false;
1298 }
1299 } else {
1300 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
1301 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001302 }
1303
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001304 // If we are updating the vdex in place, we do not need to recreate a vdex,
1305 // and can use the same existing one.
1306 if (update_vdex_in_place) {
1307 // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
1308 // have bogus stale vdex files.
1309 out_vdex_wrapper_fd->reset(
1310 in_vdex_wrapper_fd->get(),
1311 [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
1312 // Disable auto close for the in wrapper fd (it will be done when destructing the out
1313 // wrapper).
1314 in_vdex_wrapper_fd->DisableAutoClose();
1315 } else {
1316 out_vdex_wrapper_fd->reset(
1317 open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
1318 [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
1319 if (out_vdex_wrapper_fd->get() < 0) {
1320 ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
1321 return false;
1322 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001323 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001324 if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
Calin Juravle2289c0a2017-02-15 12:44:14 -08001325 out_vdex_path_str.c_str(), is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001326 ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
1327 return false;
1328 }
1329
1330 // If we got here we successfully opened the vdex files.
1331 return true;
1332}
1333
1334// Opens the output oat file for the given apk.
1335// If successful it stores the output path into out_oat_path and returns true.
1336Dex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir,
Calin Juravle80a21252017-01-17 14:43:25 -08001337 bool is_public, int uid, const char* instruction_set, bool is_secondary_dex,
1338 char* out_oat_path) {
1339 if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001340 return Dex2oatFileWrapper();
1341 }
1342 const std::string out_oat_path_str(out_oat_path);
1343 Dex2oatFileWrapper wrapper_fd(
1344 open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
1345 [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
1346 if (wrapper_fd.get() < 0) {
Calin Juravle80a21252017-01-17 14:43:25 -08001347 PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path;
Calin Juravle2289c0a2017-02-15 12:44:14 -08001348 } else if (!set_permissions_and_ownership(
1349 wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001350 ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
1351 wrapper_fd.reset(-1);
1352 }
1353 return wrapper_fd;
1354}
1355
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001356// Creates RDONLY fds for oat and vdex files, if exist.
1357// Returns false if it fails to create oat out path for the given apk path.
1358// Note that the method returns true even if the files could not be opened.
1359bool maybe_open_oat_and_vdex_file(const std::string& apk_path,
1360 const std::string& oat_dir,
1361 const std::string& instruction_set,
1362 bool is_secondary_dex,
1363 unique_fd* oat_file_fd,
1364 unique_fd* vdex_file_fd) {
1365 char oat_path[PKG_PATH_MAX];
1366 if (!create_oat_out_path(apk_path.c_str(),
1367 instruction_set.c_str(),
1368 oat_dir.c_str(),
1369 is_secondary_dex,
1370 oat_path)) {
1371 return false;
1372 }
1373 oat_file_fd->reset(open(oat_path, O_RDONLY));
1374 if (oat_file_fd->get() < 0) {
1375 PLOG(INFO) << "installd cannot open oat file during dexopt" << oat_path;
1376 }
1377
1378 std::string vdex_filename = create_vdex_filename(oat_path);
1379 vdex_file_fd->reset(open(vdex_filename.c_str(), O_RDONLY));
1380 if (vdex_file_fd->get() < 0) {
1381 PLOG(INFO) << "installd cannot open vdex file during dexopt" << vdex_filename;
1382 }
1383
1384 return true;
1385}
1386
Calin Juravle7a570e82017-01-14 16:23:30 -08001387// Updates the access times of out_oat_path based on those from apk_path.
1388void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
1389 struct stat input_stat;
1390 memset(&input_stat, 0, sizeof(input_stat));
1391 if (stat(apk_path, &input_stat) != 0) {
1392 PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
1393 return;
1394 }
1395
1396 struct utimbuf ut;
1397 ut.actime = input_stat.st_atime;
1398 ut.modtime = input_stat.st_mtime;
1399 if (utime(out_oat_path, &ut) != 0) {
1400 PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
1401 }
1402}
1403
Calin Juravle80a21252017-01-17 14:43:25 -08001404// Runs (execv) dexoptanalyzer on the given arguments.
Calin Juravle114f0812017-03-08 19:05:07 -08001405// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
1406// If this is for a profile guided compilation, profile_was_updated will tell whether or not
1407// the profile has changed.
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001408static void exec_dexoptanalyzer(const std::string& dex_file, int vdex_fd, int oat_fd,
1409 int zip_fd, const std::string& instruction_set, const std::string& compiler_filter,
1410 bool profile_was_updated, bool downgrade,
Calin Juravle58cab072017-09-12 01:02:26 -07001411 const char* class_loader_context) {
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001412 CHECK_GE(zip_fd, 0);
Andreas Gampe6a9cf722017-07-24 16:49:10 -07001413 const char* dexoptanalyzer_bin =
1414 is_debug_runtime()
1415 ? "/system/bin/dexoptanalyzerd"
1416 : "/system/bin/dexoptanalyzer";
Calin Juravle80a21252017-01-17 14:43:25 -08001417 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
1418
Calin Juravled23dee72017-07-06 16:29:11 -07001419 if (instruction_set.size() >= MAX_INSTRUCTION_SET_LEN) {
1420 LOG(ERROR) << "Instruction set " << instruction_set
1421 << " longer than max length of " << MAX_INSTRUCTION_SET_LEN;
Calin Juravle80a21252017-01-17 14:43:25 -08001422 return;
1423 }
1424
Calin Juravled23dee72017-07-06 16:29:11 -07001425 std::string dex_file_arg = "--dex-file=" + dex_file;
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001426 std::string oat_fd_arg = "--oat-fd=" + std::to_string(oat_fd);
1427 std::string vdex_fd_arg = "--vdex-fd=" + std::to_string(vdex_fd);
1428 std::string zip_fd_arg = "--zip-fd=" + std::to_string(zip_fd);
Calin Juravled23dee72017-07-06 16:29:11 -07001429 std::string isa_arg = "--isa=" + instruction_set;
1430 std::string compiler_filter_arg = "--compiler-filter=" + compiler_filter;
Calin Juravle114f0812017-03-08 19:05:07 -08001431 const char* assume_profile_changed = "--assume-profile-changed";
Shubham Ajmera54ef8622017-06-22 11:10:27 -07001432 const char* downgrade_flag = "--downgrade";
Calin Juravle58cab072017-09-12 01:02:26 -07001433 std::string class_loader_context_arg = "--class-loader-context=";
1434 if (class_loader_context != nullptr) {
1435 class_loader_context_arg += class_loader_context;
1436 }
Calin Juravle80a21252017-01-17 14:43:25 -08001437
Calin Juravle80a21252017-01-17 14:43:25 -08001438 // program name, dex file, isa, filter, the final NULL
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001439 const int argc = 6 +
Shubham Ajmera54ef8622017-06-22 11:10:27 -07001440 (profile_was_updated ? 1 : 0) +
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001441 (vdex_fd >= 0 ? 1 : 0) +
1442 (oat_fd >= 0 ? 1 : 0) +
Calin Juravle58cab072017-09-12 01:02:26 -07001443 (downgrade ? 1 : 0) +
1444 (class_loader_context != nullptr ? 1 : 0);
Shubham Ajmera54ef8622017-06-22 11:10:27 -07001445 const char* argv[argc];
Calin Juravle80a21252017-01-17 14:43:25 -08001446 int i = 0;
Andreas Gampe6a9cf722017-07-24 16:49:10 -07001447 argv[i++] = dexoptanalyzer_bin;
Calin Juravled23dee72017-07-06 16:29:11 -07001448 argv[i++] = dex_file_arg.c_str();
1449 argv[i++] = isa_arg.c_str();
1450 argv[i++] = compiler_filter_arg.c_str();
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001451 if (oat_fd >= 0) {
1452 argv[i++] = oat_fd_arg.c_str();
1453 }
1454 if (vdex_fd >= 0) {
1455 argv[i++] = vdex_fd_arg.c_str();
1456 }
1457 argv[i++] = zip_fd_arg.c_str();
Calin Juravle114f0812017-03-08 19:05:07 -08001458 if (profile_was_updated) {
1459 argv[i++] = assume_profile_changed;
1460 }
Shubham Ajmera54ef8622017-06-22 11:10:27 -07001461 if (downgrade) {
1462 argv[i++] = downgrade_flag;
1463 }
Calin Juravle58cab072017-09-12 01:02:26 -07001464 if (class_loader_context != nullptr) {
Calin Juravle91501072017-10-26 15:44:53 -07001465 argv[i++] = class_loader_context_arg.c_str();
Calin Juravle58cab072017-09-12 01:02:26 -07001466 }
Calin Juravle80a21252017-01-17 14:43:25 -08001467 argv[i] = NULL;
1468
Andreas Gampe6a9cf722017-07-24 16:49:10 -07001469 execv(dexoptanalyzer_bin, (char * const *)argv);
1470 ALOGE("execv(%s) failed: %s\n", dexoptanalyzer_bin, strerror(errno));
Calin Juravle80a21252017-01-17 14:43:25 -08001471}
1472
1473// Prepares the oat dir for the secondary dex files.
Calin Juravle114f0812017-03-08 19:05:07 -08001474static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid,
1475 const char* instruction_set, std::string* oat_dir_out) {
1476 unsigned long dirIndex = dex_path.rfind('/');
Calin Juravle80a21252017-01-17 14:43:25 -08001477 if (dirIndex == std::string::npos) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001478 LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001479 return false;
1480 }
Calin Juravle114f0812017-03-08 19:05:07 -08001481 std::string dex_dir = dex_path.substr(0, dirIndex);
Calin Juravle80a21252017-01-17 14:43:25 -08001482
Calin Juravle80a21252017-01-17 14:43:25 -08001483 // Create oat file output directory.
Calin Juravleebc8a792017-04-04 20:21:05 -07001484 mode_t oat_dir_mode = S_IRWXU | S_IRWXG | S_IXOTH;
1485 if (prepare_app_cache_dir(dex_dir, "oat", oat_dir_mode, uid, uid) != 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001486 LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001487 return false;
1488 }
1489
1490 char oat_dir[PKG_PATH_MAX];
Calin Juravle114f0812017-03-08 19:05:07 -08001491 snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", dex_dir.c_str());
Calin Juravle80a21252017-01-17 14:43:25 -08001492 oat_dir_out->assign(oat_dir);
1493
1494 // Create oat/isa output directory.
Calin Juravleebc8a792017-04-04 20:21:05 -07001495 if (prepare_app_cache_dir(*oat_dir_out, instruction_set, oat_dir_mode, uid, uid) != 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001496 LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001497 return false;
1498 }
1499
1500 return true;
1501}
1502
1503static int constexpr DEXOPTANALYZER_BIN_EXEC_ERROR = 200;
1504
1505// Verifies the result of dexoptanalyzer executed for the apk_path.
1506// If the result is valid returns true and sets dexopt_needed_out to a valid value.
1507// Returns false for errors or unexpected result values.
Calin Juravle114f0812017-03-08 19:05:07 -08001508static bool process_dexoptanalyzer_result(const std::string& dex_path, int result,
Calin Juravle80a21252017-01-17 14:43:25 -08001509 int* dexopt_needed_out) {
1510 // The result values are defined in dexoptanalyzer.
1511 switch (result) {
1512 case 0: // no_dexopt_needed
1513 *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
1514 case 1: // dex2oat_from_scratch
1515 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
1516 case 5: // dex2oat_for_bootimage_odex
1517 *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
1518 case 6: // dex2oat_for_filter_odex
1519 *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
1520 case 7: // dex2oat_for_relocation_odex
1521 *dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
1522 case 2: // dex2oat_for_bootimage_oat
1523 case 3: // dex2oat_for_filter_oat
1524 case 4: // dex2oat_for_relocation_oat
Calin Juravlec9eab382017-01-25 01:17:17 -08001525 LOG(ERROR) << "Dexoptnalyzer return the status of an oat file."
1526 << " Expected odex file status for secondary dex " << dex_path
Calin Juravle80a21252017-01-17 14:43:25 -08001527 << " : dexoptanalyzer result=" << result;
1528 return false;
1529 default:
Calin Juravlec9eab382017-01-25 01:17:17 -08001530 LOG(ERROR) << "Unexpected result for dexoptanalyzer " << dex_path
Calin Juravle80a21252017-01-17 14:43:25 -08001531 << " exec_dexoptanalyzer result=" << result;
1532 return false;
1533 }
1534}
1535
Calin Juravlec9eab382017-01-25 01:17:17 -08001536// Processes the dex_path as a secondary dex files and return true if the path dex file should
Calin Juravle80a21252017-01-17 14:43:25 -08001537// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
1538// successfully.
Calin Juravleebc8a792017-04-04 20:21:05 -07001539// When returning true, the output parameters will be:
1540// - is_public_out: whether or not the oat file should not be made public
1541// - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
1542// - oat_dir_out: the oat dir path where the oat file should be stored
1543// - dex_path_out: the real path of the dex file
Calin Juravle114f0812017-03-08 19:05:07 -08001544static bool process_secondary_dex_dexopt(const char* original_dex_path, const char* pkgname,
Calin Juravle80a21252017-01-17 14:43:25 -08001545 int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
Calin Juravleebc8a792017-04-04 20:21:05 -07001546 const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
Calin Juravle58cab072017-09-12 01:02:26 -07001547 std::string* oat_dir_out, std::string* dex_path_out, bool downgrade,
1548 const char* class_loader_context) {
Calin Juravle80a21252017-01-17 14:43:25 -08001549 int storage_flag;
1550
1551 if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
1552 storage_flag = FLAG_STORAGE_CE;
1553 if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1554 LOG(ERROR) << "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
1555 return false;
1556 }
1557 } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1558 storage_flag = FLAG_STORAGE_DE;
1559 } else {
1560 LOG(ERROR) << "Secondary dex storage flag must be set";
1561 return false;
1562 }
1563
Calin Juravle114f0812017-03-08 19:05:07 -08001564 {
1565 // As opposed to the primary apk, secondary dex files might contain symlinks.
1566 // Resolve the path before passing it to the validate method to
1567 // make sure the verification is done on the real location.
1568 UniqueCPtr<char> dex_real_path_cstr(realpath(original_dex_path, nullptr));
1569 if (dex_real_path_cstr == nullptr) {
1570 PLOG(ERROR) << "Could not get the real path of the secondary dex file "
1571 << original_dex_path;
1572 return false;
1573 } else {
1574 dex_path_out->assign(dex_real_path_cstr.get());
1575 }
1576 }
1577 const std::string& dex_path = *dex_path_out;
Calin Juravled23dee72017-07-06 16:29:11 -07001578 if (!validate_dex_path_size(dex_path)) {
1579 return false;
1580 }
Calin Juravlec9eab382017-01-25 01:17:17 -08001581 if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
1582 LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001583 return false;
1584 }
1585
1586 // Check if the path exist. If not, there's nothing to do.
Calin Juravleebc8a792017-04-04 20:21:05 -07001587 struct stat dex_path_stat;
1588 if (stat(dex_path.c_str(), &dex_path_stat) != 0) {
Calin Juravle80a21252017-01-17 14:43:25 -08001589 if (errno == ENOENT) {
1590 // Secondary dex files might be deleted any time by the app.
1591 // Nothing to do if that's the case
Calin Juravle114f0812017-03-08 19:05:07 -08001592 ALOGV("Secondary dex does not exist %s", dex_path.c_str());
Calin Juravle80a21252017-01-17 14:43:25 -08001593 return NO_DEXOPT_NEEDED;
1594 } else {
Calin Juravlec9eab382017-01-25 01:17:17 -08001595 PLOG(ERROR) << "Could not access secondary dex " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001596 }
1597 }
1598
Calin Juravleebc8a792017-04-04 20:21:05 -07001599 // Check if we should make the oat file public.
1600 // Note that if the dex file is not public the compiled code cannot be made public.
1601 *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) &&
1602 ((dex_path_stat.st_mode & S_IROTH) != 0);
1603
Calin Juravle80a21252017-01-17 14:43:25 -08001604 // Prepare the oat directories.
Calin Juravle114f0812017-03-08 19:05:07 -08001605 if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, oat_dir_out)) {
Calin Juravle80a21252017-01-17 14:43:25 -08001606 return false;
1607 }
1608
Calin Juravle114f0812017-03-08 19:05:07 -08001609 // Analyze profiles.
1610 bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true);
1611
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001612 unique_fd oat_file_fd;
1613 unique_fd vdex_file_fd;
1614 unique_fd zip_fd;
1615 zip_fd.reset(open(dex_path.c_str(), O_RDONLY));
1616 if (zip_fd.get() < 0) {
1617 PLOG(ERROR) << "installd cannot open " << dex_path << " for input during dexopt";
1618 return false;
1619 }
1620 if (!maybe_open_oat_and_vdex_file(dex_path,
1621 *oat_dir_out,
1622 instruction_set,
1623 true /* is_secondary_dex */,
1624 &oat_file_fd,
1625 &vdex_file_fd)) {
1626 return false;
1627 }
1628
Calin Juravle80a21252017-01-17 14:43:25 -08001629 pid_t pid = fork();
1630 if (pid == 0) {
1631 // child -- drop privileges before continuing.
1632 drop_capabilities(uid);
1633 // Run dexoptanalyzer to get dexopt_needed code.
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001634 exec_dexoptanalyzer(dex_path,
1635 vdex_file_fd.get(),
1636 oat_file_fd.get(),
1637 zip_fd.get(),
1638 instruction_set,
1639 compiler_filter,
1640 profile_was_updated,
Calin Juravle58cab072017-09-12 01:02:26 -07001641 downgrade, class_loader_context);
Calin Juravle80a21252017-01-17 14:43:25 -08001642 exit(DEXOPTANALYZER_BIN_EXEC_ERROR);
1643 }
1644
1645 /* parent */
1646
1647 int result = wait_child(pid);
1648 if (!WIFEXITED(result)) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001649 LOG(ERROR) << "dexoptanalyzer failed for path " << dex_path << ": " << result;
Calin Juravle80a21252017-01-17 14:43:25 -08001650 return false;
1651 }
1652 result = WEXITSTATUS(result);
Calin Juravlec9eab382017-01-25 01:17:17 -08001653 bool success = process_dexoptanalyzer_result(dex_path, result, dexopt_needed_out);
Calin Juravle80a21252017-01-17 14:43:25 -08001654 // Run dexopt only if needed or forced.
1655 // Note that dexoptanalyzer is executed even if force compilation is enabled.
1656 // We ignore its valid dexopNeeded result, but still check (in process_dexoptanalyzer_result)
1657 // that we only get results for odex files (apk_dir/oat/isa/code.odex) and not
1658 // for oat files from dalvik-cache.
1659 if (success && ((dexopt_flags & DEXOPT_FORCE) != 0)) {
1660 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
1661 }
1662
1663 return success;
1664}
1665
Calin Juravlec9eab382017-01-25 01:17:17 -08001666int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
Calin Juravle80a21252017-01-17 14:43:25 -08001667 int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
Calin Juravle52c45822017-07-13 22:50:21 -07001668 const char* volume_uuid, const char* class_loader_context, const char* se_info,
Shubham Ajmera54ef8622017-06-22 11:10:27 -07001669 bool downgrade) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001670 CHECK(pkgname != nullptr);
1671 CHECK(pkgname[0] != 0);
1672 if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
1673 LOG_FATAL("dexopt flags contains unknown fields\n");
1674 }
1675
Calin Juravled23dee72017-07-06 16:29:11 -07001676 if (!validate_dex_path_size(dex_path)) {
Calin Juravle52c45822017-07-13 22:50:21 -07001677 return -1;
1678 }
1679
1680 if (class_loader_context != nullptr && strlen(class_loader_context) > PKG_PATH_MAX) {
1681 LOG(ERROR) << "Class loader context exceeds the allowed size: " << class_loader_context;
1682 return -1;
Calin Juravled23dee72017-07-06 16:29:11 -07001683 }
1684
Calin Juravleebc8a792017-04-04 20:21:05 -07001685 bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
Calin Juravle7a570e82017-01-14 16:23:30 -08001686 bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
1687 bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
1688 bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
Calin Juravle80a21252017-01-17 14:43:25 -08001689 bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
Andreas Gampea73a0cb2017-11-02 18:14:42 -07001690 bool background_job_compile = (dexopt_flags & DEXOPT_IDLE_BACKGROUND_JOB) != 0;
Calin Juravle80a21252017-01-17 14:43:25 -08001691
1692 // Check if we're dealing with a secondary dex file and if we need to compile it.
1693 std::string oat_dir_str;
Calin Juravle114f0812017-03-08 19:05:07 -08001694 std::string dex_real_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001695 if (is_secondary_dex) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001696 if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
Calin Juravleebc8a792017-04-04 20:21:05 -07001697 instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
Calin Juravle58cab072017-09-12 01:02:26 -07001698 &dex_real_path, downgrade, class_loader_context)) {
Calin Juravle80a21252017-01-17 14:43:25 -08001699 oat_dir = oat_dir_str.c_str();
Calin Juravle114f0812017-03-08 19:05:07 -08001700 dex_path = dex_real_path.c_str();
Calin Juravle80a21252017-01-17 14:43:25 -08001701 if (dexopt_needed == NO_DEXOPT_NEEDED) {
1702 return 0; // Nothing to do, report success.
1703 }
1704 } else {
1705 return -1; // We had an error, logged in the process method.
1706 }
1707 } else {
Calin Juravlec9eab382017-01-25 01:17:17 -08001708 // Currently these flags are only use for secondary dex files.
1709 // Verify that they are not set for primary apks.
Calin Juravle80a21252017-01-17 14:43:25 -08001710 CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
1711 CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
1712 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001713
1714 // Open the input file.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001715 unique_fd input_fd(open(dex_path, O_RDONLY, 0));
Calin Juravle7a570e82017-01-14 16:23:30 -08001716 if (input_fd.get() < 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001717 ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001718 return -1;
1719 }
1720
1721 // Create the output OAT file.
1722 char out_oat_path[PKG_PATH_MAX];
Calin Juravlec9eab382017-01-25 01:17:17 -08001723 Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
Calin Juravle80a21252017-01-17 14:43:25 -08001724 instruction_set, is_secondary_dex, out_oat_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001725 if (out_oat_fd.get() < 0) {
1726 return -1;
1727 }
1728
1729 // Open vdex files.
1730 Dex2oatFileWrapper in_vdex_fd;
1731 Dex2oatFileWrapper out_vdex_fd;
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001732 if (!open_vdex_files_for_dex2oat(dex_path, out_oat_path, dexopt_needed, instruction_set,
1733 is_public, uid, is_secondary_dex, profile_guided, &in_vdex_fd, &out_vdex_fd)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001734 return -1;
1735 }
1736
Calin Juravlecb556e32017-04-04 20:22:50 -07001737 // Ensure that the oat dir and the compiler artifacts of secondary dex files have the correct
1738 // selinux context (we generate them on the fly during the dexopt invocation and they don't
1739 // fully inherit their parent context).
1740 // Note that for primary apk the oat files are created before, in a separate installd
1741 // call which also does the restorecon. TODO(calin): unify the paths.
1742 if (is_secondary_dex) {
1743 if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
1744 SELINUX_ANDROID_RESTORECON_RECURSE)) {
1745 LOG(ERROR) << "Failed to restorecon " << oat_dir;
1746 return -1;
1747 }
1748 }
1749
Jeff Sharkey90aff262016-12-12 14:28:24 -07001750 // Create a swap file if necessary.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001751 unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001752
Calin Juravle7a570e82017-01-14 16:23:30 -08001753 // Create the app image file if needed.
1754 Dex2oatFileWrapper image_fd =
Calin Juravle2289c0a2017-02-15 12:44:14 -08001755 maybe_open_app_image(out_oat_path, profile_guided, is_public, uid, is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001756
Calin Juravle7a570e82017-01-14 16:23:30 -08001757 // Open the reference profile if needed.
Calin Juravle114f0812017-03-08 19:05:07 -08001758 Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
1759 pkgname, dex_path, profile_guided, is_public, uid, is_secondary_dex);
Calin Juravle7a570e82017-01-14 16:23:30 -08001760
Calin Juravlec9eab382017-01-25 01:17:17 -08001761 ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001762
1763 pid_t pid = fork();
1764 if (pid == 0) {
1765 /* child -- drop privileges before continuing */
1766 drop_capabilities(uid);
1767
Richard Uhler76cc0272016-12-08 10:46:35 +00001768 SetDex2OatScheduling(boot_complete);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001769 if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
1770 ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
1771 _exit(67);
1772 }
1773
Richard Uhler76cc0272016-12-08 10:46:35 +00001774 run_dex2oat(input_fd.get(),
1775 out_oat_fd.get(),
1776 in_vdex_fd.get(),
Calin Juravle7a570e82017-01-14 16:23:30 -08001777 out_vdex_fd.get(),
Richard Uhler76cc0272016-12-08 10:46:35 +00001778 image_fd.get(),
Jeff Hao10b8a6e2017-04-05 17:11:39 -07001779 dex_path,
Richard Uhler76cc0272016-12-08 10:46:35 +00001780 out_oat_path,
1781 swap_fd.get(),
1782 instruction_set,
1783 compiler_filter,
Richard Uhler76cc0272016-12-08 10:46:35 +00001784 debuggable,
1785 boot_complete,
Andreas Gampea73a0cb2017-11-02 18:14:42 -07001786 background_job_compile,
Richard Uhler76cc0272016-12-08 10:46:35 +00001787 reference_profile_fd.get(),
Calin Juravle52c45822017-07-13 22:50:21 -07001788 class_loader_context);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001789 _exit(68); /* only get here on exec failure */
1790 } else {
1791 int res = wait_child(pid);
1792 if (res == 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001793 ALOGV("DexInv: --- END '%s' (success) ---\n", dex_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001794 } else {
Calin Juravlec9eab382017-01-25 01:17:17 -08001795 ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", dex_path, res);
Andreas Gampe013f02e2017-03-20 18:36:54 -07001796 return res;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001797 }
1798 }
1799
Calin Juravlec9eab382017-01-25 01:17:17 -08001800 update_out_oat_access_times(dex_path, out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001801
1802 // We've been successful, don't delete output.
1803 out_oat_fd.SetCleanup(false);
Calin Juravle7a570e82017-01-14 16:23:30 -08001804 out_vdex_fd.SetCleanup(false);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001805 image_fd.SetCleanup(false);
1806 reference_profile_fd.SetCleanup(false);
1807
1808 return 0;
1809}
1810
Calin Juravlec9eab382017-01-25 01:17:17 -08001811// Try to remove the given directory. Log an error if the directory exists
1812// and is empty but could not be removed.
1813static bool rmdir_if_empty(const char* dir) {
1814 if (rmdir(dir) == 0) {
1815 return true;
1816 }
1817 if (errno == ENOENT || errno == ENOTEMPTY) {
1818 return true;
1819 }
1820 PLOG(ERROR) << "Failed to remove dir: " << dir;
1821 return false;
1822}
1823
1824// Try to unlink the given file. Log an error if the file exists and could not
1825// be unlinked.
1826static bool unlink_if_exists(const std::string& file) {
1827 if (unlink(file.c_str()) == 0) {
1828 return true;
1829 }
1830 if (errno == ENOENT) {
1831 return true;
1832
1833 }
1834 PLOG(ERROR) << "Could not unlink: " << file;
1835 return false;
1836}
1837
1838// Create the oat file structure for the secondary dex 'dex_path' and assign
1839// the individual path component to the 'out_' parameters.
1840static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
1841 /*out*/char* out_oat_dir, /*out*/char* out_oat_isa_dir, /*out*/char* out_oat_path) {
1842 size_t dirIndex = dex_path.rfind('/');
1843 if (dirIndex == std::string::npos) {
1844 LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path;
1845 return false;
1846 }
1847 // TODO(calin): we have similar computations in at lest 3 other places
1848 // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by
1849 // use string append.
1850 std::string apk_dir = dex_path.substr(0, dirIndex);
1851 snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
1852 snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
1853
1854 if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
Calin Juravle114f0812017-03-08 19:05:07 -08001855 /*is_secondary_dex*/true, out_oat_path)) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001856 LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path;
1857 return false;
1858 }
1859 return true;
1860}
1861
1862// Reconcile the secondary dex 'dex_path' and its generated oat files.
1863// Return true if all the parameters are valid and the secondary dex file was
1864// processed successfully (i.e. the dex_path either exists, or if not, its corresponding
1865// oat/vdex/art files where deleted successfully). In this case, out_secondary_dex_exists
1866// will be true if the secondary dex file still exists. If the secondary dex file does not exist,
1867// the method cleans up any previously generated compiler artifacts (oat, vdex, art).
1868// Return false if there were errors during processing. In this case
1869// out_secondary_dex_exists will be set to false.
1870bool reconcile_secondary_dex_file(const std::string& dex_path,
1871 const std::string& pkgname, int uid, const std::vector<std::string>& isas,
1872 const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
1873 /*out*/bool* out_secondary_dex_exists) {
1874 // Set out to false to start with, just in case we have validation errors.
1875 *out_secondary_dex_exists = false;
Calin Juravled23dee72017-07-06 16:29:11 -07001876 if (!validate_dex_path_size(dex_path)) {
1877 return false;
1878 }
1879
Calin Juravlec9eab382017-01-25 01:17:17 -08001880 if (isas.size() == 0) {
1881 LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector";
1882 return false;
1883 }
1884
1885 const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
Calin Juravledd42e272017-09-11 11:50:36 -07001886
1887 // Note that we cannot validate the package path here because the file might not exist
1888 // and we cannot call realpath to resolve system symlinks. Since /data/user/0 symlinks to
1889 // /data/data/ a lot of validations will fail if we attempt to check the package path.
1890 // It is still ok to be more relaxed because any file removal is done after forking and
1891 // dropping capabilities.
Calin Juravlec9eab382017-01-25 01:17:17 -08001892 if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr,
Calin Juravledd42e272017-09-11 11:50:36 -07001893 uid, storage_flag, /*validate_package_path*/ false)) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001894 LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
1895 return false;
1896 }
1897
1898 if (access(dex_path.c_str(), F_OK) == 0) {
1899 // The path exists, nothing to do. The odex files (if any) will be left untouched.
1900 *out_secondary_dex_exists = true;
1901 return true;
1902 } else if (errno != ENOENT) {
1903 PLOG(ERROR) << "Failed to check access to secondary dex " << dex_path;
1904 return false;
1905 }
1906
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001907 // As a security measure we want to unlink art artifacts with the reduced capabilities
1908 // of the package user id. So we fork and drop capabilities in the child.
1909 pid_t pid = fork();
1910 if (pid == 0) {
1911 // The secondary dex does not exist anymore. Clear any generated files.
1912 char oat_path[PKG_PATH_MAX];
1913 char oat_dir[PKG_PATH_MAX];
1914 char oat_isa_dir[PKG_PATH_MAX];
1915 bool result = true;
1916 /* child -- drop privileges before continuing */
1917 drop_capabilities(uid);
1918 for (size_t i = 0; i < isas.size(); i++) {
1919 if (!create_secondary_dex_oat_layout(dex_path,
1920 isas[i],
1921 oat_dir,
1922 oat_isa_dir,
1923 oat_path)) {
1924 LOG(ERROR) << "Could not create secondary odex layout: "
1925 << dex_path;
1926 result = false;
1927 continue;
1928 }
Calin Juravle51314092017-05-18 15:33:05 -07001929
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001930 // Delete oat/vdex/art files.
1931 result = unlink_if_exists(oat_path) && result;
1932 result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
1933 result = unlink_if_exists(create_image_filename(oat_path)) && result;
Calin Juravlec9eab382017-01-25 01:17:17 -08001934
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001935 // Delete profiles.
1936 std::string current_profile = create_current_profile_path(
Calin Juravle51314092017-05-18 15:33:05 -07001937 multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001938 std::string reference_profile = create_reference_profile_path(
Calin Juravle51314092017-05-18 15:33:05 -07001939 dex_path, /*is_secondary*/true);
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001940 result = unlink_if_exists(current_profile) && result;
1941 result = unlink_if_exists(reference_profile) && result;
Calin Juravle51314092017-05-18 15:33:05 -07001942
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001943 // We upgraded once the location of current profile for secondary dex files.
1944 // Check for any previous left-overs and remove them as well.
1945 std::string old_current_profile = dex_path + ".prof";
1946 result = unlink_if_exists(old_current_profile);
Calin Juravle3760ad32017-07-27 16:31:55 -07001947
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001948 // Try removing the directories as well, they might be empty.
1949 result = rmdir_if_empty(oat_isa_dir) && result;
1950 result = rmdir_if_empty(oat_dir) && result;
1951 }
1952 result ? _exit(0) : _exit(1);
Calin Juravlec9eab382017-01-25 01:17:17 -08001953 }
1954
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001955 int return_code = wait_child(pid);
1956 return return_code == 0;
Calin Juravlec9eab382017-01-25 01:17:17 -08001957}
1958
Jeff Sharkey90aff262016-12-12 14:28:24 -07001959// Helper for move_ab, so that we can have common failure-case cleanup.
1960static bool unlink_and_rename(const char* from, const char* to) {
1961 // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
1962 // return a failure.
1963 struct stat s;
1964 if (stat(to, &s) == 0) {
1965 if (!S_ISREG(s.st_mode)) {
1966 LOG(ERROR) << from << " is not a regular file to replace for A/B.";
1967 return false;
1968 }
1969 if (unlink(to) != 0) {
1970 LOG(ERROR) << "Could not unlink " << to << " to move A/B.";
1971 return false;
1972 }
1973 } else {
1974 // This may be a permission problem. We could investigate the error code, but we'll just
1975 // let the rename failure do the work for us.
1976 }
1977
1978 // Try to rename "to" to "from."
1979 if (rename(from, to) != 0) {
1980 PLOG(ERROR) << "Could not rename " << from << " to " << to;
1981 return false;
1982 }
1983 return true;
1984}
1985
1986// Move/rename a B artifact (from) to an A artifact (to).
1987static bool move_ab_path(const std::string& b_path, const std::string& a_path) {
1988 // Check whether B exists.
1989 {
1990 struct stat s;
1991 if (stat(b_path.c_str(), &s) != 0) {
1992 // Silently ignore for now. The service calling this isn't smart enough to understand
1993 // lack of artifacts at the moment.
1994 return false;
1995 }
1996 if (!S_ISREG(s.st_mode)) {
1997 LOG(ERROR) << "A/B artifact " << b_path << " is not a regular file.";
1998 // Try to unlink, but swallow errors.
1999 unlink(b_path.c_str());
2000 return false;
2001 }
2002 }
2003
2004 // Rename B to A.
2005 if (!unlink_and_rename(b_path.c_str(), a_path.c_str())) {
2006 // Delete the b_path so we don't try again (or fail earlier).
2007 if (unlink(b_path.c_str()) != 0) {
2008 PLOG(ERROR) << "Could not unlink " << b_path;
2009 }
2010
2011 return false;
2012 }
2013
2014 return true;
2015}
2016
2017bool move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
2018 // Get the current slot suffix. No suffix, no A/B.
2019 std::string slot_suffix;
2020 {
2021 char buf[kPropertyValueMax];
2022 if (get_property("ro.boot.slot_suffix", buf, nullptr) <= 0) {
2023 return false;
2024 }
2025 slot_suffix = buf;
2026
2027 if (!ValidateTargetSlotSuffix(slot_suffix)) {
2028 LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
2029 return false;
2030 }
2031 }
2032
2033 // Validate other inputs.
2034 if (validate_apk_path(apk_path) != 0) {
2035 LOG(ERROR) << "Invalid apk_path: " << apk_path;
2036 return false;
2037 }
2038 if (validate_apk_path(oat_dir) != 0) {
2039 LOG(ERROR) << "Invalid oat_dir: " << oat_dir;
2040 return false;
2041 }
2042
2043 char a_path[PKG_PATH_MAX];
2044 if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
2045 return false;
2046 }
2047 const std::string a_vdex_path = create_vdex_filename(a_path);
2048 const std::string a_image_path = create_image_filename(a_path);
2049
2050 // B path = A path + slot suffix.
2051 const std::string b_path = StringPrintf("%s.%s", a_path, slot_suffix.c_str());
2052 const std::string b_vdex_path = StringPrintf("%s.%s", a_vdex_path.c_str(), slot_suffix.c_str());
2053 const std::string b_image_path = StringPrintf("%s.%s",
2054 a_image_path.c_str(),
2055 slot_suffix.c_str());
2056
2057 bool success = true;
2058 if (move_ab_path(b_path, a_path)) {
2059 if (move_ab_path(b_vdex_path, a_vdex_path)) {
2060 // Note: we can live without an app image. As such, ignore failure to move the image file.
2061 // If we decide to require the app image, or the app image being moved correctly,
2062 // then change accordingly.
2063 constexpr bool kIgnoreAppImageFailure = true;
2064
2065 if (!a_image_path.empty()) {
2066 if (!move_ab_path(b_image_path, a_image_path)) {
2067 unlink(a_image_path.c_str());
2068 if (!kIgnoreAppImageFailure) {
2069 success = false;
2070 }
2071 }
2072 }
2073 } else {
2074 // Cleanup: delete B image, ignore errors.
2075 unlink(b_image_path.c_str());
2076 success = false;
2077 }
2078 } else {
2079 // Cleanup: delete B image, ignore errors.
2080 unlink(b_vdex_path.c_str());
2081 unlink(b_image_path.c_str());
2082 success = false;
2083 }
2084 return success;
2085}
2086
2087bool delete_odex(const char* apk_path, const char* instruction_set, const char* oat_dir) {
2088 // Delete the oat/odex file.
2089 char out_path[PKG_PATH_MAX];
Calin Juravle80a21252017-01-17 14:43:25 -08002090 if (!create_oat_out_path(apk_path, instruction_set, oat_dir,
Calin Juravle114f0812017-03-08 19:05:07 -08002091 /*is_secondary_dex*/false, out_path)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07002092 return false;
2093 }
2094
2095 // In case of a permission failure report the issue. Otherwise just print a warning.
2096 auto unlink_and_check = [](const char* path) -> bool {
2097 int result = unlink(path);
2098 if (result != 0) {
2099 if (errno == EACCES || errno == EPERM) {
2100 PLOG(ERROR) << "Could not unlink " << path;
2101 return false;
2102 }
2103 PLOG(WARNING) << "Could not unlink " << path;
2104 }
2105 return true;
2106 };
2107
2108 // Delete the oat/odex file.
2109 bool return_value_oat = unlink_and_check(out_path);
2110
2111 // Derive and delete the app image.
2112 bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
2113
Nicolas Geoffray192fb962017-05-25 13:58:06 +01002114 // Derive and delete the vdex file.
2115 bool return_value_vdex = unlink_and_check(create_vdex_filename(out_path).c_str());
2116
Jeff Sharkey90aff262016-12-12 14:28:24 -07002117 // Report success.
Nicolas Geoffray192fb962017-05-25 13:58:06 +01002118 return return_value_oat && return_value_art && return_value_vdex;
Jeff Sharkey90aff262016-12-12 14:28:24 -07002119}
2120
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06002121static bool is_absolute_path(const std::string& path) {
2122 if (path.find('/') != 0 || path.find("..") != std::string::npos) {
2123 LOG(ERROR) << "Invalid absolute path " << path;
2124 return false;
2125 } else {
2126 return true;
2127 }
2128}
2129
2130static bool is_valid_instruction_set(const std::string& instruction_set) {
2131 // TODO: add explicit whitelisting of instruction sets
2132 if (instruction_set.find('/') != std::string::npos) {
2133 LOG(ERROR) << "Invalid instruction set " << instruction_set;
2134 return false;
2135 } else {
2136 return true;
2137 }
2138}
2139
2140bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir,
2141 const char *apk_path, const char *instruction_set) {
2142 std::string oat_dir_ = oat_dir;
2143 std::string apk_path_ = apk_path;
2144 std::string instruction_set_ = instruction_set;
2145
2146 if (!is_absolute_path(oat_dir_)) return false;
2147 if (!is_absolute_path(apk_path_)) return false;
2148 if (!is_valid_instruction_set(instruction_set_)) return false;
2149
2150 std::string::size_type end = apk_path_.rfind('.');
2151 std::string::size_type start = apk_path_.rfind('/', end);
2152 if (end == std::string::npos || start == std::string::npos) {
2153 LOG(ERROR) << "Invalid apk_path " << apk_path_;
2154 return false;
2155 }
2156
2157 std::string res_ = oat_dir_ + '/' + instruction_set + '/'
2158 + apk_path_.substr(start + 1, end - start - 1) + ".odex";
2159 const char* res = res_.c_str();
2160 if (strlen(res) >= PKG_PATH_MAX) {
2161 LOG(ERROR) << "Result too large";
2162 return false;
2163 } else {
2164 strlcpy(path, res, PKG_PATH_MAX);
2165 return true;
2166 }
2167}
2168
2169bool calculate_odex_file_path_default(char path[PKG_PATH_MAX], const char *apk_path,
2170 const char *instruction_set) {
2171 std::string apk_path_ = apk_path;
2172 std::string instruction_set_ = instruction_set;
2173
2174 if (!is_absolute_path(apk_path_)) return false;
2175 if (!is_valid_instruction_set(instruction_set_)) return false;
2176
2177 std::string::size_type end = apk_path_.rfind('.');
2178 std::string::size_type start = apk_path_.rfind('/', end);
2179 if (end == std::string::npos || start == std::string::npos) {
2180 LOG(ERROR) << "Invalid apk_path " << apk_path_;
2181 return false;
2182 }
2183
2184 std::string oat_dir = apk_path_.substr(0, start + 1) + "oat";
2185 return calculate_oat_file_path_default(path, oat_dir.c_str(), apk_path, instruction_set);
2186}
2187
2188bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src,
2189 const char *instruction_set) {
2190 std::string src_ = src;
2191 std::string instruction_set_ = instruction_set;
2192
2193 if (!is_absolute_path(src_)) return false;
2194 if (!is_valid_instruction_set(instruction_set_)) return false;
2195
2196 for (auto it = src_.begin() + 1; it < src_.end(); ++it) {
2197 if (*it == '/') {
2198 *it = '@';
2199 }
2200 }
2201
2202 std::string res_ = android_data_dir + DALVIK_CACHE + '/' + instruction_set_ + src_
2203 + DALVIK_CACHE_POSTFIX;
2204 const char* res = res_.c_str();
2205 if (strlen(res) >= PKG_PATH_MAX) {
2206 LOG(ERROR) << "Result too large";
2207 return false;
2208 } else {
2209 strlcpy(path, res, PKG_PATH_MAX);
2210 return true;
2211 }
2212}
2213
Jeff Sharkey6c2c0562016-12-07 12:12:00 -07002214} // namespace installd
2215} // namespace android