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