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