1 /* 2 * Copyright (C) 2007 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 dalvik.system; 18 19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 20 21 import android.annotation.SystemApi; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.system.ErrnoException; 24 25 import java.io.File; 26 import java.io.FileNotFoundException; 27 import java.io.IOException; 28 import java.nio.ByteBuffer; 29 import java.util.Arrays; 30 import java.util.Enumeration; 31 import java.util.List; 32 import libcore.io.Libcore; 33 import libcore.util.NonNull; 34 import libcore.util.Nullable; 35 36 import dalvik.annotation.optimization.ReachabilitySensitive; 37 38 /** 39 * Loads DEX files. This class is meant for internal use and should not be used 40 * by applications. 41 * 42 * @deprecated This class should not be used directly by applications. It will hurt 43 * performance in most cases and will lead to incorrect execution of bytecode in 44 * the worst case. Applications should use one of the standard classloaders such 45 * as {@link dalvik.system.PathClassLoader} instead. <b>This API will be removed 46 * in a future Android release</b>. 47 */ 48 @Deprecated 49 public final class DexFile { 50 /** 51 * If close is called, mCookie becomes null but the internal cookie is preserved if the close 52 * failed so that we can free resources in the finalizer. 53 */ 54 @UnsupportedAppUsage 55 @ReachabilitySensitive 56 private Object mCookie; 57 58 @UnsupportedAppUsage 59 private Object mInternalCookie; 60 @UnsupportedAppUsage 61 private final String mFileName; 62 63 /** 64 * Opens a DEX file from a given File object. 65 * 66 * @deprecated Applications should use one of the standard classloaders such 67 * as {@link dalvik.system.PathClassLoader} instead. <b>This API will be removed 68 * in a future Android release</b>. 69 */ 70 @Deprecated DexFile(File file)71 public DexFile(File file) throws IOException { 72 this(file.getPath()); 73 } 74 /* 75 * Private version with class loader argument. 76 * 77 * @param file 78 * the File object referencing the actual DEX file 79 * @param loader 80 * the class loader object creating the DEX file object 81 * @param elements 82 * the temporary dex path list elements from DexPathList.makeElements 83 */ DexFile(File file, ClassLoader loader, DexPathList.Element[] elements)84 DexFile(File file, ClassLoader loader, DexPathList.Element[] elements) 85 throws IOException { 86 this(file.getPath(), loader, elements); 87 } 88 89 /** 90 * Opens a DEX file from a given filename. 91 * 92 * @deprecated Applications should use one of the standard classloaders such 93 * as {@link dalvik.system.PathClassLoader} instead. <b>This API will be removed 94 * in a future Android release</b>. 95 */ 96 @Deprecated DexFile(String fileName)97 public DexFile(String fileName) throws IOException { 98 this(fileName, null, null); 99 } 100 101 /* 102 * Private version with class loader argument. 103 * 104 * @param fileName 105 * the filename of the DEX file 106 * @param loader 107 * the class loader creating the DEX file object 108 * @param elements 109 * the temporary dex path list elements from DexPathList.makeElements 110 */ DexFile(String fileName, ClassLoader loader, DexPathList.Element[] elements)111 DexFile(String fileName, ClassLoader loader, DexPathList.Element[] elements) 112 throws IOException { 113 mCookie = openDexFile(fileName, null, 0, loader, elements); 114 mInternalCookie = mCookie; 115 mFileName = fileName; 116 //System.out.println("DEX FILE cookie is " + mCookie + " fileName=" + fileName); 117 } 118 DexFile(ByteBuffer[] bufs, ClassLoader loader, DexPathList.Element[] elements)119 DexFile(ByteBuffer[] bufs, ClassLoader loader, DexPathList.Element[] elements) 120 throws IOException { 121 mCookie = openInMemoryDexFiles(bufs, loader, elements); 122 mInternalCookie = mCookie; 123 mFileName = null; 124 } 125 126 /** 127 * Opens a DEX file from a given filename, using a specified file 128 * to hold the optimized data. 129 * 130 * @param sourceName 131 * Jar or APK file with "classes.dex". 132 * @param outputName 133 * File that will hold the optimized form of the DEX data. 134 * @param flags 135 * Enable optional features. 136 * @param loader 137 * The class loader creating the DEX file object. 138 * @param elements 139 * The temporary dex path list elements from DexPathList.makeElements 140 */ DexFile(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements)141 private DexFile(String sourceName, String outputName, int flags, ClassLoader loader, 142 DexPathList.Element[] elements) throws IOException { 143 if (outputName != null) { 144 try { 145 String parent = new File(outputName).getParent(); 146 if (Libcore.os.getuid() != Libcore.os.stat(parent).st_uid) { 147 throw new IllegalArgumentException("Optimized data directory " + parent 148 + " is not owned by the current user. Shared storage cannot protect" 149 + " your application from code injection attacks."); 150 } 151 } catch (ErrnoException ignored) { 152 // assume we'll fail with a more contextual error later 153 } 154 } 155 156 mCookie = openDexFile(sourceName, outputName, flags, loader, elements); 157 mInternalCookie = mCookie; 158 mFileName = sourceName; 159 //System.out.println("DEX FILE cookie is " + mCookie + " sourceName=" + sourceName + " outputName=" + outputName); 160 } 161 162 /** 163 * Open a DEX file, specifying the file in which the optimized DEX 164 * data should be written. If the optimized form exists and appears 165 * to be current, it will be used; if not, the VM will attempt to 166 * regenerate it. 167 * 168 * @deprecated Applications should use one of the standard classloaders such 169 * as {@link dalvik.system.PathClassLoader} instead. <b>This API will be removed 170 * in a future Android release</b>. 171 */ 172 @Deprecated loadDex(String sourcePathName, String outputPathName, int flags)173 static public DexFile loadDex(String sourcePathName, String outputPathName, 174 int flags) throws IOException { 175 176 /* 177 * TODO: we may want to cache previously-opened DexFile objects. 178 * The cache would be synchronized with close(). This would help 179 * us avoid mapping the same DEX more than once when an app 180 * decided to open it multiple times. In practice this may not 181 * be a real issue. 182 */ 183 return loadDex(sourcePathName, outputPathName, flags, null, null); 184 } 185 186 /* 187 * Private version of loadDex that also takes a class loader. 188 * 189 * @param sourcePathName 190 * Jar or APK file with "classes.dex". (May expand this to include 191 * "raw DEX" in the future.) 192 * @param outputPathName 193 * File that will hold the optimized form of the DEX data. 194 * @param flags 195 * Enable optional features. (Currently none defined.) 196 * @param loader 197 * Class loader that is aloading the DEX file. 198 * @param elements 199 * The temporary dex path list elements from DexPathList.makeElements 200 * @return 201 * A new or previously-opened DexFile. 202 * @throws IOException 203 * If unable to open the source or output file. 204 */ 205 @UnsupportedAppUsage loadDex(String sourcePathName, String outputPathName, int flags, ClassLoader loader, DexPathList.Element[] elements)206 static DexFile loadDex(String sourcePathName, String outputPathName, 207 int flags, ClassLoader loader, DexPathList.Element[] elements) throws IOException { 208 209 /* 210 * TODO: we may want to cache previously-opened DexFile objects. 211 * The cache would be synchronized with close(). This would help 212 * us avoid mapping the same DEX more than once when an app 213 * decided to open it multiple times. In practice this may not 214 * be a real issue. 215 */ 216 return new DexFile(sourcePathName, outputPathName, flags, loader, elements); 217 } 218 219 /** 220 * Gets the name of the (already opened) DEX file. 221 * 222 * @return the file name 223 */ getName()224 public String getName() { 225 return mFileName; 226 } 227 toString()228 @Override public String toString() { 229 if (mFileName != null) { 230 return getName(); 231 } else { 232 return "InMemoryDexFile[cookie=" + Arrays.toString((long[]) mCookie) + "]"; 233 } 234 } 235 236 /** 237 * Closes the DEX file. 238 * <p> 239 * This may not be able to release all of the resources. If classes from this DEX file are 240 * still resident, the DEX file can't be unmapped. In the case where we do not release all 241 * the resources, close is called again in the finalizer. 242 * 243 * @throws IOException 244 * if an I/O error occurs during closing the file, which 245 * normally should not happen 246 */ close()247 public void close() throws IOException { 248 if (mInternalCookie != null) { 249 if (closeDexFile(mInternalCookie)) { 250 mInternalCookie = null; 251 } 252 mCookie = null; 253 } 254 } 255 256 /** 257 * Loads a class. Returns the class on success, or a {@code null} reference 258 * on failure. 259 * <p> 260 * If you are not calling this from a class loader, this is most likely not 261 * going to do what you want. Use {@link Class#forName(String)} instead. 262 * <p> 263 * The method does not throw {@link ClassNotFoundException} if the class 264 * isn't found because it isn't reasonable to throw exceptions wildly every 265 * time a class is not found in the first DEX file we look at. 266 * 267 * @param name 268 * the class name, which should look like "java/lang/String" 269 * 270 * @param loader 271 * the class loader that tries to load the class (in most cases 272 * the caller of the method 273 * 274 * @return the {@link Class} object representing the class, or {@code null} 275 * if the class cannot be loaded 276 */ loadClass(String name, ClassLoader loader)277 public Class loadClass(String name, ClassLoader loader) { 278 String slashName = name.replace('.', '/'); 279 return loadClassBinaryName(slashName, loader, null); 280 } 281 282 /** 283 * See {@link #loadClass(String, ClassLoader)}. 284 * 285 * This takes a "binary" class name to better match ClassLoader semantics. 286 * 287 * @hide 288 */ 289 @UnsupportedAppUsage loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed)290 public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) { 291 return defineClass(name, loader, mCookie, this, suppressed); 292 } 293 defineClass(String name, ClassLoader loader, Object cookie, DexFile dexFile, List<Throwable> suppressed)294 private static Class defineClass(String name, ClassLoader loader, Object cookie, 295 DexFile dexFile, List<Throwable> suppressed) { 296 Class result = null; 297 try { 298 result = defineClassNative(name, loader, cookie, dexFile); 299 } catch (NoClassDefFoundError e) { 300 if (suppressed != null) { 301 suppressed.add(e); 302 } 303 } catch (ClassNotFoundException e) { 304 if (suppressed != null) { 305 suppressed.add(e); 306 } 307 } 308 return result; 309 } 310 311 /** 312 * Enumerate the names of the classes in this DEX file. 313 * 314 * @return an enumeration of names of classes contained in the DEX file, in 315 * the usual internal form (like "java/lang/String"). 316 */ entries()317 public Enumeration<String> entries() { 318 return new DFEnum(this); 319 } 320 321 /* 322 * Helper class. 323 */ 324 private static class DFEnum implements Enumeration<String> { 325 private int mIndex; 326 @UnsupportedAppUsage 327 private String[] mNameList; 328 DFEnum(DexFile df)329 DFEnum(DexFile df) { 330 mIndex = 0; 331 mNameList = getClassNameList(df.mCookie); 332 } 333 hasMoreElements()334 public boolean hasMoreElements() { 335 return (mIndex < mNameList.length); 336 } 337 nextElement()338 public String nextElement() { 339 return mNameList[mIndex++]; 340 } 341 } 342 343 /** 344 * Called when the class is finalized. Makes sure the DEX file is closed. 345 * 346 * @throws IOException 347 * if an I/O error occurs during closing the file, which 348 * normally should not happen 349 */ finalize()350 @Override protected void finalize() throws Throwable { 351 try { 352 if (mInternalCookie != null && !closeDexFile(mInternalCookie)) { 353 throw new AssertionError("Failed to close dex file in finalizer."); 354 } 355 mInternalCookie = null; 356 mCookie = null; 357 } finally { 358 super.finalize(); 359 } 360 } 361 362 363 /* 364 * Open a DEX file. The value returned is a magic VM cookie. On 365 * failure, an IOException is thrown. 366 */ 367 @UnsupportedAppUsage openDexFile(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements)368 private static Object openDexFile(String sourceName, String outputName, int flags, 369 ClassLoader loader, DexPathList.Element[] elements) throws IOException { 370 // Use absolute paths to enable the use of relative paths when testing on host. 371 return openDexFileNative(new File(sourceName).getAbsolutePath(), 372 (outputName == null) 373 ? null 374 : new File(outputName).getAbsolutePath(), 375 flags, 376 loader, 377 elements); 378 } 379 openInMemoryDexFiles(ByteBuffer[] bufs, ClassLoader loader, DexPathList.Element[] elements)380 private static Object openInMemoryDexFiles(ByteBuffer[] bufs, ClassLoader loader, 381 DexPathList.Element[] elements) throws IOException { 382 // Preprocess the ByteBuffers for openInMemoryDexFilesNative. We extract 383 // the backing array (non-direct buffers only) and start/end positions 384 // so that the native method does not have to call Java methods anymore. 385 byte[][] arrays = new byte[bufs.length][]; 386 int[] starts = new int[bufs.length]; 387 int[] ends = new int[bufs.length]; 388 for (int i = 0; i < bufs.length; ++i) { 389 arrays[i] = bufs[i].isDirect() ? null : bufs[i].array(); 390 starts[i] = bufs[i].position(); 391 ends[i] = bufs[i].limit(); 392 } 393 return openInMemoryDexFilesNative(bufs, arrays, starts, ends, loader, elements); 394 } 395 openInMemoryDexFilesNative(ByteBuffer[] bufs, byte[][] arrays, int[] starts, int[] ends, ClassLoader loader, DexPathList.Element[] elements)396 private static native Object openInMemoryDexFilesNative(ByteBuffer[] bufs, byte[][] arrays, 397 int[] starts, int[] ends, ClassLoader loader, DexPathList.Element[] elements); 398 399 /* 400 * Initiates background verification of this DexFile. This is a sepearate down-call 401 * from openDexFile and openInMemoryDexFiles because it requires the class loader's 402 * DexPathList to have been initialized for its classes to be resolvable by ART. 403 * DexPathList will open the dex files first, finalize `dexElements` and then call this. 404 */ verifyInBackground(ClassLoader classLoader)405 /*package*/ void verifyInBackground(ClassLoader classLoader) { 406 verifyInBackgroundNative(mCookie, classLoader); 407 } 408 verifyInBackgroundNative(Object mCookie, ClassLoader classLoader)409 private static native void verifyInBackgroundNative(Object mCookie, ClassLoader classLoader); 410 411 /* 412 * Returns true if the dex file is backed by a valid oat file. 413 */ 414 @UnsupportedAppUsage isBackedByOatFile()415 /*package*/ boolean isBackedByOatFile() { 416 return isBackedByOatFile(mCookie); 417 } 418 419 /* 420 * Set the dex file as trusted: it can access hidden APIs of the platform. 421 */ setTrusted()422 /*package*/ void setTrusted() { 423 setTrusted(mCookie); 424 } 425 426 /* 427 * Returns true if we managed to close the dex file. 428 */ closeDexFile(Object cookie)429 private static native boolean closeDexFile(Object cookie); defineClassNative(String name, ClassLoader loader, Object cookie, DexFile dexFile)430 private static native Class defineClassNative(String name, ClassLoader loader, Object cookie, 431 DexFile dexFile) 432 throws ClassNotFoundException, NoClassDefFoundError; 433 @UnsupportedAppUsage getClassNameList(Object cookie)434 private static native String[] getClassNameList(Object cookie); isBackedByOatFile(Object cookie)435 private static native boolean isBackedByOatFile(Object cookie); setTrusted(Object cookie)436 private static native void setTrusted(Object cookie); 437 /* 438 * Open a DEX file. The value returned is a magic VM cookie. On 439 * failure, an IOException is thrown. 440 */ 441 @UnsupportedAppUsage openDexFileNative(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements)442 private static native Object openDexFileNative(String sourceName, String outputName, int flags, 443 ClassLoader loader, DexPathList.Element[] elements); 444 445 /** 446 * Returns true if the VM believes that the apk/jar file is out of date 447 * and should be passed through "dexopt" again. 448 * 449 * @param fileName the absolute path to the apk/jar file to examine. 450 * @return true if dexopt should be called on the file, false otherwise. 451 * @throws java.io.FileNotFoundException if fileName is not readable, 452 * not a file, or not present. 453 * @throws java.io.IOException if fileName is not a valid apk/jar file or 454 * if problems occur while parsing it. 455 * @throws java.lang.NullPointerException if fileName is null. 456 */ isDexOptNeeded(String fileName)457 public static native boolean isDexOptNeeded(String fileName) 458 throws FileNotFoundException, IOException; 459 460 /** 461 * No dexopt should (or can) be done to update the apk/jar. 462 * 463 * See {@link #getDexOptNeeded(String, String, String, boolean, boolean)}. 464 * 465 * @hide 466 */ 467 @SystemApi(client = MODULE_LIBRARIES) 468 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 469 public static final int NO_DEXOPT_NEEDED = 0; 470 471 /** 472 * dex2oat should be run to update the apk/jar from scratch. 473 * 474 * See {@link #getDexOptNeeded(String, String, String, boolean, boolean)}. 475 * 476 * @hide 477 */ 478 public static final int DEX2OAT_FROM_SCRATCH = 1; 479 480 /** 481 * dex2oat should be run to update the apk/jar because the existing code 482 * is out of date with respect to the boot image. 483 * 484 * See {@link #getDexOptNeeded(String, String, String, boolean, boolean)}. 485 * 486 * @hide 487 */ 488 public static final int DEX2OAT_FOR_BOOT_IMAGE = 2; 489 490 /** 491 * dex2oat should be run to update the apk/jar because the existing code 492 * is out of date with respect to the target compiler filter. 493 * 494 * See {@link #getDexOptNeeded(String, String, String, boolean, boolean)}. 495 * 496 * @hide 497 */ 498 @SystemApi(client = MODULE_LIBRARIES) 499 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 500 public static final int DEX2OAT_FOR_FILTER = 3; 501 502 503 /** 504 * Calls {@link #getDexOptNeeded(String, String, String, String, String, boolean, boolean)} 505 * with a null class loader context. 506 * 507 * TODO(ngeoffray, calin): deprecate / remove. 508 * @hide 509 */ getDexOptNeeded(String fileName, String instructionSet, String compilerFilter, boolean newProfile, boolean downgrade)510 public static int getDexOptNeeded(String fileName, 511 String instructionSet, String compilerFilter, boolean newProfile, boolean downgrade) 512 throws FileNotFoundException, IOException { 513 return getDexOptNeeded( 514 fileName, instructionSet, compilerFilter, null, newProfile, downgrade); 515 } 516 517 /** 518 * Returns the VM's opinion of what kind of dexopt is needed to make the 519 * apk/jar file up to date, where {@code targetMode} is used to indicate what 520 * type of compilation the caller considers up-to-date, and {@code newProfile} 521 * is used to indicate whether profile information has changed recently. 522 * 523 * @param fileName the absolute path to the apk/jar file to examine. 524 * @param instructionSet instruction set to examine 525 * @param compilerFilter a compiler filter to use for what a caller considers up-to-date. 526 * @param classLoaderContext a string encoding the class loader context the dex file 527 * is intended to have at runtime. 528 * @param newProfile flag that describes whether a profile corresponding 529 * to the dex file has been recently updated and should be considered 530 * in the state of the file. 531 * @param downgrade flag that describes if the purpose of dexopt is to downgrade the 532 * compiler filter. If set to false, will be evaluated as an upgrade request. 533 * @return NO_DEXOPT_NEEDED, or DEX2OAT_*. See documentation 534 * of the particular status code for more information on its 535 * meaning. Returns a positive status code if the status refers to 536 * the oat file in the oat location. Returns a negative status 537 * code if the status refers to the oat file in the odex location. 538 * @throws java.io.FileNotFoundException if fileName is not readable, 539 * not a file, or not present. 540 * @throws java.io.IOException if fileName is not a valid apk/jar file or 541 * if problems occur while parsing it. 542 * @throws java.lang.NullPointerException if {@code fileName} is {@code null}. 543 * 544 * @hide 545 */ 546 @SystemApi(client = MODULE_LIBRARIES) 547 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getDexOptNeeded(@onNull String fileName, @NonNull String instructionSet, @NonNull String compilerFilter, @Nullable String classLoaderContext, boolean newProfile, boolean downgrade)548 public static native int getDexOptNeeded(@NonNull String fileName, 549 @NonNull String instructionSet, @NonNull String compilerFilter, @Nullable String classLoaderContext, 550 boolean newProfile, boolean downgrade) 551 throws FileNotFoundException, IOException; 552 553 /** 554 * Returns the status of the dex file {@code fileName}. The returned string is 555 * an opaque, human readable representation of the current status. The output 556 * is only meant for debugging and is not guaranteed to be stable across 557 * releases and/or devices. 558 * 559 * @hide 560 */ getDexFileStatus(String fileName, String instructionSet)561 public static native String getDexFileStatus(String fileName, String instructionSet) 562 throws FileNotFoundException; 563 564 /** 565 * Encapsulates information about the optimizations performed on a dex file. 566 * 567 * Note that the info is only meant for debugging and is not guaranteed to be 568 * stable across releases and/or devices. 569 * 570 * @hide 571 */ 572 @SystemApi(client = MODULE_LIBRARIES) 573 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 574 public static final class OptimizationInfo { 575 // The human readable refined optimization status of the validity of the odex file. 576 private final String status; 577 // The optimization reason. The reason might be "unknown" if the 578 // the compiler artifacts were not annotated during optimizations. 579 private final String reason; 580 OptimizationInfo(String status, String reason)581 private OptimizationInfo(String status, String reason) { 582 this.status = status; 583 this.reason = reason; 584 } 585 586 /** 587 * Returns the human readable refined status of the validity of the odex file. 588 * 589 * @return optimization status 590 * 591 * @hide 592 */ 593 @SystemApi(client = MODULE_LIBRARIES) 594 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getStatus()595 public @NonNull String getStatus() { 596 return status; 597 } 598 599 /** 600 * Returns the reason of a particular optimization used. 601 * 602 * @return optimization reason 603 * 604 * @hide 605 */ 606 @SystemApi(client = MODULE_LIBRARIES) 607 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getReason()608 public @NonNull String getReason() { 609 return reason; 610 } 611 } 612 613 /** 614 * Retrieves the optimization info for a dex file. 615 * 616 * @param fileName path to dex file 617 * @param instructionSet instruction set to get optimization info for 618 * @return {@link OptimizationInfo} for {@code fileName} dex file 619 * @throws FileNotFoundException if {@code fileName} not found 620 * 621 * @hide 622 */ 623 @SystemApi(client = MODULE_LIBRARIES) 624 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getDexFileOptimizationInfo( @onNull String fileName, @NonNull String instructionSet)625 public static @NonNull OptimizationInfo getDexFileOptimizationInfo( 626 @NonNull String fileName, @NonNull String instructionSet) throws FileNotFoundException { 627 String[] status = getDexFileOptimizationStatus(fileName, instructionSet); 628 return new OptimizationInfo(status[0], status[1]); 629 } 630 631 /** 632 * Returns the optimization status of the dex file {@code fileName}. The returned 633 * array will have 2 elements which specify: 634 * - index 0: the level of optimizations 635 * - index 1: the optimization reason. The reason might be "unknown" if the 636 * the compiler artifacts were not annotated during optimizations. 637 * 638 * The output is only meant for debugging and is not guaranteed to be stable across 639 * releases and/or devices. 640 * 641 * @hide 642 */ getDexFileOptimizationStatus( String fileName, String instructionSet)643 private static native String[] getDexFileOptimizationStatus( 644 String fileName, String instructionSet) throws FileNotFoundException; 645 646 /** 647 * Returns the paths of the optimized files generated for {@code fileName}. 648 * If no optimized code exists the method returns {@code null}. 649 * 650 * @param fileName path to dex file 651 * @param instructionSet instruction set to get optimized files for 652 * @return paths to optimized code, or {@code null} if they do not exist 653 * @throws FileNotFoundException 654 * 655 * @hide 656 */ 657 @SystemApi(client = MODULE_LIBRARIES) 658 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getDexFileOutputPaths(@onNull String fileName, @NonNull String instructionSet)659 public static native @Nullable String[] getDexFileOutputPaths(@NonNull String fileName, @NonNull String instructionSet) 660 throws FileNotFoundException; 661 662 /** 663 * Returns whether the given filter is a valid filter. 664 * 665 * @param filter filter string 666 * @return whether given filter string is a valid filter 667 * 668 * @hide 669 */ 670 @SystemApi(client = MODULE_LIBRARIES) 671 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) isValidCompilerFilter(@onNull String filter)672 public native static boolean isValidCompilerFilter(@NonNull String filter); 673 674 /** 675 * Returns whether the given filter is based on profiles. 676 * 677 * @param filter filter string 678 * @return whether given filter string is based on profiles 679 * 680 * @hide 681 */ 682 @SystemApi(client = MODULE_LIBRARIES) 683 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) isProfileGuidedCompilerFilter(@onNull String filter)684 public native static boolean isProfileGuidedCompilerFilter(@NonNull String filter); 685 686 /** 687 * Returns the version of the compiler filter that is not based on profiles. 688 * If the input is not a valid filter, or the filter is already not based on 689 * profiles, this returns the input. 690 * 691 * @param filter filter string 692 * @return version of the compiler filter that is not based on profiles 693 * 694 * @hide 695 */ getNonProfileGuidedCompilerFilter(String filter)696 public native static String getNonProfileGuidedCompilerFilter(String filter); 697 698 /** 699 * Returns the version of the compiler filter that is suitable for safe mode. 700 * If the input is not a valid filter, or the filter is already suitable for 701 * safe mode, this returns the input. 702 * 703 * @param filter filter string 704 * @return version of the compiler filter that is suitable for safe mode 705 * 706 * @hide 707 */ 708 @SystemApi(client = MODULE_LIBRARIES) 709 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getSafeModeCompilerFilter(@onNull String filter)710 public native static @NonNull String getSafeModeCompilerFilter(@NonNull String filter); 711 712 /** 713 * Returns the static file size of the original dex file. 714 * The original size of the uncompressed dex file is returned. 715 * On device the dex file may be compressed or embedded in some other 716 * file (e.g. oat) in a platform implementation dependent manner. This 717 * method abstracts away from those details and provides an efficient 718 * implementation given that the dex file in question has already been 719 * uncompressed, extracted, and/or loaded by the runtime as appropriate. 720 * <p> 721 * In the case of multidex, returns the sum of the original uncompressed 722 * multidex entry file sizes. 723 * 724 * @hide 725 */ getStaticSizeOfDexFile()726 public long getStaticSizeOfDexFile() { 727 return getStaticSizeOfDexFile(mCookie); 728 } 729 getStaticSizeOfDexFile(Object cookie)730 private static native long getStaticSizeOfDexFile(Object cookie); 731 } 732