| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.lang; |
| |
| import android.system.ErrnoException; |
| import android.system.StructPasswd; |
| import android.system.StructUtsname; |
| import dalvik.system.VMRuntime; |
| import dalvik.system.VMStack; |
| import java.io.BufferedInputStream; |
| import java.io.Console; |
| import java.io.FileDescriptor; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.InputStream; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.nio.channels.Channel; |
| import java.nio.channels.spi.SelectorProvider; |
| import java.util.AbstractMap; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| import libcore.icu.ICU; |
| import libcore.io.Libcore; |
| |
| /** |
| * Provides access to system-related information and resources including |
| * standard input and output. Enables clients to dynamically load native |
| * libraries. All methods of this class are accessed in a static way and the |
| * class itself can not be instantiated. |
| * |
| * @see Runtime |
| */ |
| public final class System { |
| |
| /** |
| * Default input stream. |
| */ |
| public static final InputStream in; |
| |
| /** |
| * Default output stream. |
| */ |
| public static final PrintStream out; |
| |
| /** |
| * Default error output stream. |
| */ |
| public static final PrintStream err; |
| |
| private static final String lineSeparator; |
| private static final Properties unchangeableSystemProperties; |
| private static Properties systemProperties; |
| |
| /** |
| * Dedicated lock for GC / Finalization logic. |
| */ |
| private static final Object lock = new Object(); |
| |
| /** |
| * Whether or not we need to do a GC before running the finalizers. |
| */ |
| private static boolean runGC; |
| |
| /** |
| * If we just ran finalization, we might want to do a GC to free the finalized objects. |
| * This lets us do gc/runFinlization/gc sequences but prevents back to back System.gc(). |
| */ |
| private static boolean justRanFinalization; |
| |
| static { |
| err = new PrintStream(new FileOutputStream(FileDescriptor.err)); |
| out = new PrintStream(new FileOutputStream(FileDescriptor.out)); |
| in = new BufferedInputStream(new FileInputStream(FileDescriptor.in)); |
| unchangeableSystemProperties = initUnchangeableSystemProperties(); |
| systemProperties = createSystemProperties(); |
| lineSeparator = System.getProperty("line.separator"); |
| } |
| |
| /** |
| * Sets the standard input stream to the given user defined input stream. |
| * |
| * @param newIn |
| * the user defined input stream to set as the standard input |
| * stream. |
| */ |
| public static void setIn(InputStream newIn) { |
| setFieldImpl("in", "Ljava/io/InputStream;", newIn); |
| } |
| |
| /** |
| * Sets the standard output stream to the given user defined output stream. |
| * |
| * @param newOut |
| * the user defined output stream to set as the standard output |
| * stream. |
| */ |
| public static void setOut(PrintStream newOut) { |
| setFieldImpl("out", "Ljava/io/PrintStream;", newOut); |
| } |
| |
| /** |
| * Sets the standard error output stream to the given user defined output |
| * stream. |
| * |
| * @param newErr |
| * the user defined output stream to set as the standard error |
| * output stream. |
| */ |
| public static void setErr(PrintStream newErr) { |
| setFieldImpl("err", "Ljava/io/PrintStream;", newErr); |
| } |
| |
| /** |
| * Prevents this class from being instantiated. |
| */ |
| private System() { |
| } |
| |
| /** |
| * Copies {@code length} elements from the array {@code src}, |
| * starting at offset {@code srcPos}, into the array {@code dst}, |
| * starting at offset {@code dstPos}. |
| * |
| * <p>The source and destination arrays can be the same array, |
| * in which case copying is performed as if the source elements |
| * are first copied into a temporary array and then into the |
| * destination array. |
| * |
| * @param src |
| * the source array to copy the content. |
| * @param srcPos |
| * the starting index of the content in {@code src}. |
| * @param dst |
| * the destination array to copy the data into. |
| * @param dstPos |
| * the starting index for the copied content in {@code dst}. |
| * @param length |
| * the number of elements to be copied. |
| */ |
| public static native void arraycopy(Object src, int srcPos, Object dst, int dstPos, int length); |
| |
| /** |
| * The char array length threshold below which to use a Java |
| * (non-native) version of arraycopy() instead of the native |
| * version. See b/7103825. |
| */ |
| private static final int ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD = 64; |
| |
| /** |
| * The char[] specialized version of arraycopy(). |
| * |
| * @hide internal use only |
| */ |
| public static void arraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) { |
| if (src == null) { |
| throw new NullPointerException("src == null"); |
| } |
| if (dst == null) { |
| throw new NullPointerException("dst == null"); |
| } |
| if (srcPos < 0 || dstPos < 0 || length < 0 || |
| srcPos > src.length - length || dstPos > dst.length - length) { |
| throw new ArrayIndexOutOfBoundsException( |
| "src.length=" + src.length + " srcPos=" + srcPos + |
| " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); |
| } |
| if (length <= ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD) { |
| // Copy char by char for shorter arrays. |
| if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { |
| // Copy backward (to avoid overwriting elements before |
| // they are copied in case of an overlap on the same |
| // array.) |
| for (int i = length - 1; i >= 0; --i) { |
| dst[dstPos + i] = src[srcPos + i]; |
| } |
| } else { |
| // Copy forward. |
| for (int i = 0; i < length; ++i) { |
| dst[dstPos + i] = src[srcPos + i]; |
| } |
| } |
| } else { |
| // Call the native version for longer arrays. |
| arraycopyCharUnchecked(src, srcPos, dst, dstPos, length); |
| } |
| } |
| |
| /** |
| * The char[] specialized, unchecked, native version of |
| * arraycopy(). This assumes error checking has been done. |
| */ |
| private static native void arraycopyCharUnchecked(char[] src, int srcPos, |
| char[] dst, int dstPos, int length); |
| |
| /** |
| * Returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC. |
| * |
| * <p>This method always returns UTC times, regardless of the system's time zone. |
| * This is often called "Unix time" or "epoch time". |
| * Use a {@link java.text.DateFormat} instance to format this time for display to a human. |
| * |
| * <p>This method shouldn't be used for measuring timeouts or |
| * other elapsed time measurements, as changing the system time can affect |
| * the results. Use {@link #nanoTime} for that. |
| */ |
| public static native long currentTimeMillis(); |
| |
| /** |
| * Returns the current timestamp of the most precise timer available on the |
| * local system, in nanoseconds. Equivalent to Linux's {@code CLOCK_MONOTONIC}. |
| * |
| * <p>This timestamp should only be used to measure a duration by comparing it |
| * against another timestamp on the same device. |
| * Values returned by this method do not have a defined correspondence to |
| * wall clock times; the zero value is typically whenever the device last booted. |
| * Use {@link #currentTimeMillis} if you want to know what time it is. |
| */ |
| public static native long nanoTime(); |
| |
| /** |
| * Causes the VM to stop running and the program to exit with the given exit status. |
| * If {@link #runFinalizersOnExit(boolean)} has been previously invoked with a |
| * {@code true} argument, then all objects will be properly |
| * garbage-collected and finalized first. |
| */ |
| public static void exit(int code) { |
| Runtime.getRuntime().exit(code); |
| } |
| |
| /** |
| * Indicates to the VM that it would be a good time to run the |
| * garbage collector. Note that this is a hint only. There is no guarantee |
| * that the garbage collector will actually be run. |
| */ |
| public static void gc() { |
| boolean shouldRunGC; |
| synchronized(lock) { |
| shouldRunGC = justRanFinalization; |
| if (shouldRunGC) { |
| justRanFinalization = false; |
| } else { |
| runGC = true; |
| } |
| } |
| if (shouldRunGC) { |
| Runtime.getRuntime().gc(); |
| } |
| } |
| |
| /** |
| * Returns the value of the environment variable with the given name, or null if no such |
| * variable exists. |
| */ |
| public static String getenv(String name) { |
| if (name == null) { |
| throw new NullPointerException("name == null"); |
| } |
| return Libcore.os.getenv(name); |
| } |
| |
| /** |
| * Returns an unmodifiable map of all environment variables to their values. |
| */ |
| public static Map<String, String> getenv() { |
| Map<String, String> map = new HashMap<String, String>(); |
| for (String entry : Libcore.os.environ()) { |
| int index = entry.indexOf('='); |
| if (index != -1) { |
| map.put(entry.substring(0, index), entry.substring(index + 1)); |
| } |
| } |
| return new SystemEnvironment(map); |
| } |
| |
| /** |
| * Returns the inherited channel from the creator of the current virtual |
| * machine. |
| * |
| * @return the inherited {@link Channel} or {@code null} if none exists. |
| * @throws IOException |
| * if an I/O error occurred. |
| * @see SelectorProvider |
| * @see SelectorProvider#inheritedChannel() |
| */ |
| public static Channel inheritedChannel() throws IOException { |
| return SelectorProvider.provider().inheritedChannel(); |
| } |
| |
| /** |
| * Returns the system properties. Note that this is not a copy, so that |
| * changes made to the returned Properties object will be reflected in |
| * subsequent calls to getProperty and getProperties. |
| * |
| * @return the system properties. |
| */ |
| public static Properties getProperties() { |
| return systemProperties; |
| } |
| |
| private static Properties initUnchangeableSystemProperties() { |
| VMRuntime runtime = VMRuntime.getRuntime(); |
| Properties p = new Properties(); |
| |
| String projectUrl = "http://www.android.com/"; |
| String projectName = "The Android Project"; |
| |
| p.put("java.boot.class.path", runtime.bootClassPath()); |
| p.put("java.class.path", runtime.classPath()); |
| |
| // None of these four are meaningful on Android, but these keys are guaranteed |
| // to be present for System.getProperty. For java.class.version, we use the maximum |
| // class file version that dx currently supports. |
| p.put("java.class.version", "50.0"); |
| p.put("java.compiler", ""); |
| p.put("java.ext.dirs", ""); |
| p.put("java.version", "0"); |
| |
| // TODO: does this make any sense? Should we just leave java.home unset? |
| String javaHome = getenv("JAVA_HOME"); |
| if (javaHome == null) { |
| javaHome = "/system"; |
| } |
| p.put("java.home", javaHome); |
| |
| p.put("java.specification.name", "Dalvik Core Library"); |
| p.put("java.specification.vendor", projectName); |
| p.put("java.specification.version", "0.9"); |
| |
| p.put("java.vendor", projectName); |
| p.put("java.vendor.url", projectUrl); |
| p.put("java.vm.name", "Dalvik"); |
| p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification"); |
| p.put("java.vm.specification.vendor", projectName); |
| p.put("java.vm.specification.version", "0.9"); |
| p.put("java.vm.vendor", projectName); |
| p.put("java.vm.version", runtime.vmVersion()); |
| |
| p.put("file.separator", "/"); |
| p.put("line.separator", "\n"); |
| p.put("path.separator", ":"); |
| |
| p.put("java.runtime.name", "Android Runtime"); |
| p.put("java.runtime.version", "0.9"); |
| p.put("java.vm.vendor.url", projectUrl); |
| |
| p.put("file.encoding", "UTF-8"); |
| p.put("user.language", "en"); |
| p.put("user.region", "US"); |
| |
| try { |
| StructPasswd passwd = Libcore.os.getpwuid(Libcore.os.getuid()); |
| p.put("user.home", passwd.pw_dir); |
| p.put("user.name", passwd.pw_name); |
| } catch (ErrnoException exception) { |
| throw new AssertionError(exception); |
| } |
| |
| StructUtsname info = Libcore.os.uname(); |
| p.put("os.arch", info.machine); |
| p.put("os.name", info.sysname); |
| p.put("os.version", info.release); |
| |
| // Undocumented Android-only properties. |
| p.put("android.icu.library.version", ICU.getIcuVersion()); |
| p.put("android.icu.unicode.version", ICU.getUnicodeVersion()); |
| p.put("android.icu.cldr.version", ICU.getCldrVersion()); |
| |
| parsePropertyAssignments(p, specialProperties()); |
| |
| // Override built-in properties with settings from the command line. |
| parsePropertyAssignments(p, runtime.properties()); |
| return p; |
| } |
| |
| private static Properties createSystemProperties() { |
| Properties p = new PropertiesWithNonOverrideableDefaults(unchangeableSystemProperties); |
| // On Android, each app gets its own temporary directory. |
| // (See android.app.ActivityThread.) This is just a fallback default, |
| // useful only on the host. |
| p.put("java.io.tmpdir", "/tmp"); |
| return p; |
| } |
| |
| /** |
| * Returns an array of "key=value" strings containing information not otherwise |
| * easily available, such as #defined library versions. |
| */ |
| private static native String[] specialProperties(); |
| |
| /** |
| * Adds each element of 'assignments' to 'p', treating each element as an |
| * assignment in the form "key=value". |
| */ |
| private static void parsePropertyAssignments(Properties p, String[] assignments) { |
| for (String assignment : assignments) { |
| int split = assignment.indexOf('='); |
| String key = assignment.substring(0, split); |
| String value = assignment.substring(split + 1); |
| p.put(key, value); |
| } |
| } |
| |
| /** |
| * Returns the value of a particular system property or {@code null} if no |
| * such property exists. |
| * |
| * <p>The following properties are always provided by the Dalvik VM <b>and |
| * cannot be modified</b>: |
| * <p><table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> |
| * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> |
| * <td><b>Name</b></td> <td><b>Meaning</b></td> <td><b>Example</b></td></tr> |
| * <tr><td>file.separator</td> <td>{@link java.io.File#separator}</td> <td>{@code /}</td></tr> |
| * |
| * <tr><td>java.class.path</td> <td>System class path</td> <td>{@code .}</td></tr> |
| * <tr><td>java.class.version</td> <td>(Not useful on Android)</td> <td>{@code 50.0}</td></tr> |
| * <tr><td>java.compiler</td> <td>(Not useful on Android)</td> <td>Empty</td></tr> |
| * <tr><td>java.ext.dirs</td> <td>(Not useful on Android)</td> <td>Empty</td></tr> |
| * <tr><td>java.home</td> <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr> |
| * <tr><td>java.io.tmpdir</td> <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr> |
| * <tr><td>java.library.path</td> <td>Search path for JNI libraries</td> <td>{@code /vendor/lib:/system/lib}</td></tr> |
| * <tr><td>java.vendor</td> <td>Human-readable VM vendor</td> <td>{@code The Android Project}</td></tr> |
| * <tr><td>java.vendor.url</td> <td>URL for VM vendor's web site</td> <td>{@code http://www.android.com/}</td></tr> |
| * <tr><td>java.version</td> <td>(Not useful on Android)</td> <td>{@code 0}</td></tr> |
| * |
| * <tr><td>java.specification.version</td> <td>VM libraries version</td> <td>{@code 0.9}</td></tr> |
| * <tr><td>java.specification.vendor</td> <td>VM libraries vendor</td> <td>{@code The Android Project}</td></tr> |
| * <tr><td>java.specification.name</td> <td>VM libraries name</td> <td>{@code Dalvik Core Library}</td></tr> |
| * <tr><td>java.vm.version</td> <td>VM implementation version</td> <td>{@code 1.2.0}</td></tr> |
| * <tr><td>java.vm.vendor</td> <td>VM implementation vendor</td> <td>{@code The Android Project}</td></tr> |
| * <tr><td>java.vm.name</td> <td>VM implementation name</td> <td>{@code Dalvik}</td></tr> |
| * <tr><td>java.vm.specification.version</td> <td>VM specification version</td> <td>{@code 0.9}</td></tr> |
| * <tr><td>java.vm.specification.vendor</td> <td>VM specification vendor</td> <td>{@code The Android Project}</td></tr> |
| * <tr><td>java.vm.specification.name</td> <td>VM specification name</td> <td>{@code Dalvik Virtual Machine Specification}</td></tr> |
| * |
| * <tr><td>line.separator</td> <td>The system line separator</td> <td>{@code \n}</td></tr> |
| * |
| * <tr><td>os.arch</td> <td>OS architecture</td> <td>{@code armv7l}</td></tr> |
| * <tr><td>os.name</td> <td>OS (kernel) name</td> <td>{@code Linux}</td></tr> |
| * <tr><td>os.version</td> <td>OS (kernel) version</td> <td>{@code 2.6.32.9-g103d848}</td></tr> |
| * |
| * <tr><td>path.separator</td> <td>See {@link java.io.File#pathSeparator}</td> <td>{@code :}</td></tr> |
| * |
| * <tr><td>user.dir</td> <td>Base of non-absolute paths</td> <td>{@code /}</td></tr> |
| * <tr><td>user.home</td> <td>(Not useful on Android)</td> <td>Empty</td></tr> |
| * <tr><td>user.name</td> <td>(Not useful on Android)</td> <td>Empty</td></tr> |
| * |
| * </table> |
| * |
| * <p>It is an error to override anyone of these properties. Any attempt to |
| * do so will leave their values unchanged. |
| * |
| * @param propertyName |
| * the name of the system property to look up. |
| * @return the value of the specified system property or {@code null} if the |
| * property doesn't exist. |
| */ |
| public static String getProperty(String propertyName) { |
| return getProperty(propertyName, null); |
| } |
| |
| /** |
| * Returns the value of a particular system property. The {@code |
| * defaultValue} will be returned if no such property has been found. |
| */ |
| public static String getProperty(String name, String defaultValue) { |
| checkPropertyName(name); |
| return systemProperties.getProperty(name, defaultValue); |
| } |
| |
| /** |
| * Sets the value of a particular system property. Most system properties |
| * are read only and cannot be cleared or modified. See {@link #setProperty} for a |
| * list of such properties. |
| * |
| * @return the old value of the property or {@code null} if the property |
| * didn't exist. |
| */ |
| public static String setProperty(String name, String value) { |
| checkPropertyName(name); |
| return (String) systemProperties.setProperty(name, value); |
| } |
| |
| /** |
| * Removes a specific system property. Most system properties |
| * are read only and cannot be cleared or modified. See {@link #setProperty} for a |
| * list of such properties. |
| * |
| * @return the property value or {@code null} if the property didn't exist. |
| * @throws NullPointerException |
| * if the argument is {@code null}. |
| * @throws IllegalArgumentException |
| * if the argument is empty. |
| */ |
| public static String clearProperty(String name) { |
| checkPropertyName(name); |
| return (String) systemProperties.remove(name); |
| } |
| |
| private static void checkPropertyName(String name) { |
| if (name == null) { |
| throw new NullPointerException("name == null"); |
| } |
| if (name.isEmpty()) { |
| throw new IllegalArgumentException("name is empty"); |
| } |
| } |
| |
| /** |
| * Returns the {@link java.io.Console} associated with this VM, or null. |
| * Not all VMs will have an associated console. A console is typically only |
| * available for programs run from the command line. |
| * @since 1.6 |
| */ |
| public static Console console() { |
| return Console.getConsole(); |
| } |
| |
| /** |
| * Returns null. Android does not use {@code SecurityManager}. This method |
| * is only provided for source compatibility. |
| * |
| * @return null |
| */ |
| public static SecurityManager getSecurityManager() { |
| return null; |
| } |
| |
| /** |
| * Returns an integer hash code for the parameter. The hash code returned is |
| * the same one that would be returned by the method {@code |
| * java.lang.Object.hashCode()}, whether or not the object's class has |
| * overridden hashCode(). The hash code for {@code null} is {@code 0}. |
| * |
| * @param anObject |
| * the object to calculate the hash code. |
| * @return the hash code for the given object. |
| * @see java.lang.Object#hashCode |
| */ |
| public static native int identityHashCode(Object anObject); |
| |
| /** |
| * Returns the system's line separator. On Android, this is {@code "\n"}. The value |
| * comes from the value of the {@code line.separator} system property when the VM |
| * starts. Later changes to the property will not affect the value returned by this |
| * method. |
| * @since 1.7 |
| */ |
| public static String lineSeparator() { |
| return lineSeparator; |
| } |
| |
| /** |
| * See {@link Runtime#load}. |
| */ |
| public static void load(String pathName) { |
| Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader()); |
| } |
| |
| /** |
| * See {@link Runtime#loadLibrary}. |
| */ |
| public static void loadLibrary(String libName) { |
| Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader()); |
| } |
| |
| /** |
| * @hide internal use only |
| */ |
| public static void logE(String message) { |
| log('E', message, null); |
| } |
| |
| /** |
| * @hide internal use only |
| */ |
| public static void logE(String message, Throwable th) { |
| log('E', message, th); |
| } |
| |
| /** |
| * @hide internal use only |
| */ |
| public static void logI(String message) { |
| log('I', message, null); |
| } |
| |
| /** |
| * @hide internal use only |
| */ |
| public static void logI(String message, Throwable th) { |
| log('I', message, th); |
| } |
| |
| /** |
| * @hide internal use only |
| */ |
| public static void logW(String message) { |
| log('W', message, null); |
| } |
| |
| /** |
| * @hide internal use only |
| */ |
| public static void logW(String message, Throwable th) { |
| log('W', message, th); |
| } |
| |
| private static native void log(char type, String message, Throwable th); |
| |
| /** |
| * Provides a hint to the VM that it would be useful to attempt |
| * to perform any outstanding object finalization. |
| */ |
| public static void runFinalization() { |
| boolean shouldRunGC; |
| synchronized(lock) { |
| shouldRunGC = runGC; |
| runGC = false; |
| } |
| if (shouldRunGC) { |
| Runtime.getRuntime().gc(); |
| } |
| Runtime.getRuntime().runFinalization(); |
| synchronized(lock) { |
| justRanFinalization = true; |
| } |
| } |
| |
| /** |
| * Ensures that, when the VM is about to exit, all objects are |
| * finalized. Note that all finalization which occurs when the system is |
| * exiting is performed after all running threads have been terminated. |
| * |
| * @param flag |
| * the flag determines if finalization on exit is enabled. |
| * @deprecated This method is unsafe. |
| */ |
| @SuppressWarnings("deprecation") |
| @Deprecated |
| public static void runFinalizersOnExit(boolean flag) { |
| Runtime.runFinalizersOnExit(flag); |
| } |
| |
| /** |
| * Attempts to set all system properties. Copies all properties from |
| * {@code p} and discards system properties that are read only and cannot |
| * be modified. See {@link #setProperty} for a list of such properties. |
| */ |
| public static void setProperties(Properties p) { |
| PropertiesWithNonOverrideableDefaults userProperties = |
| new PropertiesWithNonOverrideableDefaults(unchangeableSystemProperties); |
| if (p != null) { |
| userProperties.putAll(p); |
| } |
| |
| systemProperties = userProperties; |
| } |
| |
| /** |
| * Throws {@code SecurityException}. |
| * |
| * <p>Security managers do <i>not</i> provide a secure environment for |
| * executing untrusted code and are unsupported on Android. Untrusted code |
| * cannot be safely isolated within a single VM on Android, so this method |
| * <i>always</i> throws a {@code SecurityException}. |
| * |
| * @param sm a security manager |
| * @throws SecurityException always |
| */ |
| public static void setSecurityManager(SecurityManager sm) { |
| if (sm != null) { |
| throw new SecurityException(); |
| } |
| } |
| |
| /** |
| * Returns the platform specific file name format for the shared library |
| * named by the argument. On Android, this would turn {@code "MyLibrary"} into |
| * {@code "libMyLibrary.so"}. |
| */ |
| public static native String mapLibraryName(String nickname); |
| |
| /** |
| * Used to set System.err, System.in, and System.out. |
| */ |
| private static native void setFieldImpl(String field, String signature, Object stream); |
| |
| /** |
| * A properties class that prohibits changes to any of the properties |
| * contained in its defaults. |
| */ |
| static final class PropertiesWithNonOverrideableDefaults extends Properties { |
| PropertiesWithNonOverrideableDefaults(Properties defaults) { |
| super(defaults); |
| } |
| |
| @Override |
| public Object put(Object key, Object value) { |
| if (defaults.containsKey(key)) { |
| logE("Ignoring attempt to set property \"" + key + |
| "\" to value \"" + value + "\"."); |
| return defaults.get(key); |
| } |
| |
| return super.put(key, value); |
| } |
| |
| @Override |
| public Object remove(Object key) { |
| if (defaults.containsKey(key)) { |
| logE("Ignoring attempt to remove property \"" + key + "\"."); |
| return null; |
| } |
| |
| return super.remove(key); |
| } |
| } |
| |
| /** |
| * The unmodifiable environment variables map. System.getenv() specifies |
| * that this map must throw when passed non-String keys. |
| */ |
| static class SystemEnvironment extends AbstractMap<String, String> { |
| private final Map<String, String> map; |
| |
| public SystemEnvironment(Map<String, String> map) { |
| this.map = Collections.unmodifiableMap(map); |
| } |
| |
| @Override public Set<Entry<String, String>> entrySet() { |
| return map.entrySet(); |
| } |
| |
| @Override public String get(Object key) { |
| return map.get(toNonNullString(key)); |
| } |
| |
| @Override public boolean containsKey(Object key) { |
| return map.containsKey(toNonNullString(key)); |
| } |
| |
| @Override public boolean containsValue(Object value) { |
| return map.containsValue(toNonNullString(value)); |
| } |
| |
| private String toNonNullString(Object o) { |
| if (o == null) { |
| throw new NullPointerException("o == null"); |
| } |
| return (String) o; |
| } |
| } |
| } |