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.NonNull; 20 import android.annotation.Nullable; 21 import android.app.AppOpsManager; 22 import android.content.Context; 23 import android.content.pm.ApplicationInfo; 24 import android.content.pm.IPackageManager; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageManager; 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.ISnapshotRuntimeProfileCallback; 31 import android.content.pm.dex.PackageOptimizationInfo; 32 import android.os.Binder; 33 import android.os.Build; 34 import android.os.Handler; 35 import android.os.ParcelFileDescriptor; 36 import android.os.Process; 37 import android.os.RemoteException; 38 import android.os.ServiceManager; 39 import android.os.SystemProperties; 40 import android.util.ArrayMap; 41 import android.util.Log; 42 import android.util.Slog; 43 44 import com.android.internal.os.BackgroundThread; 45 import com.android.internal.os.RoSystemProperties; 46 import com.android.internal.util.ArrayUtils; 47 import com.android.internal.util.Preconditions; 48 import com.android.server.LocalServices; 49 import com.android.server.art.ArtManagerLocal; 50 import com.android.server.pm.DexOptHelper; 51 import com.android.server.pm.Installer; 52 import com.android.server.pm.PackageManagerLocal; 53 import com.android.server.pm.PackageManagerService; 54 import com.android.server.pm.PackageManagerServiceCompilerMapping; 55 import com.android.server.pm.PackageManagerServiceUtils; 56 import com.android.server.pm.pkg.AndroidPackage; 57 58 import dalvik.system.DexFile; 59 import dalvik.system.VMRuntime; 60 61 import libcore.io.IoUtils; 62 63 import java.io.FileNotFoundException; 64 import java.io.IOException; 65 import java.nio.file.Files; 66 import java.nio.file.Path; 67 import java.nio.file.Paths; 68 import java.util.Objects; 69 70 /** 71 * A system service that provides access to runtime and compiler artifacts. 72 * 73 * This service is not accessed by users directly, instead one uses an instance of 74 * {@link ArtManager}, which can be accessed via {@link PackageManager} as follows: 75 * <p/> 76 * {@code context().getPackageManager().getArtManager();} 77 * <p class="note"> 78 * Note: Accessing runtime artifacts may require extra permissions. For example querying the 79 * runtime profiles of apps requires {@link android.Manifest.permission#READ_RUNTIME_PROFILES} 80 * which is a system-level permission that will not be granted to normal apps. 81 */ 82 public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { 83 private static final String TAG = "ArtManagerService"; 84 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 85 86 // Package name used to create the profile directory layout when 87 // taking a snapshot of the boot image profile. 88 private static final String BOOT_IMAGE_ANDROID_PACKAGE = "android"; 89 // Profile name used for the boot image profile. 90 private static final String BOOT_IMAGE_PROFILE_NAME = "android.prof"; 91 92 private final Context mContext; 93 private IPackageManager mPackageManager; 94 private final Installer mInstaller; 95 96 private final Handler mHandler; 97 98 static { verifyTronLoggingConstants()99 verifyTronLoggingConstants(); 100 } 101 ArtManagerService(Context context, Installer installer, Object ignored)102 public ArtManagerService(Context context, Installer installer, 103 Object ignored) { 104 mContext = context; 105 mInstaller = installer; 106 mHandler = new Handler(BackgroundThread.getHandler().getLooper()); 107 108 LocalServices.addService(ArtManagerInternal.class, new ArtManagerInternalImpl()); 109 } 110 111 @NonNull getPackageManager()112 private IPackageManager getPackageManager() { 113 if (mPackageManager == null) { 114 mPackageManager = IPackageManager.Stub.asInterface( 115 ServiceManager.getService("package")); 116 } 117 return mPackageManager; 118 } 119 checkAndroidPermissions(int callingUid, String callingPackage)120 private boolean checkAndroidPermissions(int callingUid, String callingPackage) { 121 // Callers always need this permission 122 mContext.enforceCallingOrSelfPermission( 123 android.Manifest.permission.READ_RUNTIME_PROFILES, TAG); 124 125 // Callers also need the ability to read usage statistics 126 switch (mContext.getSystemService(AppOpsManager.class) 127 .noteOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage)) { 128 case AppOpsManager.MODE_ALLOWED: 129 return true; 130 case AppOpsManager.MODE_DEFAULT: 131 mContext.enforceCallingOrSelfPermission( 132 android.Manifest.permission.PACKAGE_USAGE_STATS, TAG); 133 return true; 134 default: 135 return false; 136 } 137 } 138 139 /** 140 * Checks if the calling user is the shell user and if it is, it checks if it can 141 * to take a profile snapshot of the give package: 142 * - on debuggable builds the shell user can take profile snapshots of any app. 143 * - on non-debuggable builds the shell user can only take snapshots of debuggable apps. 144 * 145 * Returns true iff the callingUid is the shell uid and the shell is allowed snapshot profiles. 146 * 147 * Note that the root users will go through the regular {@link #checkAndroidPermissions) checks. 148 */ checkShellPermissions(@rofileType int profileType, String packageName, int callingUid)149 private boolean checkShellPermissions(@ProfileType int profileType, String packageName, 150 int callingUid) { 151 if (callingUid != Process.SHELL_UID) { 152 return false; 153 } 154 if (RoSystemProperties.DEBUGGABLE) { 155 return true; 156 } 157 if (profileType == ArtManager.PROFILE_BOOT_IMAGE) { 158 // The shell cannot profile the boot image on non-debuggable builds. 159 return false; 160 } 161 PackageInfo info = null; 162 try { 163 info = getPackageManager().getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); 164 } catch (RemoteException ignored) { 165 // Should not happen. 166 } 167 if (info == null) { 168 return false; 169 } 170 171 // On user builds the shell can only profile debuggable apps. 172 return (info.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) 173 == ApplicationInfo.FLAG_DEBUGGABLE; 174 } 175 176 @Override snapshotRuntimeProfile(@rofileType int profileType, @Nullable String packageName, @Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback, String callingPackage)177 public void snapshotRuntimeProfile(@ProfileType int profileType, @Nullable String packageName, 178 @Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback, 179 String callingPackage) { 180 int callingUid = Binder.getCallingUid(); 181 if (!checkShellPermissions(profileType, packageName, callingUid) && 182 !checkAndroidPermissions(callingUid, callingPackage)) { 183 try { 184 callback.onError(ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 185 } catch (RemoteException ignored) { 186 } 187 return; 188 } 189 190 // Validity checks on the arguments. 191 Objects.requireNonNull(callback); 192 193 boolean bootImageProfile = profileType == ArtManager.PROFILE_BOOT_IMAGE; 194 if (!bootImageProfile) { 195 Preconditions.checkStringNotEmpty(codePath); 196 Preconditions.checkStringNotEmpty(packageName); 197 } 198 199 // Verify that runtime profiling is enabled. 200 if (!isRuntimeProfilingEnabled(profileType, callingPackage)) { 201 throw new IllegalStateException("Runtime profiling is not enabled for " + profileType); 202 } 203 204 if (DEBUG) { 205 Slog.d(TAG, "Requested snapshot for " + packageName + ":" + codePath); 206 } 207 208 if (bootImageProfile) { 209 snapshotBootImageProfile(callback); 210 } else { 211 snapshotAppProfile(packageName, codePath, callback); 212 } 213 } 214 snapshotAppProfile( String packageName, String codePath, ISnapshotRuntimeProfileCallback callback)215 private void snapshotAppProfile( 216 String packageName, String codePath, ISnapshotRuntimeProfileCallback callback) { 217 PackageInfo info = null; 218 try { 219 // Note that we use the default user 0 to retrieve the package info. 220 // This doesn't really matter because for user 0 we always get a package back (even if 221 // it's not installed for the user 0). It is ok because we only care about the code 222 // paths and not if the package is enabled or not for the user. 223 224 // TODO(calin): consider adding an API to PMS which can retrieve the 225 // PackageParser.Package. 226 info = getPackageManager().getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); 227 } catch (RemoteException ignored) { 228 // Should not happen. 229 } 230 if (info == null) { 231 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_PACKAGE_NOT_FOUND); 232 return; 233 } 234 235 boolean pathFound = info.applicationInfo.getBaseCodePath().equals(codePath); 236 String splitName = null; 237 String[] splitCodePaths = info.applicationInfo.getSplitCodePaths(); 238 if (!pathFound && (splitCodePaths != null)) { 239 for (int i = splitCodePaths.length - 1; i >= 0; i--) { 240 if (splitCodePaths[i].equals(codePath)) { 241 pathFound = true; 242 splitName = info.applicationInfo.splitNames[i]; 243 break; 244 } 245 } 246 } 247 if (!pathFound) { 248 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND); 249 return; 250 } 251 252 // All good, create the profile snapshot. 253 ParcelFileDescriptor fd; 254 255 try (PackageManagerLocal.FilteredSnapshot snapshot = 256 PackageManagerServiceUtils.getPackageManagerLocal() 257 .withFilteredSnapshot()) { 258 fd = DexOptHelper.getArtManagerLocal().snapshotAppProfile( 259 snapshot, packageName, splitName); 260 } catch (IllegalArgumentException e) { 261 // ArtManagerLocal.snapshotAppProfile couldn't find the package or split. Since 262 // we've checked them above this can only happen due to race, i.e. the package got 263 // removed. So let's report it as SNAPSHOT_FAILED_PACKAGE_NOT_FOUND even if it was 264 // for the split. 265 // TODO(mast): Reuse the same snapshot to avoid this race. 266 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_PACKAGE_NOT_FOUND); 267 return; 268 } catch (IllegalStateException | ArtManagerLocal.SnapshotProfileException e) { 269 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 270 return; 271 } 272 273 postSuccess(packageName, fd, callback); 274 } 275 276 @Override isRuntimeProfilingEnabled(@rofileType int profileType, String callingPackage)277 public boolean isRuntimeProfilingEnabled(@ProfileType int profileType, String callingPackage) { 278 int callingUid = Binder.getCallingUid(); 279 if (callingUid != Process.SHELL_UID && !checkAndroidPermissions(callingUid, callingPackage)) { 280 return false; 281 } 282 283 switch (profileType) { 284 case ArtManager.PROFILE_APPS : 285 return true; 286 case ArtManager.PROFILE_BOOT_IMAGE: 287 // The device config property overrides the system property version. 288 boolean profileBootClassPath = SystemProperties.getBoolean( 289 "persist.device_config.runtime_native_boot.profilebootclasspath", 290 SystemProperties.getBoolean("dalvik.vm.profilebootclasspath", false)); 291 return (Build.IS_USERDEBUG || Build.IS_ENG) && profileBootClassPath; 292 default: 293 throw new IllegalArgumentException("Invalid profile type:" + profileType); 294 } 295 } 296 snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback)297 private void snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback) { 298 ParcelFileDescriptor fd; 299 300 try (PackageManagerLocal.FilteredSnapshot snapshot = 301 PackageManagerServiceUtils.getPackageManagerLocal() 302 .withFilteredSnapshot()) { 303 fd = DexOptHelper.getArtManagerLocal().snapshotBootImageProfile(snapshot); 304 } catch (IllegalStateException | ArtManagerLocal.SnapshotProfileException e) { 305 postError(callback, BOOT_IMAGE_ANDROID_PACKAGE, 306 ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 307 return; 308 } 309 310 postSuccess(BOOT_IMAGE_ANDROID_PACKAGE, fd, callback); 311 } 312 313 /** 314 * Post {@link ISnapshotRuntimeProfileCallback#onError(int)} with the given error message 315 * on the internal {@code mHandler}. 316 */ postError(ISnapshotRuntimeProfileCallback callback, String packageName, int errCode)317 private void postError(ISnapshotRuntimeProfileCallback callback, String packageName, 318 int errCode) { 319 if (DEBUG) { 320 Slog.d(TAG, "Failed to snapshot profile for " + packageName + " with error: " + 321 errCode); 322 } 323 mHandler.post(() -> { 324 try { 325 callback.onError(errCode); 326 } catch (RemoteException | RuntimeException e) { 327 Slog.w(TAG, "Failed to callback after profile snapshot for " + packageName, e); 328 } 329 }); 330 } 331 postSuccess(String packageName, ParcelFileDescriptor fd, ISnapshotRuntimeProfileCallback callback)332 private void postSuccess(String packageName, ParcelFileDescriptor fd, 333 ISnapshotRuntimeProfileCallback callback) { 334 if (DEBUG) { 335 Slog.d(TAG, "Successfully snapshot profile for " + packageName); 336 } 337 mHandler.post(() -> { 338 try { 339 // Double check that the descriptor is still valid. 340 // We've seen production issues (b/76028139) where this can turn invalid (there are 341 // suspicions around the finalizer behaviour). 342 if (fd.getFileDescriptor().valid()) { 343 callback.onSuccess(fd); 344 } else { 345 Slog.wtf(TAG, "The snapshot FD became invalid before posting the result for " 346 + packageName); 347 callback.onError(ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); 348 } 349 } catch (RemoteException | RuntimeException e) { 350 Slog.w(TAG, 351 "Failed to call onSuccess after profile snapshot for " + packageName, e); 352 } finally { 353 IoUtils.closeQuietly(fd); 354 } 355 }); 356 } 357 358 // Constants used for logging compilation filter to TRON. 359 // DO NOT CHANGE existing values. 360 // 361 // NOTE: '-1' value is reserved for the case where we cannot produce a valid 362 // PackageOptimizationInfo because the ArtManagerInternal is not ready to be used by the 363 // ActivityMetricsLoggers. 364 private static final int TRON_COMPILATION_FILTER_ERROR = 0; 365 private static final int TRON_COMPILATION_FILTER_UNKNOWN = 1; 366 private static final int TRON_COMPILATION_FILTER_ASSUMED_VERIFIED = 2; 367 private static final int TRON_COMPILATION_FILTER_EXTRACT = 3; 368 private static final int TRON_COMPILATION_FILTER_VERIFY = 4; 369 private static final int TRON_COMPILATION_FILTER_QUICKEN = 5; 370 private static final int TRON_COMPILATION_FILTER_SPACE_PROFILE = 6; 371 private static final int TRON_COMPILATION_FILTER_SPACE = 7; 372 private static final int TRON_COMPILATION_FILTER_SPEED_PROFILE = 8; 373 private static final int TRON_COMPILATION_FILTER_SPEED = 9; 374 private static final int TRON_COMPILATION_FILTER_EVERYTHING_PROFILE = 10; 375 private static final int TRON_COMPILATION_FILTER_EVERYTHING = 11; 376 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK = 12; 377 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK = 13; 378 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK = 14; 379 // Filter with IORap 380 private static final int TRON_COMPILATION_FILTER_ASSUMED_VERIFIED_IORAP = 15; 381 private static final int TRON_COMPILATION_FILTER_EXTRACT_IORAP = 16; 382 private static final int TRON_COMPILATION_FILTER_VERIFY_IORAP = 17; 383 private static final int TRON_COMPILATION_FILTER_QUICKEN_IORAP = 18; 384 private static final int TRON_COMPILATION_FILTER_SPACE_PROFILE_IORAP = 19; 385 private static final int TRON_COMPILATION_FILTER_SPACE_IORAP = 20; 386 private static final int TRON_COMPILATION_FILTER_SPEED_PROFILE_IORAP = 21; 387 private static final int TRON_COMPILATION_FILTER_SPEED_IORAP = 22; 388 private static final int TRON_COMPILATION_FILTER_EVERYTHING_PROFILE_IORAP = 23; 389 private static final int TRON_COMPILATION_FILTER_EVERYTHING_IORAP = 24; 390 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_IORAP = 25; 391 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK_IORAP = 26; 392 private static final int TRON_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK_IORAP = 27; 393 394 // Constants used for logging compilation reason to TRON. 395 // DO NOT CHANGE existing values. 396 // 397 // In the below constants, the abbreviation DM stands for "DEX metadata". 398 // 399 // NOTE: '-1' value is reserved for the case where we cannot produce a valid 400 // PackageOptimizationInfo because the ArtManagerInternal is not ready to be used by the 401 // ActivityMetricsLoggers. 402 private static final int TRON_COMPILATION_REASON_ERROR = 0; 403 private static final int TRON_COMPILATION_REASON_UNKNOWN = 1; 404 private static final int TRON_COMPILATION_REASON_FIRST_BOOT = 2; 405 private static final int TRON_COMPILATION_REASON_BOOT_DEPRECATED_SINCE_S = 3; 406 private static final int TRON_COMPILATION_REASON_INSTALL = 4; 407 private static final int TRON_COMPILATION_REASON_BG_DEXOPT = 5; 408 private static final int TRON_COMPILATION_REASON_AB_OTA = 6; 409 private static final int TRON_COMPILATION_REASON_INACTIVE = 7; 410 private static final int TRON_COMPILATION_REASON_SHARED = 8; 411 private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DM = 9; 412 private static final int TRON_COMPILATION_REASON_INSTALL_FAST = 10; 413 private static final int TRON_COMPILATION_REASON_INSTALL_BULK = 11; 414 private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY = 12; 415 private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED = 13; 416 private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 14; 417 private static final int TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM = 15; 418 private static final int TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM = 16; 419 private static final int TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM = 17; 420 private static final int TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM = 18; 421 private static final int 422 TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM = 19; 423 private static final int TRON_COMPILATION_REASON_BOOT_AFTER_OTA = 20; 424 private static final int TRON_COMPILATION_REASON_POST_BOOT = 21; 425 private static final int TRON_COMPILATION_REASON_CMDLINE = 22; 426 private static final int TRON_COMPILATION_REASON_PREBUILT = 23; 427 private static final int TRON_COMPILATION_REASON_VDEX = 24; 428 private static final int TRON_COMPILATION_REASON_BOOT_AFTER_MAINLINE_UPDATE = 25; 429 430 // The annotation to add as a suffix to the compilation reason when dexopt was 431 // performed with dex metadata. 432 public static final String DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION = "-dm"; 433 434 /** 435 * Convert the compilation reason to an int suitable to be logged to TRON. 436 */ getCompilationReasonTronValue(String compilationReason)437 private static int getCompilationReasonTronValue(String compilationReason) { 438 switch (compilationReason) { 439 case "cmdline" : return TRON_COMPILATION_REASON_CMDLINE; 440 case "error" : return TRON_COMPILATION_REASON_ERROR; 441 case "first-boot" : return TRON_COMPILATION_REASON_FIRST_BOOT; 442 case "boot-after-ota": return TRON_COMPILATION_REASON_BOOT_AFTER_OTA; 443 case "boot-after-mainline-update": 444 return TRON_COMPILATION_REASON_BOOT_AFTER_MAINLINE_UPDATE; 445 case "post-boot" : return TRON_COMPILATION_REASON_POST_BOOT; 446 case "install" : return TRON_COMPILATION_REASON_INSTALL; 447 case "bg-dexopt" : return TRON_COMPILATION_REASON_BG_DEXOPT; 448 case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA; 449 case "inactive" : return TRON_COMPILATION_REASON_INACTIVE; 450 case "shared" : return TRON_COMPILATION_REASON_SHARED; 451 case "prebuilt" : return TRON_COMPILATION_REASON_PREBUILT; 452 case "vdex" : return TRON_COMPILATION_REASON_VDEX; 453 case "install-fast" : 454 return TRON_COMPILATION_REASON_INSTALL_FAST; 455 case "install-bulk" : 456 return TRON_COMPILATION_REASON_INSTALL_BULK; 457 case "install-bulk-secondary" : 458 return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY; 459 case "install-bulk-downgraded" : 460 return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED; 461 case "install-bulk-secondary-downgraded" : 462 return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; 463 // These are special markers for dex metadata installation that do not 464 // have an equivalent as a system property. 465 case "install" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : 466 return TRON_COMPILATION_REASON_INSTALL_WITH_DM; 467 case "install-fast" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : 468 return TRON_COMPILATION_REASON_INSTALL_FAST_WITH_DM; 469 case "install-bulk" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : 470 return TRON_COMPILATION_REASON_INSTALL_BULK_WITH_DM; 471 case "install-bulk-secondary" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : 472 return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_WITH_DM; 473 case "install-bulk-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : 474 return TRON_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED_WITH_DM; 475 case "install-bulk-secondary-downgraded" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : 476 return TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM; 477 default: return TRON_COMPILATION_REASON_UNKNOWN; 478 } 479 } 480 481 /** 482 * Convert the compilation filter to an int suitable to be logged to TRON. 483 */ getCompilationFilterTronValue(String compilationFilter)484 private static int getCompilationFilterTronValue(String compilationFilter) { 485 switch (compilationFilter) { 486 case "error" : return TRON_COMPILATION_FILTER_ERROR; 487 case "unknown" : return TRON_COMPILATION_FILTER_UNKNOWN; 488 case "assume-verified" : return TRON_COMPILATION_FILTER_ASSUMED_VERIFIED; 489 case "extract" : return TRON_COMPILATION_FILTER_EXTRACT; 490 case "verify" : return TRON_COMPILATION_FILTER_VERIFY; 491 case "quicken" : return TRON_COMPILATION_FILTER_QUICKEN; 492 case "space-profile" : return TRON_COMPILATION_FILTER_SPACE_PROFILE; 493 case "space" : return TRON_COMPILATION_FILTER_SPACE; 494 case "speed-profile" : return TRON_COMPILATION_FILTER_SPEED_PROFILE; 495 case "speed" : return TRON_COMPILATION_FILTER_SPEED; 496 case "everything-profile" : return TRON_COMPILATION_FILTER_EVERYTHING_PROFILE; 497 case "everything" : return TRON_COMPILATION_FILTER_EVERYTHING; 498 case "run-from-apk" : return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK; 499 case "run-from-apk-fallback" : 500 return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK; 501 case "run-from-vdex-fallback" : 502 return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK; 503 case "assume-verified-iorap" : return TRON_COMPILATION_FILTER_ASSUMED_VERIFIED_IORAP; 504 case "extract-iorap" : return TRON_COMPILATION_FILTER_EXTRACT_IORAP; 505 case "verify-iorap" : return TRON_COMPILATION_FILTER_VERIFY_IORAP; 506 case "quicken-iorap" : return TRON_COMPILATION_FILTER_QUICKEN_IORAP; 507 case "space-profile-iorap" : return TRON_COMPILATION_FILTER_SPACE_PROFILE_IORAP; 508 case "space-iorap" : return TRON_COMPILATION_FILTER_SPACE_IORAP; 509 case "speed-profile-iorap" : return TRON_COMPILATION_FILTER_SPEED_PROFILE_IORAP; 510 case "speed-iorap" : return TRON_COMPILATION_FILTER_SPEED_IORAP; 511 case "everything-profile-iorap" : 512 return TRON_COMPILATION_FILTER_EVERYTHING_PROFILE_IORAP; 513 case "everything-iorap" : return TRON_COMPILATION_FILTER_EVERYTHING_IORAP; 514 case "run-from-apk-iorap" : return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_IORAP; 515 case "run-from-apk-fallback-iorap" : 516 return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK_IORAP; 517 case "run-from-vdex-fallback-iorap" : 518 return TRON_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK_IORAP; 519 default: return TRON_COMPILATION_FILTER_UNKNOWN; 520 } 521 } 522 verifyTronLoggingConstants()523 private static void verifyTronLoggingConstants() { 524 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 525 String reason = PackageManagerServiceCompilerMapping.REASON_STRINGS[i]; 526 int value = getCompilationReasonTronValue(reason); 527 if (value == TRON_COMPILATION_REASON_ERROR 528 || value == TRON_COMPILATION_REASON_UNKNOWN) { 529 throw new IllegalArgumentException("Compilation reason not configured for TRON " 530 + "logging: " + reason); 531 } 532 } 533 } 534 535 private class ArtManagerInternalImpl extends ArtManagerInternal { 536 private static final String IORAP_DIR = "/data/misc/iorapd"; 537 private static final String TAG = "ArtManagerInternalImpl"; 538 539 @Override getPackageOptimizationInfo( ApplicationInfo info, String abi, String activityName)540 public PackageOptimizationInfo getPackageOptimizationInfo( 541 ApplicationInfo info, String abi, String activityName) { 542 if (info.packageName.equals(PackageManagerService.PLATFORM_PACKAGE_NAME)) { 543 // PackageManagerService.PLATFORM_PACKAGE_NAME in this context means that the 544 // activity is defined in bootclasspath. Currently, we don't have an API to get the 545 // correct optimization info. 546 return PackageOptimizationInfo.createWithNoInfo(); 547 } 548 549 String compilationReason; 550 String compilationFilter; 551 try { 552 String isa = VMRuntime.getInstructionSet(abi); 553 DexFile.OptimizationInfo optInfo = 554 DexFile.getDexFileOptimizationInfo(info.getBaseCodePath(), isa); 555 compilationFilter = optInfo.getStatus(); 556 compilationReason = optInfo.getReason(); 557 } catch (FileNotFoundException e) { 558 Slog.e(TAG, "Could not get optimizations status for " + info.getBaseCodePath(), e); 559 compilationFilter = "error"; 560 compilationReason = "error"; 561 } catch (IllegalArgumentException e) { 562 Slog.wtf(TAG, "Requested optimization status for " + info.getBaseCodePath() 563 + " due to an invalid abi " + abi, e); 564 compilationFilter = "error"; 565 compilationReason = "error"; 566 } 567 568 if (checkIorapCompiledTrace(info.packageName, activityName, info.longVersionCode)) { 569 compilationFilter = compilationFilter + "-iorap"; 570 } 571 572 int compilationFilterTronValue = getCompilationFilterTronValue(compilationFilter); 573 int compilationReasonTronValue = getCompilationReasonTronValue(compilationReason); 574 575 return new PackageOptimizationInfo( 576 compilationFilterTronValue, compilationReasonTronValue); 577 } 578 579 /* 580 * Checks the existence of IORap compiled trace for an app. 581 * 582 * @return true if the compiled trace exists and the size is greater than 1kb. 583 */ checkIorapCompiledTrace( String packageName, String activityName, long version)584 private boolean checkIorapCompiledTrace( 585 String packageName, String activityName, long version) { 586 // For example: /data/misc/iorapd/com.google.android.GoogleCamera/ 587 // 60092239/com.android.camera.CameraLauncher/compiled_traces/compiled_trace.pb 588 // TODO(b/258223472): Clean up iorap code. 589 Path tracePath = Paths.get(IORAP_DIR, 590 packageName, 591 Long.toString(version), 592 activityName, 593 "compiled_traces", 594 "compiled_trace.pb"); 595 try { 596 boolean exists = Files.exists(tracePath); 597 if (DEBUG) { 598 Log.d(TAG, tracePath.toString() + (exists? " exists" : " doesn't exist")); 599 } 600 if (exists) { 601 long bytes = Files.size(tracePath); 602 if (DEBUG) { 603 Log.d(TAG, tracePath.toString() + " size is " + Long.toString(bytes)); 604 } 605 return bytes > 0L; 606 } 607 return exists; 608 } catch (IOException e) { 609 Log.d(TAG, e.getMessage()); 610 return false; 611 } 612 } 613 } 614 } 615