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