1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.pm.dex; 18 19 import android.annotation.UserIdInt; 20 import android.app.AppOpsManager; 21 import android.content.Context; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.IPackageManager; 24 import android.content.pm.PackageInfo; 25 import android.content.pm.PackageManager; 26 import android.content.pm.PackageParser; 27 import android.content.pm.dex.ArtManager; 28 import android.content.pm.dex.ArtManager.ProfileType; 29 import android.content.pm.dex.ArtManagerInternal; 30 import android.content.pm.dex.DexMetadataHelper; 31 import android.content.pm.dex.ISnapshotRuntimeProfileCallback; 32 import android.content.pm.dex.PackageOptimizationInfo; 33 import android.os.Binder; 34 import android.os.Build; 35 import android.os.Handler; 36 import android.os.ParcelFileDescriptor; 37 import android.os.Process; 38 import android.os.RemoteException; 39 import android.os.SystemProperties; 40 import android.os.UserHandle; 41 import android.system.Os; 42 import android.util.ArrayMap; 43 import android.util.Log; 44 import android.util.Slog; 45 46 import com.android.internal.annotations.GuardedBy; 47 import com.android.internal.os.BackgroundThread; 48 import com.android.internal.os.RoSystemProperties; 49 import com.android.internal.util.ArrayUtils; 50 import com.android.internal.util.Preconditions; 51 import com.android.server.LocalServices; 52 import com.android.server.pm.Installer; 53 import com.android.server.pm.Installer.InstallerException; 54 import com.android.server.pm.PackageManagerServiceCompilerMapping; 55 56 import dalvik.system.DexFile; 57 import dalvik.system.VMRuntime; 58 59 import libcore.io.IoUtils; 60 import libcore.util.NonNull; 61 import libcore.util.Nullable; 62 63 import java.io.File; 64 import java.io.FileNotFoundException; 65 66 /** 67 * A system service that provides access to runtime and compiler artifacts. 68 * 69 * This service is not accessed by users directly, instead one uses an instance of 70 * {@link ArtManager}, which can be accessed via {@link PackageManager} as follows: 71 * <p/> 72 * {@code context().getPackageManager().getArtManager();} 73 * <p class="note"> 74 * Note: Accessing runtime artifacts may require extra permissions. For example querying the 75 * runtime profiles of apps requires {@link android.Manifest.permission#READ_RUNTIME_PROFILES} 76 * which is a system-level permission that will not be granted to normal apps. 77 */ 78 public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { 79 private static final String TAG = "ArtManagerService"; 80 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 81 82 // Package name used to create the profile directory layout when 83 // taking a snapshot of the boot image profile. 84 private static final String BOOT_IMAGE_ANDROID_PACKAGE = "android"; 85 // Profile name used for the boot image profile. 86 private static final String BOOT_IMAGE_PROFILE_NAME = "android.prof"; 87 88 private final Context mContext; 89 private final IPackageManager mPackageManager; 90 private final Object mInstallLock; 91 @GuardedBy("mInstallLock") 92 private final Installer mInstaller; 93 94 private final Handler mHandler; 95 96 static { 97 verifyTronLoggingConstants(); 98 } 99 100 public ArtManagerService(Context context, IPackageManager pm, Installer installer, 101 Object installLock) { 102 mContext = context; 103 mPackageManager = pm; 104 mInstaller = installer; 105 mInstallLock = installLock; 106 mHandler = new Handler(BackgroundThread.getHandler().getLooper()); 107 108 LocalServices.addService(ArtManagerInternal.class, new ArtManagerInternalImpl()); 109 } 110 111 private boolean checkAndroidPermissions(int callingUid, String callingPackage) { 112 // Callers always need this permission 113 mContext.enforceCallingOrSelfPermission( 114 android.Manifest.permission.READ_RUNTIME_PROFILES, TAG); 115 116 // Callers also need the ability to read usage statistics 117 switch (mContext.getSystemService(AppOpsManager.class) 118 .noteOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage)) { 119 case AppOpsManager.MODE_ALLOWED: 120 return true; 121 case AppOpsManager.MODE_DEFAULT: 122 mContext.enforceCallingOrSelfPermission( 123 android.Manifest.permission.PACKAGE_USAGE_STATS, TAG); 124 return true; 125 default: 126 return false; 127 } 128 } 129 130 /** 131 * Checks if the calling user is the shell user and if it is, it checks if it can 132 * to take a profile snapshot of the give package: 133 * - on debuggable builds the shell user can take profile snapshots of any app. 134 * - on non-debuggable builds the shell user can only take snapshots of debuggable apps. 135 * 136 * Returns true iff the callingUid is the shell uid and the shell is allowed snapshot profiles. 137 * 138 * Note that the root users will go through the regular {@link #checkAndroidPermissions) checks. 139 */ 140 private boolean checkShellPermissions(@ProfileType int profileType, String packageName, 141 int callingUid) { 142 if (callingUid != Process.SHELL_UID) { 143 return false; 144 } 145 if (RoSystemProperties.DEBUGGABLE) { 146 return true; 147 } 148 if (profileType == ArtManager.PROFILE_BOOT_IMAGE) { 149 // The shell cannot profile the boot image on non-debuggable builds. 150 return false; 151 } 152 PackageInfo info = null; 153 try { 154 info = mPackageManager.getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); 155 } catch (RemoteException ignored) { 156 // Should not happen. 157 } 158 if (info == null) { 159 return false; 160 } 161 162 // On user builds the shell can only profile debuggable apps. 163 return (info.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) 164 == ApplicationInfo.FLAG_DEBUGGABLE; 165 } 166 167 168 @Override 169 public void snapshotRuntimeProfile(@ProfileType int profileType, @Nullable String packageName, 170 @Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback, 171 String callingPackage) { 172 int callingUid = Binder.getCallingUid(); 173 if (!checkShellPermissions(profileType, packageName, callingUid) && 174 !checkAndroidPermissions(callingUid, callingPackage)) { 175 try { 176 callback.onError(ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 177 } catch (RemoteException ignored) { 178 } 179 return; 180 } 181 182 // Sanity checks on the arguments. 183 Preconditions.checkNotNull(callback); 184 185 boolean bootImageProfile = profileType == ArtManager.PROFILE_BOOT_IMAGE; 186 if (!bootImageProfile) { 187 Preconditions.checkStringNotEmpty(codePath); 188 Preconditions.checkStringNotEmpty(packageName); 189 } 190 191 // Verify that runtime profiling is enabled. 192 if (!isRuntimeProfilingEnabled(profileType, callingPackage)) { 193 throw new IllegalStateException("Runtime profiling is not enabled for " + profileType); 194 } 195 196 if (DEBUG) { 197 Slog.d(TAG, "Requested snapshot for " + packageName + ":" + codePath); 198 } 199 200 if (bootImageProfile) { 201 snapshotBootImageProfile(callback); 202 } else { 203 snapshotAppProfile(packageName, codePath, callback); 204 } 205 } 206 207 private void snapshotAppProfile(String packageName, String codePath, 208 ISnapshotRuntimeProfileCallback callback) { 209 PackageInfo info = null; 210 try { 211 // Note that we use the default user 0 to retrieve the package info. 212 // This doesn't really matter because for user 0 we always get a package back (even if 213 // it's not installed for the user 0). It is ok because we only care about the code 214 // paths and not if the package is enabled or not for the user. 215 216 // TODO(calin): consider adding an API to PMS which can retrieve the 217 // PackageParser.Package. 218 info = mPackageManager.getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); 219 } catch (RemoteException ignored) { 220 // Should not happen. 221 } 222 if (info == null) { 223 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_PACKAGE_NOT_FOUND); 224 return; 225 } 226 227 boolean pathFound = info.applicationInfo.getBaseCodePath().equals(codePath); 228 String splitName = null; 229 String[] splitCodePaths = info.applicationInfo.getSplitCodePaths(); 230 if (!pathFound && (splitCodePaths != null)) { 231 for (int i = splitCodePaths.length - 1; i >= 0; i--) { 232 if (splitCodePaths[i].equals(codePath)) { 233 pathFound = true; 234 splitName = info.applicationInfo.splitNames[i]; 235 break; 236 } 237 } 238 } 239 if (!pathFound) { 240 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND); 241 return; 242 } 243 244 // All good, create the profile snapshot. 245 int appId = UserHandle.getAppId(info.applicationInfo.uid); 246 if (appId < 0) { 247 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 248 Slog.wtf(TAG, "AppId is -1 for package: " + packageName); 249 return; 250 } 251 252 createProfileSnapshot(packageName, ArtManager.getProfileName(splitName), codePath, 253 appId, callback); 254 // Destroy the snapshot, we no longer need it. 255 destroyProfileSnapshot(packageName, ArtManager.getProfileName(splitName)); 256 } 257 258 private void createProfileSnapshot(String packageName, String profileName, String classpath, 259 int appId, ISnapshotRuntimeProfileCallback callback) { 260 // Ask the installer to snapshot the profile. 261 synchronized (mInstallLock) { 262 try { 263 if (!mInstaller.createProfileSnapshot(appId, packageName, profileName, classpath)) { 264 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 265 return; 266 } 267 } catch (InstallerException e) { 268 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 269 return; 270 } 271 } 272 273 // Open the snapshot and invoke the callback. 274 File snapshotProfile = ArtManager.getProfileSnapshotFileForName(packageName, profileName); 275 276 ParcelFileDescriptor fd = null; 277 try { 278 fd = ParcelFileDescriptor.open(snapshotProfile, ParcelFileDescriptor.MODE_READ_ONLY); 279 if (fd == null || !fd.getFileDescriptor().valid()) { 280 Slog.wtf(TAG, 281 "ParcelFileDescriptor.open returned an invalid descriptor for " 282 + packageName + ":" + snapshotProfile + ". isNull=" + (fd == null)); 283 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 284 } else { 285 postSuccess(packageName, fd, callback); 286 } 287 } catch (FileNotFoundException e) { 288 Slog.w(TAG, "Could not open snapshot profile for " + packageName + ":" 289 + snapshotProfile, e); 290 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 291 } 292 } 293 294 private void destroyProfileSnapshot(String packageName, String profileName) { 295 if (DEBUG) { 296 Slog.d(TAG, "Destroying profile snapshot for" + packageName + ":" + profileName); 297 } 298 299 synchronized (mInstallLock) { 300 try { 301 mInstaller.destroyProfileSnapshot(packageName, profileName); 302 } catch (InstallerException e) { 303 Slog.e(TAG, "Failed to destroy profile snapshot for " + 304 packageName + ":" + profileName, e); 305 } 306 } 307 } 308 309 @Override 310 public boolean isRuntimeProfilingEnabled(@ProfileType int profileType, String callingPackage) { 311 int callingUid = Binder.getCallingUid(); 312 if (callingUid != Process.SHELL_UID && !checkAndroidPermissions(callingUid, callingPackage)) { 313 return false; 314 } 315 316 switch (profileType) { 317 case ArtManager.PROFILE_APPS : 318 return SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); 319 case ArtManager.PROFILE_BOOT_IMAGE: 320 return (Build.IS_USERDEBUG || Build.IS_ENG) && 321 SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false) && 322 SystemProperties.getBoolean("dalvik.vm.profilebootimage", false); 323 default: 324 throw new IllegalArgumentException("Invalid profile type:" + profileType); 325 } 326 } 327 328 private void snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback) { 329 // Combine the profiles for boot classpath and system server classpath. 330 // This avoids having yet another type of profiles and simplifies the processing. 331 String classpath = String.join(":", Os.getenv("BOOTCLASSPATH"), 332 Os.getenv("SYSTEMSERVERCLASSPATH")); 333 334 // Create the snapshot. 335 createProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME, classpath, 336 /*appId*/ -1, callback); 337 // Destroy the snapshot, we no longer need it. 338 destroyProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME); 339 } 340 341 /** 342 * Post {@link ISnapshotRuntimeProfileCallback#onError(int)} with the given error message 343 * on the internal {@code mHandler}. 344 */ 345 private void postError(ISnapshotRuntimeProfileCallback callback, String packageName, 346 int errCode) { 347 if (DEBUG) { 348 Slog.d(TAG, "Failed to snapshot profile for " + packageName + " with error: " + 349 errCode); 350 } 351 mHandler.post(() -> { 352 try { 353 callback.onError(errCode); 354 } catch (Exception e) { 355 Slog.w(TAG, "Failed to callback after profile snapshot for " + packageName, e); 356 } 357 }); 358 } 359 360 private void postSuccess(String packageName, ParcelFileDescriptor fd, 361 ISnapshotRuntimeProfileCallback callback) { 362 if (DEBUG) { 363 Slog.d(TAG, "Successfully snapshot profile for " + packageName); 364 } 365 mHandler.post(() -> { 366 try { 367 // Double check that the descriptor is still valid. 368 // We've seen production issues (b/76028139) where this can turn invalid (there are 369 // suspicions around the finalizer behaviour). 370 if (fd.getFileDescriptor().valid()) { 371 callback.onSuccess(fd); 372 } else { 373 Slog.wtf(TAG, "The snapshot FD became invalid before posting the result for " 374 + packageName); 375 callback.onError(ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 376 } 377 } catch (Exception e) { 378 Slog.w(TAG, 379 "Failed to call onSuccess after profile snapshot for " + packageName, e); 380 } finally { 381 IoUtils.closeQuietly(fd); 382 } 383 }); 384 } 385 386 /** 387 * Prepare the application profiles. 388 * For all code paths: 389 * - create the current primary profile to save time at app startup time. 390 * - copy the profiles from the associated dex metadata file to the reference profile. 391 */ 392 public void prepareAppProfiles(PackageParser.Package pkg, @UserIdInt int user) { 393 final int appId = UserHandle.getAppId(pkg.applicationInfo.uid); 394 if (user < 0) { 395 Slog.wtf(TAG, "Invalid user id: " + user); 396 return; 397 } 398 if (appId < 0) { 399 Slog.wtf(TAG, "Invalid app id: " + appId); 400 return; 401 } 402 try { 403 ArrayMap<String, String> codePathsProfileNames = getPackageProfileNames(pkg); 404 for (int i = codePathsProfileNames.size() - 1; i >= 0; i--) { 405 String codePath = codePathsProfileNames.keyAt(i); 406 String profileName = codePathsProfileNames.valueAt(i); 407 File dexMetadata = DexMetadataHelper.findDexMetadataForFile(new File(codePath)); 408 String dexMetadataPath = dexMetadata == null ? null : dexMetadata.getAbsolutePath(); 409 synchronized (mInstaller) { 410 boolean result = mInstaller.prepareAppProfile(pkg.packageName, user, appId, 411 profileName, codePath, dexMetadataPath); 412 if (!result) { 413 Slog.e(TAG, "Failed to prepare profile for " + 414 pkg.packageName + ":" + codePath); 415 } 416 } 417 } 418 } catch (InstallerException e) { 419 Slog.e(TAG, "Failed to prepare profile for " + pkg.packageName, e); 420 } 421 } 422 423 /** 424 * Prepares the app profiles for a set of users. {@see ArtManagerService#prepareAppProfiles}. 425 */ 426 public void prepareAppProfiles(PackageParser.Package pkg, int[] user) { 427 for (int i = 0; i < user.length; i++) { 428 prepareAppProfiles(pkg, user[i]); 429 } 430 } 431 432 /** 433 * Clear the profiles for the given package. 434 */ 435 public void clearAppProfiles(PackageParser.Package pkg) { 436 try { 437 ArrayMap<String, String> packageProfileNames = getPackageProfileNames(pkg); 438 for (int i = packageProfileNames.size() - 1; i >= 0; i--) { 439 String profileName = packageProfileNames.valueAt(i); 440 mInstaller.clearAppProfiles(pkg.packageName, profileName); 441 } 442 } catch (InstallerException e) { 443 Slog.w(TAG, String.valueOf(e)); 444 } 445 } 446 447 /** 448 * Dumps the profiles for the given package. 449 */ 450 public void dumpProfiles(PackageParser.Package pkg) { 451 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); 452 try { 453 ArrayMap<String, String> packageProfileNames = getPackageProfileNames(pkg); 454 for (int i = packageProfileNames.size() - 1; i >= 0; i--) { 455 String codePath = packageProfileNames.keyAt(i); 456 String profileName = packageProfileNames.valueAt(i); 457 synchronized (mInstallLock) { 458 mInstaller.dumpProfiles(sharedGid, pkg.packageName, profileName, codePath); 459 } 460 } 461 } catch (InstallerException e) { 462 Slog.w(TAG, "Failed to dump profiles", e); 463 } 464 } 465 466 /** 467 * Build the profiles names for all the package code paths (excluding resource only paths). 468 * Return the map [code path -> profile name]. 469 */ 470 private ArrayMap<String, String> getPackageProfileNames(PackageParser.Package pkg) { 471 ArrayMap<String, String> result = new ArrayMap<>(); 472 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { 473 result.put(pkg.baseCodePath, ArtManager.getProfileName(null)); 474 } 475 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { 476 for (int i = 0; i < pkg.splitCodePaths.length; i++) { 477 if ((pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) { 478 result.put(pkg.splitCodePaths[i], ArtManager.getProfileName(pkg.splitNames[i])); 479 } 480 } 481 } 482 return result; 483 } 484 485 // Constants used for logging compilation filter to TRON. 486 // DO NOT CHANGE existing values. 487 // 488 // NOTE: '-1' value is reserved for the case where we cannot produce a valid 489 // PackageOptimizationInfo because the ArtManagerInternal is not ready to be used by the 490 // ActivityMetricsLoggers. 491 private static final int TRON_COMPILATION_FILTER_ERROR = 0; 492 private static final int TRON_COMPILATION_FILTER_UNKNOWN = 1; 493 private static final int TRON_COMPILATION_FILTER_ASSUMED_VERIFIED = 2; 494 private static final int TRON_COMPILATION_FILTER_EXTRACT = 3; 495 private static final int TRON_COMPILATION_FILTER_VERIFY = 4; 496 private static final int TRON_COMPILATION_FILTER_QUICKEN = 5; 497 private static final int TRON_COMPILATION_FILTER_SPACE_PROFILE = 6; 498 private static final int TRON_COMPILATION_FILTER_SPACE = 7; 499 private static final int TRON_COMPILATION_FILTER_SPEED_PROFILE = 8; 500 private static final int TRON_COMPILATION_FILTER_SPEED = 9; 501 private static final int TRON_COMPILATION_FILTER_EVERYTHING_PROFILE = 10; 502 private static final int TRON_COMPILATION_FILTER_EVERYTHING = 11; 503 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK = 12; 504 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK = 13; 505 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK = 14; 506 507 // Constants used for logging compilation reason to TRON. 508 // DO NOT CHANGE existing values. 509 // 510 // NOTE: '-1' value is reserved for the case where we cannot produce a valid 511 // PackageOptimizationInfo because the ArtManagerInternal is not ready to be used by the 512 // ActivityMetricsLoggers. 513 private static final int TRON_COMPILATION_REASON_ERROR = 0; 514 private static final int TRON_COMPILATION_REASON_UNKNOWN = 1; 515 private static final int TRON_COMPILATION_REASON_FIRST_BOOT = 2; 516 private static final int TRON_COMPILATION_REASON_BOOT = 3; 517 private static final int TRON_COMPILATION_REASON_INSTALL = 4; 518 private static final int TRON_COMPILATION_REASON_BG_DEXOPT = 5; 519 private static final int TRON_COMPILATION_REASON_AB_OTA = 6; 520 private static final int TRON_COMPILATION_REASON_INACTIVE = 7; 521 private static final int TRON_COMPILATION_REASON_SHARED = 8; 522 523 /** 524 * Convert the compilation reason to an int suitable to be logged to TRON. 525 */ 526 private static int getCompilationReasonTronValue(String compilationReason) { 527 switch (compilationReason) { 528 case "unknown" : return TRON_COMPILATION_REASON_UNKNOWN; 529 case "error" : return TRON_COMPILATION_REASON_ERROR; 530 case "first-boot" : return TRON_COMPILATION_REASON_FIRST_BOOT; 531 case "boot" : return TRON_COMPILATION_REASON_BOOT; 532 case "install" : return TRON_COMPILATION_REASON_INSTALL; 533 case "bg-dexopt" : return TRON_COMPILATION_REASON_BG_DEXOPT; 534 case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA; 535 case "inactive" : return TRON_COMPILATION_REASON_INACTIVE; 536 case "shared" : return TRON_COMPILATION_REASON_SHARED; 537 default: return TRON_COMPILATION_REASON_UNKNOWN; 538 } 539 } 540 541 /** 542 * Convert the compilation filter to an int suitable to be logged to TRON. 543 */ 544 private static int getCompilationFilterTronValue(String compilationFilter) { 545 switch (compilationFilter) { 546 case "error" : return TRON_COMPILATION_FILTER_ERROR; 547 case "unknown" : return TRON_COMPILATION_FILTER_UNKNOWN; 548 case "assume-verified" : return TRON_COMPILATION_FILTER_ASSUMED_VERIFIED; 549 case "extract" : return TRON_COMPILATION_FILTER_EXTRACT; 550 case "verify" : return TRON_COMPILATION_FILTER_VERIFY; 551 case "quicken" : return TRON_COMPILATION_FILTER_QUICKEN; 552 case "space-profile" : return TRON_COMPILATION_FILTER_SPACE_PROFILE; 553 case "space" : return TRON_COMPILATION_FILTER_SPACE; 554 case "speed-profile" : return TRON_COMPILATION_FILTER_SPEED_PROFILE; 555 case "speed" : return TRON_COMPILATION_FILTER_SPEED; 556 case "everything-profile" : return TRON_COMPILATION_FILTER_EVERYTHING_PROFILE; 557 case "everything" : return TRON_COMPILATION_FILTER_EVERYTHING; 558 case "run-from-apk" : return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK; 559 case "run-from-apk-fallback" : 560 return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK; 561 case "run-from-vdex-fallback" : 562 return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK; 563 default: return TRON_COMPILATION_FILTER_UNKNOWN; 564 } 565 } 566 567 private static void verifyTronLoggingConstants() { 568 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 569 String reason = PackageManagerServiceCompilerMapping.REASON_STRINGS[i]; 570 int value = getCompilationReasonTronValue(reason); 571 if (value == TRON_COMPILATION_REASON_ERROR 572 || value == TRON_COMPILATION_REASON_UNKNOWN) { 573 throw new IllegalArgumentException("Compilation reason not configured for TRON " 574 + "logging: " + reason); 575 } 576 } 577 } 578 579 private class ArtManagerInternalImpl extends ArtManagerInternal { 580 @Override 581 public PackageOptimizationInfo getPackageOptimizationInfo( 582 ApplicationInfo info, String abi) { 583 String compilationReason; 584 String compilationFilter; 585 try { 586 String isa = VMRuntime.getInstructionSet(abi); 587 DexFile.OptimizationInfo optInfo = 588 DexFile.getDexFileOptimizationInfo(info.getBaseCodePath(), isa); 589 compilationFilter = optInfo.getStatus(); 590 compilationReason = optInfo.getReason(); 591 } catch (FileNotFoundException e) { 592 Slog.e(TAG, "Could not get optimizations status for " + info.getBaseCodePath(), e); 593 compilationFilter = "error"; 594 compilationReason = "error"; 595 } catch (IllegalArgumentException e) { 596 Slog.wtf(TAG, "Requested optimization status for " + info.getBaseCodePath() 597 + " due to an invalid abi " + abi, e); 598 compilationFilter = "error"; 599 compilationReason = "error"; 600 } 601 602 int compilationFilterTronValue = getCompilationFilterTronValue(compilationFilter); 603 int compilationReasonTronValue = getCompilationReasonTronValue(compilationReason); 604 605 return new PackageOptimizationInfo( 606 compilationFilterTronValue, compilationReasonTronValue); 607 } 608 } 609 } 610