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