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
17package dalvik.system;
18
19import java.util.HashMap;
20import java.util.Map;
21
22/**
23 * Provides an interface to VM-global, Dalvik-specific features.
24 * An application cannot create its own Runtime instance, and must obtain
25 * one from the getRuntime method.
26 *
27 * @hide
28 */
29public final class VMRuntime {
30
31    /**
32     * Holds the VMRuntime singleton.
33     */
34    private static final VMRuntime THE_ONE = new VMRuntime();
35
36    private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
37            = new HashMap<String, String>();
38    static {
39        ABI_TO_INSTRUCTION_SET_MAP.put("armeabi", "arm");
40        ABI_TO_INSTRUCTION_SET_MAP.put("armeabi-v7a", "arm");
41        ABI_TO_INSTRUCTION_SET_MAP.put("mips", "mips");
42        ABI_TO_INSTRUCTION_SET_MAP.put("mips64", "mips64");
43        ABI_TO_INSTRUCTION_SET_MAP.put("x86", "x86");
44        ABI_TO_INSTRUCTION_SET_MAP.put("x86_64", "x86_64");
45        ABI_TO_INSTRUCTION_SET_MAP.put("arm64-v8a", "arm64");
46    }
47
48    private int targetSdkVersion;
49
50    /**
51     * Prevents this class from being instantiated.
52     */
53    private VMRuntime() {
54    }
55
56    /**
57     * Returns the object that represents the VM instance's Dalvik-specific
58     * runtime environment.
59     *
60     * @return the runtime object
61     */
62    public static VMRuntime getRuntime() {
63        return THE_ONE;
64    }
65
66    /**
67     * Returns a copy of the VM's command-line property settings.
68     * These are in the form "name=value" rather than "-Dname=value".
69     */
70    public native String[] properties();
71
72    /**
73     * Returns the VM's boot class path.
74     */
75    public native String bootClassPath();
76
77    /**
78     * Returns the VM's class path.
79     */
80    public native String classPath();
81
82    /**
83     * Returns the VM's version.
84     */
85    public native String vmVersion();
86
87    /**
88     * Returns the name of the shared library providing the VM implementation.
89     */
90    public native String vmLibrary();
91
92    /**
93     * Returns the VM's instruction set.
94     */
95    public native String vmInstructionSet();
96
97    /**
98     * Returns whether the VM is running in 64-bit mode.
99     */
100    public native boolean is64Bit();
101
102    /**
103     * Returns whether the VM is running with JNI checking enabled.
104     */
105    public native boolean isCheckJniEnabled();
106
107    /**
108     * Gets the current ideal heap utilization, represented as a number
109     * between zero and one.  After a GC happens, the Dalvik heap may
110     * be resized so that (size of live objects) / (size of heap) is
111     * equal to this number.
112     *
113     * @return the current ideal heap utilization
114     */
115    public native float getTargetHeapUtilization();
116
117    /**
118     * Sets the current ideal heap utilization, represented as a number
119     * between zero and one.  After a GC happens, the Dalvik heap may
120     * be resized so that (size of live objects) / (size of heap) is
121     * equal to this number.
122     *
123     * <p>This is only a hint to the garbage collector and may be ignored.
124     *
125     * @param newTarget the new suggested ideal heap utilization.
126     *                  This value may be adjusted internally.
127     * @return the previous ideal heap utilization
128     * @throws IllegalArgumentException if newTarget is &lt;= 0.0 or &gt;= 1.0
129     */
130    public float setTargetHeapUtilization(float newTarget) {
131        if (newTarget <= 0.0f || newTarget >= 1.0f) {
132            throw new IllegalArgumentException(newTarget +
133                    " out of range (0,1)");
134        }
135        /* Synchronize to make sure that only one thread gets
136         * a given "old" value if both update at the same time.
137         * Allows for reliable save-and-restore semantics.
138         */
139        synchronized (this) {
140            float oldTarget = getTargetHeapUtilization();
141            nativeSetTargetHeapUtilization(newTarget);
142            return oldTarget;
143        }
144    }
145
146    /**
147     * Sets the target SDK version. Should only be called before the
148     * app starts to run, because it may change the VM's behavior in
149     * dangerous ways. Use 0 to mean "current" (since callers won't
150     * necessarily know the actual current SDK version, and the
151     * allocated version numbers start at 1), and 10000 to mean
152     * CUR_DEVELOPMENT.
153     */
154    public synchronized void setTargetSdkVersion(int targetSdkVersion) {
155        this.targetSdkVersion = targetSdkVersion;
156        setTargetSdkVersionNative(this.targetSdkVersion);
157    }
158
159    /**
160     * Gets the target SDK version. See {@link #setTargetSdkVersion} for
161     * special values.
162     */
163    public synchronized int getTargetSdkVersion() {
164        return targetSdkVersion;
165    }
166
167    private native void setTargetSdkVersionNative(int targetSdkVersion);
168
169    /**
170     * This method exists for binary compatibility.  It was part of a
171     * heap sizing API which was removed in Android 3.0 (Honeycomb).
172     */
173    @Deprecated
174    public long getMinimumHeapSize() {
175        return 0;
176    }
177
178    /**
179     * This method exists for binary compatibility.  It was part of a
180     * heap sizing API which was removed in Android 3.0 (Honeycomb).
181     */
182    @Deprecated
183    public long setMinimumHeapSize(long size) {
184        return 0;
185    }
186
187    /**
188     * This method exists for binary compatibility.  It used to
189     * perform a garbage collection that cleared SoftReferences.
190     */
191    @Deprecated
192    public void gcSoftReferences() {}
193
194    /**
195     * This method exists for binary compatibility.  It is equivalent
196     * to {@link System#runFinalization}.
197     */
198    @Deprecated
199    public void runFinalizationSync() {
200        System.runFinalization();
201    }
202
203    /**
204     * Implements setTargetHeapUtilization().
205     *
206     * @param newTarget the new suggested ideal heap utilization.
207     *                  This value may be adjusted internally.
208     */
209    private native void nativeSetTargetHeapUtilization(float newTarget);
210
211    /**
212     * This method exists for binary compatibility.  It was part of
213     * the external allocation API which was removed in Android 3.0 (Honeycomb).
214     */
215    @Deprecated
216    public boolean trackExternalAllocation(long size) {
217        return true;
218    }
219
220    /**
221     * This method exists for binary compatibility.  It was part of
222     * the external allocation API which was removed in Android 3.0 (Honeycomb).
223     */
224    @Deprecated
225    public void trackExternalFree(long size) {}
226
227    /**
228     * This method exists for binary compatibility.  It was part of
229     * the external allocation API which was removed in Android 3.0 (Honeycomb).
230     */
231    @Deprecated
232    public long getExternalBytesAllocated() {
233        return 0;
234    }
235
236    /**
237     * Tells the VM to enable the JIT compiler. If the VM does not have a JIT
238     * implementation, calling this method should have no effect.
239     */
240    public native void startJitCompilation();
241
242    /**
243     * Tells the VM to disable the JIT compiler. If the VM does not have a JIT
244     * implementation, calling this method should have no effect.
245     */
246    public native void disableJitCompilation();
247
248    /**
249     * Returns an array allocated in an area of the Java heap where it will never be moved.
250     * This is used to implement native allocations on the Java heap, such as DirectByteBuffers
251     * and Bitmaps.
252     */
253    public native Object newNonMovableArray(Class<?> componentType, int length);
254
255    /**
256     * Returns an array of at least minLength, but potentially larger. The increased size comes from
257     * avoiding any padding after the array. The amount of padding varies depending on the
258     * componentType and the memory allocator implementation.
259     */
260    public native Object newUnpaddedArray(Class<?> componentType, int minLength);
261
262    /**
263     * Returns the address of array[0]. This differs from using JNI in that JNI might lie and
264     * give you the address of a copy of the array when in forcecopy mode.
265     */
266    public native long addressOf(Object array);
267
268    /**
269     * Removes any growth limits, allowing the application to allocate
270     * up to the maximum heap size.
271     */
272    public native void clearGrowthLimit();
273
274    /**
275     * Returns true if either a Java debugger or native debugger is active.
276     */
277    public native boolean isDebuggerActive();
278
279    /**
280     * Registers a native allocation so that the heap knows about it and performs GC as required.
281     * If the number of native allocated bytes exceeds the native allocation watermark, the
282     * function requests a concurrent GC. If the native bytes allocated exceeds a second higher
283     * watermark, it is determined that the application is registering native allocations at an
284     * unusually high rate and a GC is performed inside of the function to prevent memory usage
285     * from excessively increasing.
286     */
287    public native void registerNativeAllocation(int bytes);
288
289    /**
290     * Registers a native free by reducing the number of native bytes accounted for.
291     */
292    public native void registerNativeFree(int bytes);
293
294    public native void trimHeap();
295    public native void concurrentGC();
296
297    /**
298     * Let the heap know of the new process state. This can change allocation and garbage collection
299     * behavior regarding trimming and compaction.
300     */
301    public native void updateProcessState(int state);
302
303    /**
304     * Fill in dex caches with classes, fields, and methods that are
305     * already loaded. Typically used after Zygote preloading.
306     */
307    public native void preloadDexCaches();
308
309    /**
310     * Register application info
311     */
312    public static native void registerAppInfo(String appDir, String processName, String pkgname);
313
314    /**
315     * Returns the runtime instruction set corresponding to a given ABI. Multiple
316     * compatible ABIs might map to the same instruction set. For example
317     * {@code armeabi-v7a} and {@code armeabi} might map to the instruction set {@code arm}.
318     *
319     * This influences the compilation of the applications classes.
320     */
321    public static String getInstructionSet(String abi) {
322        final String instructionSet = ABI_TO_INSTRUCTION_SET_MAP.get(abi);
323        if (instructionSet == null) {
324            throw new IllegalArgumentException("Unsupported ABI: " + abi);
325        }
326
327        return instructionSet;
328    }
329
330    public static boolean is64BitInstructionSet(String instructionSet) {
331        return "arm64".equals(instructionSet) ||
332                "x86_64".equals(instructionSet) ||
333                "mips64".equals(instructionSet);
334    }
335
336    public static boolean is64BitAbi(String abi) {
337        return is64BitInstructionSet(getInstructionSet(abi));
338    }
339
340    /**
341     * Return false if the boot class path for the given instruction
342     * set mapped from disk storage, versus being interpretted from
343     * dirty pages in memory.
344     */
345    public static native boolean isBootClassPathOnDisk(String instructionSet);
346
347    /**
348     * Returns the instruction set of the current runtime.
349     */
350    public static native String getCurrentInstructionSet();
351
352}
353