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