|  | /* | 
|  | * Copyright (C) 2014 The Android Open Source Project | 
|  | * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. | 
|  | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|  | * | 
|  | * This code is free software; you can redistribute it and/or modify it | 
|  | * under the terms of the GNU General Public License version 2 only, as | 
|  | * published by the Free Software Foundation.  Oracle designates this | 
|  | * particular file as subject to the "Classpath" exception as provided | 
|  | * by Oracle in the LICENSE file that accompanied this code. | 
|  | * | 
|  | * This code is distributed in the hope that it will be useful, but WITHOUT | 
|  | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|  | * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|  | * version 2 for more details (a copy is included in the LICENSE file that | 
|  | * accompanied this code). | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License version | 
|  | * 2 along with this work; if not, write to the Free Software Foundation, | 
|  | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|  | * | 
|  | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|  | * or visit www.oracle.com if you need additional information or have any | 
|  | * questions. | 
|  | */ | 
|  |  | 
|  | package java.lang; | 
|  |  | 
|  | import dalvik.annotation.optimization.FastNative; | 
|  | import java.lang.ref.Reference; | 
|  | import java.lang.ref.ReferenceQueue; | 
|  | import java.lang.ref.WeakReference; | 
|  | import java.security.AccessController; | 
|  | import java.security.AccessControlContext; | 
|  | import java.security.PrivilegedAction; | 
|  | import java.util.Map; | 
|  | import java.util.HashMap; | 
|  | import java.util.concurrent.ConcurrentHashMap; | 
|  | import java.util.concurrent.ConcurrentMap; | 
|  | import java.util.concurrent.locks.LockSupport; | 
|  | import sun.nio.ch.Interruptible; | 
|  | import sun.reflect.CallerSensitive; | 
|  | import dalvik.system.VMStack; | 
|  | import libcore.util.EmptyArray; | 
|  |  | 
|  |  | 
|  | /** | 
|  | * A <i>thread</i> is a thread of execution in a program. The Java | 
|  | * Virtual Machine allows an application to have multiple threads of | 
|  | * execution running concurrently. | 
|  | * <p> | 
|  | * Every thread has a priority. Threads with higher priority are | 
|  | * executed in preference to threads with lower priority. Each thread | 
|  | * may or may not also be marked as a daemon. When code running in | 
|  | * some thread creates a new <code>Thread</code> object, the new | 
|  | * thread has its priority initially set equal to the priority of the | 
|  | * creating thread, and is a daemon thread if and only if the | 
|  | * creating thread is a daemon. | 
|  | * <p> | 
|  | * When a Java Virtual Machine starts up, there is usually a single | 
|  | * non-daemon thread (which typically calls the method named | 
|  | * <code>main</code> of some designated class). The Java Virtual | 
|  | * Machine continues to execute threads until either of the following | 
|  | * occurs: | 
|  | * <ul> | 
|  | * <li>The <code>exit</code> method of class <code>Runtime</code> has been | 
|  | *     called and the security manager has permitted the exit operation | 
|  | *     to take place. | 
|  | * <li>All threads that are not daemon threads have died, either by | 
|  | *     returning from the call to the <code>run</code> method or by | 
|  | *     throwing an exception that propagates beyond the <code>run</code> | 
|  | *     method. | 
|  | * </ul> | 
|  | * <p> | 
|  | * There are two ways to create a new thread of execution. One is to | 
|  | * declare a class to be a subclass of <code>Thread</code>. This | 
|  | * subclass should override the <code>run</code> method of class | 
|  | * <code>Thread</code>. An instance of the subclass can then be | 
|  | * allocated and started. For example, a thread that computes primes | 
|  | * larger than a stated value could be written as follows: | 
|  | * <hr><blockquote><pre> | 
|  | *     class PrimeThread extends Thread { | 
|  | *         long minPrime; | 
|  | *         PrimeThread(long minPrime) { | 
|  | *             this.minPrime = minPrime; | 
|  | *         } | 
|  | * | 
|  | *         public void run() { | 
|  | *             // compute primes larger than minPrime | 
|  | *              . . . | 
|  | *         } | 
|  | *     } | 
|  | * </pre></blockquote><hr> | 
|  | * <p> | 
|  | * The following code would then create a thread and start it running: | 
|  | * <blockquote><pre> | 
|  | *     PrimeThread p = new PrimeThread(143); | 
|  | *     p.start(); | 
|  | * </pre></blockquote> | 
|  | * <p> | 
|  | * The other way to create a thread is to declare a class that | 
|  | * implements the <code>Runnable</code> interface. That class then | 
|  | * implements the <code>run</code> method. An instance of the class can | 
|  | * then be allocated, passed as an argument when creating | 
|  | * <code>Thread</code>, and started. The same example in this other | 
|  | * style looks like the following: | 
|  | * <hr><blockquote><pre> | 
|  | *     class PrimeRun implements Runnable { | 
|  | *         long minPrime; | 
|  | *         PrimeRun(long minPrime) { | 
|  | *             this.minPrime = minPrime; | 
|  | *         } | 
|  | * | 
|  | *         public void run() { | 
|  | *             // compute primes larger than minPrime | 
|  | *              . . . | 
|  | *         } | 
|  | *     } | 
|  | * </pre></blockquote><hr> | 
|  | * <p> | 
|  | * The following code would then create a thread and start it running: | 
|  | * <blockquote><pre> | 
|  | *     PrimeRun p = new PrimeRun(143); | 
|  | *     new Thread(p).start(); | 
|  | * </pre></blockquote> | 
|  | * <p> | 
|  | * Every thread has a name for identification purposes. More than | 
|  | * one thread may have the same name. If a name is not specified when | 
|  | * a thread is created, a new name is generated for it. | 
|  | * <p> | 
|  | * Unless otherwise noted, passing a {@code null} argument to a constructor | 
|  | * or method in this class will cause a {@link NullPointerException} to be | 
|  | * thrown. | 
|  | * | 
|  | * @author  unascribed | 
|  | * @see     Runnable | 
|  | * @see     Runtime#exit(int) | 
|  | * @see     #run() | 
|  | * @see     #stop() | 
|  | * @since   JDK1.0 | 
|  | */ | 
|  | public | 
|  | class Thread implements Runnable { | 
|  | // Android-removed: registerNatives() not used on Android. | 
|  | /* | 
|  | /* Make sure registerNatives is the first thing <clinit> does. * | 
|  | private static native void registerNatives(); | 
|  | static { | 
|  | registerNatives(); | 
|  | } | 
|  | */ | 
|  |  | 
|  | // BEGIN Android-added: Android specific fields lock, nativePeer. | 
|  | /** | 
|  | * The synchronization object responsible for this thread's join/sleep/park operations. | 
|  | */ | 
|  | private final Object lock = new Object(); | 
|  |  | 
|  | /** | 
|  | * Reference to the native thread object. | 
|  | * | 
|  | * <p>Is 0 if the native thread has not yet been created/started, or has been destroyed. | 
|  | */ | 
|  | private volatile long nativePeer; | 
|  | // END Android-added: Android specific fields lock, nativePeer. | 
|  |  | 
|  | private volatile String name; | 
|  | private int            priority; | 
|  | private Thread         threadQ; | 
|  | private long           eetop; | 
|  |  | 
|  | /* Whether or not to single_step this thread. */ | 
|  | private boolean     single_step; | 
|  |  | 
|  | /* Whether or not the thread is a daemon thread. */ | 
|  | private boolean     daemon = false; | 
|  |  | 
|  | /* JVM state */ | 
|  | private boolean     stillborn = false; | 
|  |  | 
|  | /* What will be run. */ | 
|  | private Runnable target; | 
|  |  | 
|  | /* The group of this thread */ | 
|  | private ThreadGroup group; | 
|  |  | 
|  | /* The context ClassLoader for this thread */ | 
|  | private ClassLoader contextClassLoader; | 
|  |  | 
|  | /* The inherited AccessControlContext of this thread */ | 
|  | private AccessControlContext inheritedAccessControlContext; | 
|  |  | 
|  | /* For autonumbering anonymous threads. */ | 
|  | private static int threadInitNumber; | 
|  | private static synchronized int nextThreadNum() { | 
|  | return threadInitNumber++; | 
|  | } | 
|  |  | 
|  | /* ThreadLocal values pertaining to this thread. This map is maintained | 
|  | * by the ThreadLocal class. */ | 
|  | ThreadLocal.ThreadLocalMap threadLocals = null; | 
|  |  | 
|  | /* | 
|  | * InheritableThreadLocal values pertaining to this thread. This map is | 
|  | * maintained by the InheritableThreadLocal class. | 
|  | */ | 
|  | ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; | 
|  |  | 
|  | /* | 
|  | * The requested stack size for this thread, or 0 if the creator did | 
|  | * not specify a stack size.  It is up to the VM to do whatever it | 
|  | * likes with this number; some VMs will ignore it. | 
|  | */ | 
|  | private long stackSize; | 
|  |  | 
|  | // BEGIN Android-changed: Keep track of whether this thread was unparked while not alive. | 
|  | /* | 
|  | /* | 
|  | * JVM-private state that persists after native thread termination. | 
|  | * | 
|  | private long nativeParkEventPointer; | 
|  | */ | 
|  | /** | 
|  | * Indicates whether this thread was unpark()ed while not alive, in which case start()ing | 
|  | * it should leave it in unparked state. This field is read and written by native code in | 
|  | * the runtime, guarded by thread_list_lock. See http://b/28845097#comment49 | 
|  | */ | 
|  | private boolean unparkedBeforeStart; | 
|  | // END Android-changed: Keep track of whether this thread was unparked while not alive. | 
|  |  | 
|  | /* | 
|  | * Thread ID | 
|  | */ | 
|  | private long tid; | 
|  |  | 
|  | /* For generating thread ID */ | 
|  | private static long threadSeqNumber; | 
|  |  | 
|  |  | 
|  | // Android-added: The concept of "system-daemon" threads. See java.lang.Daemons. | 
|  | /** True if this thread is managed by {@link Daemons}. */ | 
|  | private boolean systemDaemon = false; | 
|  |  | 
|  | /* Java thread status for tools, | 
|  | * initialized to indicate thread 'not yet started' | 
|  | */ | 
|  |  | 
|  | // BEGIN Android-changed: Replace unused threadStatus field with started field. | 
|  | // Upstream this is modified by the native code and read in the start() and getState() methods | 
|  | // but in Android it is unused. The threadStatus is essentially an internal representation of | 
|  | // the Thread.State enum. Android uses two sources for that information, the native thread | 
|  | // state and the started field. The reason two sources are needed is because the native thread | 
|  | // is created when the thread is started and destroyed when the thread is stopped. That means | 
|  | // that the native thread state does not exist before the Thread has started (in State.NEW) or | 
|  | // after it has been stopped (in State.TERMINATED). In that case (i.e. when the nativePeer = 0) | 
|  | // the started field differentiates between the two states, i.e. if started = false then the | 
|  | // thread is in State.NEW and if started = true then the thread is in State.TERMINATED. | 
|  | // private volatile int threadStatus = 0; | 
|  | /** | 
|  | * True if the the Thread has been started, even it has since been stopped. | 
|  | */ | 
|  | boolean started = false; | 
|  | // END Android-changed: Replace unused threadStatus field with started field. | 
|  |  | 
|  |  | 
|  | private static synchronized long nextThreadID() { | 
|  | return ++threadSeqNumber; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * The argument supplied to the current call to | 
|  | * java.util.concurrent.locks.LockSupport.park. | 
|  | * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker | 
|  | * Accessed using java.util.concurrent.locks.LockSupport.getBlocker | 
|  | */ | 
|  | volatile Object parkBlocker; | 
|  |  | 
|  | /* The object in which this thread is blocked in an interruptible I/O | 
|  | * operation, if any.  The blocker's interrupt method should be invoked | 
|  | * after setting this thread's interrupt status. | 
|  | */ | 
|  | private volatile Interruptible blocker; | 
|  | private final Object blockerLock = new Object(); | 
|  |  | 
|  | // Android-changed: Make blockedOn() @hide public, for internal use. | 
|  | // Changed comment to reflect usage on Android | 
|  | /* Set the blocker field; used by java.nio.channels.spi.AbstractInterruptibleChannel | 
|  | */ | 
|  | /** @hide */ | 
|  | public void blockedOn(Interruptible b) { | 
|  | synchronized (blockerLock) { | 
|  | blocker = b; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * The minimum priority that a thread can have. | 
|  | */ | 
|  | public final static int MIN_PRIORITY = 1; | 
|  |  | 
|  | /** | 
|  | * The default priority that is assigned to a thread. | 
|  | */ | 
|  | public final static int NORM_PRIORITY = 5; | 
|  |  | 
|  | /** | 
|  | * The maximum priority that a thread can have. | 
|  | */ | 
|  | public final static int MAX_PRIORITY = 10; | 
|  |  | 
|  | /** | 
|  | * Returns a reference to the currently executing thread object. | 
|  | * | 
|  | * @return  the currently executing thread. | 
|  | */ | 
|  | @FastNative | 
|  | public static native Thread currentThread(); | 
|  |  | 
|  | /** | 
|  | * A hint to the scheduler that the current thread is willing to yield | 
|  | * its current use of a processor. The scheduler is free to ignore this | 
|  | * hint. | 
|  | * | 
|  | * <p> Yield is a heuristic attempt to improve relative progression | 
|  | * between threads that would otherwise over-utilise a CPU. Its use | 
|  | * should be combined with detailed profiling and benchmarking to | 
|  | * ensure that it actually has the desired effect. | 
|  | * | 
|  | * <p> It is rarely appropriate to use this method. It may be useful | 
|  | * for debugging or testing purposes, where it may help to reproduce | 
|  | * bugs due to race conditions. It may also be useful when designing | 
|  | * concurrency control constructs such as the ones in the | 
|  | * {@link java.util.concurrent.locks} package. | 
|  | */ | 
|  | public static native void yield(); | 
|  |  | 
|  | /** | 
|  | * Causes the currently executing thread to sleep (temporarily cease | 
|  | * execution) for the specified number of milliseconds, subject to | 
|  | * the precision and accuracy of system timers and schedulers. The thread | 
|  | * does not lose ownership of any monitors. | 
|  | * | 
|  | * @param  millis | 
|  | *         the length of time to sleep in milliseconds | 
|  | * | 
|  | * @throws  IllegalArgumentException | 
|  | *          if the value of {@code millis} is negative | 
|  | * | 
|  | * @throws  InterruptedException | 
|  | *          if any thread has interrupted the current thread. The | 
|  | *          <i>interrupted status</i> of the current thread is | 
|  | *          cleared when this exception is thrown. | 
|  | */ | 
|  | // BEGIN Android-changed: Implement sleep() methods using a shared native implementation. | 
|  | public static void sleep(long millis) throws InterruptedException { | 
|  | sleep(millis, 0); | 
|  | } | 
|  |  | 
|  | @FastNative | 
|  | private static native void sleep(Object lock, long millis, int nanos) | 
|  | throws InterruptedException; | 
|  | // END Android-changed: Implement sleep() methods using a shared native implementation. | 
|  |  | 
|  | /** | 
|  | * Causes the currently executing thread to sleep (temporarily cease | 
|  | * execution) for the specified number of milliseconds plus the specified | 
|  | * number of nanoseconds, subject to the precision and accuracy of system | 
|  | * timers and schedulers. The thread does not lose ownership of any | 
|  | * monitors. | 
|  | * | 
|  | * @param  millis | 
|  | *         the length of time to sleep in milliseconds | 
|  | * | 
|  | * @param  nanos | 
|  | *         {@code 0-999999} additional nanoseconds to sleep | 
|  | * | 
|  | * @throws  IllegalArgumentException | 
|  | *          if the value of {@code millis} is negative, or the value of | 
|  | *          {@code nanos} is not in the range {@code 0-999999} | 
|  | * | 
|  | * @throws  InterruptedException | 
|  | *          if any thread has interrupted the current thread. The | 
|  | *          <i>interrupted status</i> of the current thread is | 
|  | *          cleared when this exception is thrown. | 
|  | */ | 
|  | public static void sleep(long millis, int nanos) | 
|  | throws InterruptedException { | 
|  | // BEGIN Android-changed: Improve exception messages. | 
|  | /* | 
|  | if (millis < 0) { | 
|  | throw new IllegalArgumentException("timeout value is negative"); | 
|  | } | 
|  |  | 
|  | if (nanos < 0 || nanos > 999999) { | 
|  | throw new IllegalArgumentException( | 
|  | "nanosecond timeout value out of range"); | 
|  | } | 
|  | */ | 
|  | if (millis < 0) { | 
|  | throw new IllegalArgumentException("millis < 0: " + millis); | 
|  | } | 
|  | if (nanos < 0) { | 
|  | throw new IllegalArgumentException("nanos < 0: " + nanos); | 
|  | } | 
|  | if (nanos > 999999) { | 
|  | throw new IllegalArgumentException("nanos > 999999: " + nanos); | 
|  | } | 
|  | // END Android-changed: Improve exception messages. | 
|  |  | 
|  | // BEGIN Android-changed: Implement sleep() methods using a shared native implementation. | 
|  | // Attempt nanosecond rather than millisecond accuracy for sleep(); | 
|  | // RI code rounds to the nearest millisecond. | 
|  | /* | 
|  | if (nanos >= 500000 || (nanos != 0 && millis == 0)) { | 
|  | millis++; | 
|  | } | 
|  |  | 
|  | sleep(millis); | 
|  | */ | 
|  | // The JLS 3rd edition, section 17.9 says: "...sleep for zero | 
|  | // time...need not have observable effects." | 
|  | if (millis == 0 && nanos == 0) { | 
|  | // ...but we still have to handle being interrupted. | 
|  | if (Thread.interrupted()) { | 
|  | throw new InterruptedException(); | 
|  | } | 
|  | return; | 
|  | } | 
|  |  | 
|  | final int nanosPerMilli = 1000000; | 
|  | final long durationNanos; | 
|  | if (millis >= Long.MAX_VALUE / nanosPerMilli - 1L) { | 
|  | // > 292 years. Avoid overflow by capping it at roughly 292 years. | 
|  | durationNanos = Long.MAX_VALUE; | 
|  | } else { | 
|  | durationNanos = (millis * nanosPerMilli) + nanos; | 
|  | } | 
|  | long startNanos = System.nanoTime(); | 
|  |  | 
|  | Object lock = currentThread().lock; | 
|  |  | 
|  | // The native sleep(...) method actually does a monitor wait, which may return | 
|  | // early, so loop until sleep duration passes. The monitor is only notified when | 
|  | // we exit, which can't happen while we're sleeping. | 
|  | synchronized (lock) { | 
|  | for (long elapsed = 0L; elapsed < durationNanos; | 
|  | elapsed = System.nanoTime() - startNanos) { | 
|  | final long remaining = durationNanos - elapsed; | 
|  | millis = remaining / nanosPerMilli; | 
|  | nanos = (int) (remaining % nanosPerMilli); | 
|  | sleep(lock, millis, nanos); | 
|  | } | 
|  | } | 
|  | // END Android-changed: Implement sleep() methods using a shared native implementation. | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Initializes a Thread with the current AccessControlContext. | 
|  | * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext) | 
|  | */ | 
|  | private void init(ThreadGroup g, Runnable target, String name, | 
|  | long stackSize) { | 
|  | init(g, target, name, stackSize, null); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Initializes a Thread. | 
|  | * | 
|  | * @param g the Thread group | 
|  | * @param target the object whose run() method gets called | 
|  | * @param name the name of the new Thread | 
|  | * @param stackSize the desired stack size for the new thread, or | 
|  | *        zero to indicate that this parameter is to be ignored. | 
|  | * @param acc the AccessControlContext to inherit, or | 
|  | *            AccessController.getContext() if null | 
|  | */ | 
|  | private void init(ThreadGroup g, Runnable target, String name, | 
|  | long stackSize, AccessControlContext acc) { | 
|  | if (name == null) { | 
|  | throw new NullPointerException("name cannot be null"); | 
|  | } | 
|  |  | 
|  | this.name = name; | 
|  |  | 
|  | Thread parent = currentThread(); | 
|  | // Android-removed: SecurityManager stubbed out on Android. | 
|  | // SecurityManager security = System.getSecurityManager(); | 
|  | if (g == null) { | 
|  | // Android-changed: SecurityManager stubbed out on Android. | 
|  | /* | 
|  | /* Determine if it's an applet or not * | 
|  |  | 
|  | /* If there is a security manager, ask the security manager | 
|  | what to do. * | 
|  | if (security != null) { | 
|  | g = security.getThreadGroup(); | 
|  | } | 
|  |  | 
|  | /* If the security doesn't have a strong opinion of the matter | 
|  | use the parent thread group. * | 
|  | if (g == null) { | 
|  | */ | 
|  | g = parent.getThreadGroup(); | 
|  | // } | 
|  | } | 
|  |  | 
|  | // Android-removed: SecurityManager stubbed out on Android. | 
|  | /* | 
|  | /* checkAccess regardless of whether or not threadgroup is | 
|  | explicitly passed in. * | 
|  | g.checkAccess(); | 
|  |  | 
|  | /* | 
|  | * Do we have the required permissions? | 
|  | * | 
|  | if (security != null) { | 
|  | if (isCCLOverridden(getClass())) { | 
|  | security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); | 
|  | } | 
|  | } | 
|  | */ | 
|  |  | 
|  | g.addUnstarted(); | 
|  |  | 
|  | this.group = g; | 
|  | this.daemon = parent.isDaemon(); | 
|  | this.priority = parent.getPriority(); | 
|  | // Android-changed: Moved into init2(Thread) helper method. | 
|  | /* | 
|  | if (security == null || isCCLOverridden(parent.getClass())) | 
|  | this.contextClassLoader = parent.getContextClassLoader(); | 
|  | else | 
|  | this.contextClassLoader = parent.contextClassLoader; | 
|  | this.inheritedAccessControlContext = | 
|  | acc != null ? acc : AccessController.getContext(); | 
|  | */ | 
|  | this.target = target; | 
|  | // Android-removed: The priority parameter is unchecked on Android. | 
|  | // It is unclear why this is not being done (b/80180276). | 
|  | // setPriority(priority); | 
|  | // Android-changed: Moved into init2(Thread) helper method. | 
|  | // if (parent.inheritableThreadLocals != null) | 
|  | //     this.inheritableThreadLocals = | 
|  | //         ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); | 
|  | init2(parent); | 
|  |  | 
|  | /* Stash the specified stack size in case the VM cares */ | 
|  | this.stackSize = stackSize; | 
|  |  | 
|  | /* Set thread ID */ | 
|  | tid = nextThreadID(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Throws CloneNotSupportedException as a Thread can not be meaningfully | 
|  | * cloned. Construct a new Thread instead. | 
|  | * | 
|  | * @throws  CloneNotSupportedException | 
|  | *          always | 
|  | */ | 
|  | @Override | 
|  | protected Object clone() throws CloneNotSupportedException { | 
|  | throw new CloneNotSupportedException(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object. This constructor has the same | 
|  | * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} | 
|  | * {@code (null, null, gname)}, where {@code gname} is a newly generated | 
|  | * name. Automatically generated names are of the form | 
|  | * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. | 
|  | */ | 
|  | public Thread() { | 
|  | init(null, null, "Thread-" + nextThreadNum(), 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object. This constructor has the same | 
|  | * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} | 
|  | * {@code (null, target, gname)}, where {@code gname} is a newly generated | 
|  | * name. Automatically generated names are of the form | 
|  | * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. | 
|  | * | 
|  | * @param  target | 
|  | *         the object whose {@code run} method is invoked when this thread | 
|  | *         is started. If {@code null}, this classes {@code run} method does | 
|  | *         nothing. | 
|  | */ | 
|  | public Thread(Runnable target) { | 
|  | init(null, target, "Thread-" + nextThreadNum(), 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Creates a new Thread that inherits the given AccessControlContext. | 
|  | * This is not a public constructor. | 
|  | */ | 
|  | Thread(Runnable target, AccessControlContext acc) { | 
|  | init(null, target, "Thread-" + nextThreadNum(), 0, acc); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object. This constructor has the same | 
|  | * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} | 
|  | * {@code (group, target, gname)} ,where {@code gname} is a newly generated | 
|  | * name. Automatically generated names are of the form | 
|  | * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. | 
|  | * | 
|  | * @param  group | 
|  | *         the thread group. If {@code null} and there is a security | 
|  | *         manager, the group is determined by {@linkplain | 
|  | *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. | 
|  | *         If there is not a security manager or {@code | 
|  | *         SecurityManager.getThreadGroup()} returns {@code null}, the group | 
|  | *         is set to the current thread's thread group. | 
|  | * | 
|  | * @param  target | 
|  | *         the object whose {@code run} method is invoked when this thread | 
|  | *         is started. If {@code null}, this thread's run method is invoked. | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if the current thread cannot create a thread in the specified | 
|  | *          thread group | 
|  | */ | 
|  | public Thread(ThreadGroup group, Runnable target) { | 
|  | init(group, target, "Thread-" + nextThreadNum(), 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object. This constructor has the same | 
|  | * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} | 
|  | * {@code (null, null, name)}. | 
|  | * | 
|  | * @param   name | 
|  | *          the name of the new thread | 
|  | */ | 
|  | public Thread(String name) { | 
|  | init(null, null, name, 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object. This constructor has the same | 
|  | * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} | 
|  | * {@code (group, null, name)}. | 
|  | * | 
|  | * @param  group | 
|  | *         the thread group. If {@code null} and there is a security | 
|  | *         manager, the group is determined by {@linkplain | 
|  | *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. | 
|  | *         If there is not a security manager or {@code | 
|  | *         SecurityManager.getThreadGroup()} returns {@code null}, the group | 
|  | *         is set to the current thread's thread group. | 
|  | * | 
|  | * @param  name | 
|  | *         the name of the new thread | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if the current thread cannot create a thread in the specified | 
|  | *          thread group | 
|  | */ | 
|  | public Thread(ThreadGroup group, String name) { | 
|  | init(group, null, name, 0); | 
|  | } | 
|  |  | 
|  | // BEGIN Android-added: Private constructor - used by the runtime. | 
|  | /** @hide */ | 
|  | Thread(ThreadGroup group, String name, int priority, boolean daemon) { | 
|  | this.group = group; | 
|  | this.group.addUnstarted(); | 
|  | // Must be tolerant of threads without a name. | 
|  | if (name == null) { | 
|  | name = "Thread-" + nextThreadNum(); | 
|  | } | 
|  |  | 
|  | // NOTE: Resist the temptation to call setName() here. This constructor is only called | 
|  | // by the runtime to construct peers for threads that have attached via JNI and it's | 
|  | // undesirable to clobber their natively set name. | 
|  | this.name = name; | 
|  |  | 
|  | this.priority = priority; | 
|  | this.daemon = daemon; | 
|  | init2(currentThread()); | 
|  | tid = nextThreadID(); | 
|  | } | 
|  |  | 
|  | // Android-added: Helper method for previous constructor and init(...) method. | 
|  | private void init2(Thread parent) { | 
|  | this.contextClassLoader = parent.getContextClassLoader(); | 
|  | this.inheritedAccessControlContext = AccessController.getContext(); | 
|  | if (parent.inheritableThreadLocals != null) { | 
|  | this.inheritableThreadLocals = ThreadLocal.createInheritedMap( | 
|  | parent.inheritableThreadLocals); | 
|  | } | 
|  | } | 
|  | // END Android-added: Private constructor - used by the runtime. | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object. This constructor has the same | 
|  | * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} | 
|  | * {@code (null, target, name)}. | 
|  | * | 
|  | * @param  target | 
|  | *         the object whose {@code run} method is invoked when this thread | 
|  | *         is started. If {@code null}, this thread's run method is invoked. | 
|  | * | 
|  | * @param  name | 
|  | *         the name of the new thread | 
|  | */ | 
|  | public Thread(Runnable target, String name) { | 
|  | init(null, target, name, 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object so that it has {@code target} | 
|  | * as its run object, has the specified {@code name} as its name, | 
|  | * and belongs to the thread group referred to by {@code group}. | 
|  | * | 
|  | * <p>If there is a security manager, its | 
|  | * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess} | 
|  | * method is invoked with the ThreadGroup as its argument. | 
|  | * | 
|  | * <p>In addition, its {@code checkPermission} method is invoked with | 
|  | * the {@code RuntimePermission("enableContextClassLoaderOverride")} | 
|  | * permission when invoked directly or indirectly by the constructor | 
|  | * of a subclass which overrides the {@code getContextClassLoader} | 
|  | * or {@code setContextClassLoader} methods. | 
|  | * | 
|  | * <p>The priority of the newly created thread is set equal to the | 
|  | * priority of the thread creating it, that is, the currently running | 
|  | * thread. The method {@linkplain #setPriority setPriority} may be | 
|  | * used to change the priority to a new value. | 
|  | * | 
|  | * <p>The newly created thread is initially marked as being a daemon | 
|  | * thread if and only if the thread creating it is currently marked | 
|  | * as a daemon thread. The method {@linkplain #setDaemon setDaemon} | 
|  | * may be used to change whether or not a thread is a daemon. | 
|  | * | 
|  | * @param  group | 
|  | *         the thread group. If {@code null} and there is a security | 
|  | *         manager, the group is determined by {@linkplain | 
|  | *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. | 
|  | *         If there is not a security manager or {@code | 
|  | *         SecurityManager.getThreadGroup()} returns {@code null}, the group | 
|  | *         is set to the current thread's thread group. | 
|  | * | 
|  | * @param  target | 
|  | *         the object whose {@code run} method is invoked when this thread | 
|  | *         is started. If {@code null}, this thread's run method is invoked. | 
|  | * | 
|  | * @param  name | 
|  | *         the name of the new thread | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if the current thread cannot create a thread in the specified | 
|  | *          thread group or cannot override the context class loader methods. | 
|  | */ | 
|  | public Thread(ThreadGroup group, Runnable target, String name) { | 
|  | init(group, target, name, 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Allocates a new {@code Thread} object so that it has {@code target} | 
|  | * as its run object, has the specified {@code name} as its name, | 
|  | * and belongs to the thread group referred to by {@code group}, and has | 
|  | * the specified <i>stack size</i>. | 
|  | * | 
|  | * <p>This constructor is identical to {@link | 
|  | * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact | 
|  | * that it allows the thread stack size to be specified.  The stack size | 
|  | * is the approximate number of bytes of address space that the virtual | 
|  | * machine is to allocate for this thread's stack.  <b>The effect of the | 
|  | * {@code stackSize} parameter, if any, is highly platform dependent.</b> | 
|  | * | 
|  | * <p>On some platforms, specifying a higher value for the | 
|  | * {@code stackSize} parameter may allow a thread to achieve greater | 
|  | * recursion depth before throwing a {@link StackOverflowError}. | 
|  | * Similarly, specifying a lower value may allow a greater number of | 
|  | * threads to exist concurrently without throwing an {@link | 
|  | * OutOfMemoryError} (or other internal error).  The details of | 
|  | * the relationship between the value of the <tt>stackSize</tt> parameter | 
|  | * and the maximum recursion depth and concurrency level are | 
|  | * platform-dependent.  <b>On some platforms, the value of the | 
|  | * {@code stackSize} parameter may have no effect whatsoever.</b> | 
|  | * | 
|  | * <p>The virtual machine is free to treat the {@code stackSize} | 
|  | * parameter as a suggestion.  If the specified value is unreasonably low | 
|  | * for the platform, the virtual machine may instead use some | 
|  | * platform-specific minimum value; if the specified value is unreasonably | 
|  | * high, the virtual machine may instead use some platform-specific | 
|  | * maximum.  Likewise, the virtual machine is free to round the specified | 
|  | * value up or down as it sees fit (or to ignore it completely). | 
|  | * | 
|  | * <p>Specifying a value of zero for the {@code stackSize} parameter will | 
|  | * cause this constructor to behave exactly like the | 
|  | * {@code Thread(ThreadGroup, Runnable, String)} constructor. | 
|  | * | 
|  | * <p><i>Due to the platform-dependent nature of the behavior of this | 
|  | * constructor, extreme care should be exercised in its use. | 
|  | * The thread stack size necessary to perform a given computation will | 
|  | * likely vary from one JRE implementation to another.  In light of this | 
|  | * variation, careful tuning of the stack size parameter may be required, | 
|  | * and the tuning may need to be repeated for each JRE implementation on | 
|  | * which an application is to run.</i> | 
|  | * | 
|  | * <p>Implementation note: Java platform implementers are encouraged to | 
|  | * document their implementation's behavior with respect to the | 
|  | * {@code stackSize} parameter. | 
|  | * | 
|  | * | 
|  | * @param  group | 
|  | *         the thread group. If {@code null} and there is a security | 
|  | *         manager, the group is determined by {@linkplain | 
|  | *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. | 
|  | *         If there is not a security manager or {@code | 
|  | *         SecurityManager.getThreadGroup()} returns {@code null}, the group | 
|  | *         is set to the current thread's thread group. | 
|  | * | 
|  | * @param  target | 
|  | *         the object whose {@code run} method is invoked when this thread | 
|  | *         is started. If {@code null}, this thread's run method is invoked. | 
|  | * | 
|  | * @param  name | 
|  | *         the name of the new thread | 
|  | * | 
|  | * @param  stackSize | 
|  | *         the desired stack size for the new thread, or zero to indicate | 
|  | *         that this parameter is to be ignored. | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if the current thread cannot create a thread in the specified | 
|  | *          thread group | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public Thread(ThreadGroup group, Runnable target, String name, | 
|  | long stackSize) { | 
|  | init(group, target, name, stackSize); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Causes this thread to begin execution; the Java Virtual Machine | 
|  | * calls the <code>run</code> method of this thread. | 
|  | * <p> | 
|  | * The result is that two threads are running concurrently: the | 
|  | * current thread (which returns from the call to the | 
|  | * <code>start</code> method) and the other thread (which executes its | 
|  | * <code>run</code> method). | 
|  | * <p> | 
|  | * It is never legal to start a thread more than once. | 
|  | * In particular, a thread may not be restarted once it has completed | 
|  | * execution. | 
|  | * | 
|  | * @exception  IllegalThreadStateException  if the thread was already | 
|  | *               started. | 
|  | * @see        #run() | 
|  | * @see        #stop() | 
|  | */ | 
|  | public synchronized void start() { | 
|  | /** | 
|  | * This method is not invoked for the main method thread or "system" | 
|  | * group threads created/set up by the VM. Any new functionality added | 
|  | * to this method in the future may have to also be added to the VM. | 
|  | * | 
|  | * A zero status value corresponds to state "NEW". | 
|  | */ | 
|  | // Android-changed: Replace unused threadStatus field with started field. | 
|  | // The threadStatus field is unused on Android. | 
|  | if (started) | 
|  | throw new IllegalThreadStateException(); | 
|  |  | 
|  | /* Notify the group that this thread is about to be started | 
|  | * so that it can be added to the group's list of threads | 
|  | * and the group's unstarted count can be decremented. */ | 
|  | group.add(this); | 
|  |  | 
|  | // Android-changed: Use field instead of local variable. | 
|  | // It is necessary to remember the state of this across calls to this method so that it | 
|  | // can throw an IllegalThreadStateException if this method is called on an already | 
|  | // started thread. | 
|  | started = false; | 
|  | try { | 
|  | // Android-changed: Use Android specific nativeCreate() method to create/start thread. | 
|  | // start0(); | 
|  | nativeCreate(this, stackSize, daemon); | 
|  | started = true; | 
|  | } finally { | 
|  | try { | 
|  | if (!started) { | 
|  | group.threadStartFailed(this); | 
|  | } | 
|  | } catch (Throwable ignore) { | 
|  | /* do nothing. If start0 threw a Throwable then | 
|  | it will be passed up the call stack */ | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Android-changed: Use Android specific nativeCreate() method to create/start thread. | 
|  | // The upstream native method start0() only takes a reference to this object and so must obtain | 
|  | // the stack size and daemon status directly from the field whereas Android supplies the values | 
|  | // explicitly on the method call. | 
|  | // private native void start0(); | 
|  | private native static void nativeCreate(Thread t, long stackSize, boolean daemon); | 
|  |  | 
|  | /** | 
|  | * If this thread was constructed using a separate | 
|  | * <code>Runnable</code> run object, then that | 
|  | * <code>Runnable</code> object's <code>run</code> method is called; | 
|  | * otherwise, this method does nothing and returns. | 
|  | * <p> | 
|  | * Subclasses of <code>Thread</code> should override this method. | 
|  | * | 
|  | * @see     #start() | 
|  | * @see     #stop() | 
|  | * @see     #Thread(ThreadGroup, Runnable, String) | 
|  | */ | 
|  | @Override | 
|  | public void run() { | 
|  | if (target != null) { | 
|  | target.run(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * This method is called by the system to give a Thread | 
|  | * a chance to clean up before it actually exits. | 
|  | */ | 
|  | private void exit() { | 
|  | if (group != null) { | 
|  | group.threadTerminated(this); | 
|  | group = null; | 
|  | } | 
|  | /* Aggressively null out all reference fields: see bug 4006245 */ | 
|  | target = null; | 
|  | /* Speed the release of some of these resources */ | 
|  | threadLocals = null; | 
|  | inheritableThreadLocals = null; | 
|  | inheritedAccessControlContext = null; | 
|  | blocker = null; | 
|  | uncaughtExceptionHandler = null; | 
|  | } | 
|  |  | 
|  | // Android-changed: Throws UnsupportedOperationException. | 
|  | /** | 
|  | * Throws {@code UnsupportedOperationException}. | 
|  | * | 
|  | * @deprecated This method was originally designed to force a thread to stop | 
|  | *       and throw a {@code ThreadDeath} as an exception. It was inherently unsafe. | 
|  | *       Stopping a thread with | 
|  | *       Thread.stop causes it to unlock all of the monitors that it | 
|  | *       has locked (as a natural consequence of the unchecked | 
|  | *       <code>ThreadDeath</code> exception propagating up the stack).  If | 
|  | *       any of the objects previously protected by these monitors were in | 
|  | *       an inconsistent state, the damaged objects become visible to | 
|  | *       other threads, potentially resulting in arbitrary behavior.  Many | 
|  | *       uses of <code>stop</code> should be replaced by code that simply | 
|  | *       modifies some variable to indicate that the target thread should | 
|  | *       stop running.  The target thread should check this variable | 
|  | *       regularly, and return from its run method in an orderly fashion | 
|  | *       if the variable indicates that it is to stop running.  If the | 
|  | *       target thread waits for long periods (on a condition variable, | 
|  | *       for example), the <code>interrupt</code> method should be used to | 
|  | *       interrupt the wait. | 
|  | *       For more information, see | 
|  | *       <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why | 
|  | *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. | 
|  | */ | 
|  | @Deprecated | 
|  | public final void stop() { | 
|  | /* | 
|  | SecurityManager security = System.getSecurityManager(); | 
|  | if (security != null) { | 
|  | checkAccess(); | 
|  | if (this != Thread.currentThread()) { | 
|  | security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); | 
|  | } | 
|  | } | 
|  | // A zero status value corresponds to "NEW", it can't change to | 
|  | // not-NEW because we hold the lock. | 
|  | if (threadStatus != 0) { | 
|  | resume(); // Wake up thread if it was suspended; no-op otherwise | 
|  | } | 
|  |  | 
|  | // The VM can handle all thread states | 
|  | stop0(new ThreadDeath()); | 
|  | */ | 
|  | throw new UnsupportedOperationException(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Throws {@code UnsupportedOperationException}. | 
|  | * | 
|  | * @param obj ignored | 
|  | * | 
|  | * @deprecated This method was originally designed to force a thread to stop | 
|  | *        and throw a given {@code Throwable} as an exception. It was | 
|  | *        inherently unsafe (see {@link #stop()} for details), and furthermore | 
|  | *        could be used to generate exceptions that the target thread was | 
|  | *        not prepared to handle. | 
|  | *        For more information, see | 
|  | *        <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why | 
|  | *        are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. | 
|  | */ | 
|  | @Deprecated | 
|  | public final synchronized void stop(Throwable obj) { | 
|  | throw new UnsupportedOperationException(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Interrupts this thread. | 
|  | * | 
|  | * <p> Unless the current thread is interrupting itself, which is | 
|  | * always permitted, the {@link #checkAccess() checkAccess} method | 
|  | * of this thread is invoked, which may cause a {@link | 
|  | * SecurityException} to be thrown. | 
|  | * | 
|  | * <p> If this thread is blocked in an invocation of the {@link | 
|  | * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link | 
|  | * Object#wait(long, int) wait(long, int)} methods of the {@link Object} | 
|  | * class, or of the {@link #join()}, {@link #join(long)}, {@link | 
|  | * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)}, | 
|  | * methods of this class, then its interrupt status will be cleared and it | 
|  | * will receive an {@link InterruptedException}. | 
|  | * | 
|  | * <p> If this thread is blocked in an I/O operation upon an {@link | 
|  | * java.nio.channels.InterruptibleChannel InterruptibleChannel} | 
|  | * then the channel will be closed, the thread's interrupt | 
|  | * status will be set, and the thread will receive a {@link | 
|  | * java.nio.channels.ClosedByInterruptException}. | 
|  | * | 
|  | * <p> If this thread is blocked in a {@link java.nio.channels.Selector} | 
|  | * then the thread's interrupt status will be set and it will return | 
|  | * immediately from the selection operation, possibly with a non-zero | 
|  | * value, just as if the selector's {@link | 
|  | * java.nio.channels.Selector#wakeup wakeup} method were invoked. | 
|  | * | 
|  | * <p> If none of the previous conditions hold then this thread's interrupt | 
|  | * status will be set. </p> | 
|  | * | 
|  | * <p> Interrupting a thread that is not alive need not have any effect. | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if the current thread cannot modify this thread | 
|  | * | 
|  | * @revised 6.0 | 
|  | * @spec JSR-51 | 
|  | */ | 
|  | public void interrupt() { | 
|  | if (this != Thread.currentThread()) | 
|  | checkAccess(); | 
|  |  | 
|  | synchronized (blockerLock) { | 
|  | Interruptible b = blocker; | 
|  | if (b != null) { | 
|  | interrupt0();           // Just to set the interrupt flag | 
|  | b.interrupt(this); | 
|  | return; | 
|  | } | 
|  | } | 
|  | interrupt0(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Tests whether the current thread has been interrupted.  The | 
|  | * <i>interrupted status</i> of the thread is cleared by this method.  In | 
|  | * other words, if this method were to be called twice in succession, the | 
|  | * second call would return false (unless the current thread were | 
|  | * interrupted again, after the first call had cleared its interrupted | 
|  | * status and before the second call had examined it). | 
|  | * | 
|  | * <p>A thread interruption ignored because a thread was not alive | 
|  | * at the time of the interrupt will be reflected by this method | 
|  | * returning false. | 
|  | * | 
|  | * @return  <code>true</code> if the current thread has been interrupted; | 
|  | *          <code>false</code> otherwise. | 
|  | * @see #isInterrupted() | 
|  | * @revised 6.0 | 
|  | */ | 
|  | // Android-changed: Use native interrupted()/isInterrupted() methods. | 
|  | // Upstream has one native method for both these methods that takes a boolean parameter that | 
|  | // determines whether the interrupted status of the thread should be cleared after reading | 
|  | // it. While that approach does allow code reuse it is less efficient/more complex than having | 
|  | // a native implementation of each method because: | 
|  | // * The pure Java interrupted() method requires two native calls, one to get the current | 
|  | //   thread and one to get its interrupted status. | 
|  | // * Updating the interrupted flag is more complex than simply reading it. Knowing that only | 
|  | //   the current thread can clear the interrupted status makes the code simpler as it does not | 
|  | //   need to be concerned about multiple threads trying to clear the status simultaneously. | 
|  | // public static boolean interrupted() { | 
|  | //     return currentThread().isInterrupted(true); | 
|  | // } | 
|  | @FastNative | 
|  | public static native boolean interrupted(); | 
|  |  | 
|  | /** | 
|  | * Tests whether this thread has been interrupted.  The <i>interrupted | 
|  | * status</i> of the thread is unaffected by this method. | 
|  | * | 
|  | * <p>A thread interruption ignored because a thread was not alive | 
|  | * at the time of the interrupt will be reflected by this method | 
|  | * returning false. | 
|  | * | 
|  | * @return  <code>true</code> if this thread has been interrupted; | 
|  | *          <code>false</code> otherwise. | 
|  | * @see     #interrupted() | 
|  | * @revised 6.0 | 
|  | */ | 
|  | // Android-changed: Use native interrupted()/isInterrupted() methods. | 
|  | // public boolean isInterrupted() { | 
|  | //     return isInterrupted(false); | 
|  | // } | 
|  | @FastNative | 
|  | public native boolean isInterrupted(); | 
|  |  | 
|  | // Android-removed: Use native interrupted()/isInterrupted() methods. | 
|  | /* | 
|  | /** | 
|  | * Tests if some Thread has been interrupted.  The interrupted state | 
|  | * is reset or not based on the value of ClearInterrupted that is | 
|  | * passed. | 
|  | * | 
|  | private native boolean isInterrupted(boolean ClearInterrupted); | 
|  | */ | 
|  |  | 
|  | // BEGIN Android-changed: Throw UnsupportedOperationException instead of NoSuchMethodError. | 
|  | /** | 
|  | * Throws {@link UnsupportedOperationException}. | 
|  | * | 
|  | * @deprecated This method was originally designed to destroy this | 
|  | *     thread without any cleanup. Any monitors it held would have | 
|  | *     remained locked. However, the method was never implemented. | 
|  | *     If if were to be implemented, it would be deadlock-prone in | 
|  | *     much the manner of {@link #suspend}. If the target thread held | 
|  | *     a lock protecting a critical system resource when it was | 
|  | *     destroyed, no thread could ever access this resource again. | 
|  | *     If another thread ever attempted to lock this resource, deadlock | 
|  | *     would result. Such deadlocks typically manifest themselves as | 
|  | *     "frozen" processes. For more information, see | 
|  | *     <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html"> | 
|  | *     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. | 
|  | * @throws UnsupportedOperationException always | 
|  | */ | 
|  | @Deprecated | 
|  | public void destroy() { | 
|  | throw new UnsupportedOperationException(); | 
|  | } | 
|  | // END Android-changed: Throw UnsupportedOperationException instead of NoSuchMethodError. | 
|  |  | 
|  | /** | 
|  | * Tests if this thread is alive. A thread is alive if it has | 
|  | * been started and has not yet died. | 
|  | * | 
|  | * @return  <code>true</code> if this thread is alive; | 
|  | *          <code>false</code> otherwise. | 
|  | */ | 
|  | // Android-changed: Provide pure Java implementation of isAlive(). | 
|  | public final boolean isAlive() { | 
|  | return nativePeer != 0; | 
|  | } | 
|  |  | 
|  | // Android-changed: Updated JavaDoc as it always throws an UnsupportedOperationException. | 
|  | /** | 
|  | * Throws {@link UnsupportedOperationException}. | 
|  | * | 
|  | * @deprecated   This method was designed to suspend the Thread but it was | 
|  | *   inherently deadlock-prone.  If the target thread holds a lock on the | 
|  | *   monitor protecting a critical system resource when it is suspended, no | 
|  | *   thread can access this resource until the target thread is resumed. If | 
|  | *   the thread that would resume the target thread attempts to lock this | 
|  | *   monitor prior to calling <code>resume</code>, deadlock results.  Such | 
|  | *   deadlocks typically manifest themselves as "frozen" processes. | 
|  | *   For more information, see | 
|  | *   <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why | 
|  | *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. | 
|  | * @throws UnsupportedOperationException always | 
|  | */ | 
|  | @Deprecated | 
|  | public final void suspend() { | 
|  | // Android-changed: Unsupported on Android. | 
|  | // checkAccess(); | 
|  | // suspend0(); | 
|  |  | 
|  | throw new UnsupportedOperationException(); | 
|  | } | 
|  |  | 
|  | // Android-changed: Updated JavaDoc as it always throws an UnsupportedOperationException. | 
|  | /** | 
|  | * Throws {@link UnsupportedOperationException}. | 
|  | * | 
|  | * @deprecated This method exists solely for use with {@link #suspend}, | 
|  | *     which has been deprecated because it is deadlock-prone. | 
|  | *     For more information, see | 
|  | *     <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why | 
|  | *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. | 
|  | * @throws UnsupportedOperationException always | 
|  | */ | 
|  | @Deprecated | 
|  | public final void resume() { | 
|  | // Android-changed: Unsupported on Android. | 
|  | // checkAccess(); | 
|  | // resume0(); | 
|  | throw new UnsupportedOperationException(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Changes the priority of this thread. | 
|  | * <p> | 
|  | * First the <code>checkAccess</code> method of this thread is called | 
|  | * with no arguments. This may result in throwing a | 
|  | * <code>SecurityException</code>. | 
|  | * <p> | 
|  | * Otherwise, the priority of this thread is set to the smaller of | 
|  | * the specified <code>newPriority</code> and the maximum permitted | 
|  | * priority of the thread's thread group. | 
|  | * | 
|  | * @param newPriority priority to set this thread to | 
|  | * @exception  IllegalArgumentException  If the priority is not in the | 
|  | *               range <code>MIN_PRIORITY</code> to | 
|  | *               <code>MAX_PRIORITY</code>. | 
|  | * @exception  SecurityException  if the current thread cannot modify | 
|  | *               this thread. | 
|  | * @see        #getPriority | 
|  | * @see        #checkAccess() | 
|  | * @see        #getThreadGroup() | 
|  | * @see        #MAX_PRIORITY | 
|  | * @see        #MIN_PRIORITY | 
|  | * @see        ThreadGroup#getMaxPriority() | 
|  | */ | 
|  | public final void setPriority(int newPriority) { | 
|  | ThreadGroup g; | 
|  | checkAccess(); | 
|  | if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { | 
|  | // Android-changed: Improve exception message when the new priority is out of bounds. | 
|  | throw new IllegalArgumentException("Priority out of range: " + newPriority); | 
|  | } | 
|  | if((g = getThreadGroup()) != null) { | 
|  | if (newPriority > g.getMaxPriority()) { | 
|  | newPriority = g.getMaxPriority(); | 
|  | } | 
|  | // Android-changed: Avoid native call if Thread is not yet started. | 
|  | // setPriority0(priority = newPriority); | 
|  | synchronized(this) { | 
|  | this.priority = newPriority; | 
|  | if (isAlive()) { | 
|  | setPriority0(newPriority); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns this thread's priority. | 
|  | * | 
|  | * @return  this thread's priority. | 
|  | * @see     #setPriority | 
|  | */ | 
|  | public final int getPriority() { | 
|  | return priority; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Changes the name of this thread to be equal to the argument | 
|  | * <code>name</code>. | 
|  | * <p> | 
|  | * First the <code>checkAccess</code> method of this thread is called | 
|  | * with no arguments. This may result in throwing a | 
|  | * <code>SecurityException</code>. | 
|  | * | 
|  | * @param      name   the new name for this thread. | 
|  | * @exception  SecurityException  if the current thread cannot modify this | 
|  | *               thread. | 
|  | * @see        #getName | 
|  | * @see        #checkAccess() | 
|  | */ | 
|  | public final synchronized void setName(String name) { | 
|  | checkAccess(); | 
|  | if (name == null) { | 
|  | throw new NullPointerException("name cannot be null"); | 
|  | } | 
|  |  | 
|  | this.name = name; | 
|  | // Android-changed: Use isAlive() not threadStatus to check whether Thread has started. | 
|  | // The threadStatus field is not used in Android. | 
|  | // if (threadStatus != 0) { | 
|  | if (isAlive()) { | 
|  | setNativeName(name); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns this thread's name. | 
|  | * | 
|  | * @return  this thread's name. | 
|  | * @see     #setName(String) | 
|  | */ | 
|  | public final String getName() { | 
|  | return name; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the thread group to which this thread belongs. | 
|  | * This method returns null if this thread has died | 
|  | * (been stopped). | 
|  | * | 
|  | * @return  this thread's thread group. | 
|  | */ | 
|  | public final ThreadGroup getThreadGroup() { | 
|  | // BEGIN Android-added: Work around exit() not being called. | 
|  | // Android runtime does not call exit() when a Thread exits so the group field is not | 
|  | // set to null so it needs to pretend as if it did. If we are not going to call exit() | 
|  | // then this should probably just check isAlive() here rather than getState() as the | 
|  | // latter requires a native call. | 
|  | if (getState() == Thread.State.TERMINATED) { | 
|  | return null; | 
|  | } | 
|  | // END Android-added: Work around exit() not being called. | 
|  | return group; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns an estimate of the number of active threads in the current | 
|  | * thread's {@linkplain java.lang.ThreadGroup thread group} and its | 
|  | * subgroups. Recursively iterates over all subgroups in the current | 
|  | * thread's thread group. | 
|  | * | 
|  | * <p> The value returned is only an estimate because the number of | 
|  | * threads may change dynamically while this method traverses internal | 
|  | * data structures, and might be affected by the presence of certain | 
|  | * system threads. This method is intended primarily for debugging | 
|  | * and monitoring purposes. | 
|  | * | 
|  | * @return  an estimate of the number of active threads in the current | 
|  | *          thread's thread group and in any other thread group that | 
|  | *          has the current thread's thread group as an ancestor | 
|  | */ | 
|  | public static int activeCount() { | 
|  | return currentThread().getThreadGroup().activeCount(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Copies into the specified array every active thread in the current | 
|  | * thread's thread group and its subgroups. This method simply | 
|  | * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])} | 
|  | * method of the current thread's thread group. | 
|  | * | 
|  | * <p> An application might use the {@linkplain #activeCount activeCount} | 
|  | * method to get an estimate of how big the array should be, however | 
|  | * <i>if the array is too short to hold all the threads, the extra threads | 
|  | * are silently ignored.</i>  If it is critical to obtain every active | 
|  | * thread in the current thread's thread group and its subgroups, the | 
|  | * invoker should verify that the returned int value is strictly less | 
|  | * than the length of {@code tarray}. | 
|  | * | 
|  | * <p> Due to the inherent race condition in this method, it is recommended | 
|  | * that the method only be used for debugging and monitoring purposes. | 
|  | * | 
|  | * @param  tarray | 
|  | *         an array into which to put the list of threads | 
|  | * | 
|  | * @return  the number of threads put into the array | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if {@link java.lang.ThreadGroup#checkAccess} determines that | 
|  | *          the current thread cannot access its thread group | 
|  | */ | 
|  | public static int enumerate(Thread tarray[]) { | 
|  | return currentThread().getThreadGroup().enumerate(tarray); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Counts the number of stack frames in this thread. The thread must | 
|  | * be suspended. | 
|  | * | 
|  | * @return     the number of stack frames in this thread. | 
|  | * @exception  IllegalThreadStateException  if this thread is not | 
|  | *             suspended. | 
|  | * @deprecated The definition of this call depends on {@link #suspend}, | 
|  | *             which is deprecated.  Further, the results of this call | 
|  | *             were never well-defined. | 
|  | */ | 
|  | @Deprecated | 
|  | // Android-changed: Provide non-native implementation of countStackFrames(). | 
|  | // public native int countStackFrames(); | 
|  | public int countStackFrames() { | 
|  | return getStackTrace().length; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Waits at most {@code millis} milliseconds for this thread to | 
|  | * die. A timeout of {@code 0} means to wait forever. | 
|  | * | 
|  | * <p> This implementation uses a loop of {@code this.wait} calls | 
|  | * conditioned on {@code this.isAlive}. As a thread terminates the | 
|  | * {@code this.notifyAll} method is invoked. It is recommended that | 
|  | * applications not use {@code wait}, {@code notify}, or | 
|  | * {@code notifyAll} on {@code Thread} instances. | 
|  | * | 
|  | * @param  millis | 
|  | *         the time to wait in milliseconds | 
|  | * | 
|  | * @throws  IllegalArgumentException | 
|  | *          if the value of {@code millis} is negative | 
|  | * | 
|  | * @throws  InterruptedException | 
|  | *          if any thread has interrupted the current thread. The | 
|  | *          <i>interrupted status</i> of the current thread is | 
|  | *          cleared when this exception is thrown. | 
|  | */ | 
|  | // BEGIN Android-changed: Synchronize on separate lock object not this Thread. | 
|  | // nativePeer and hence isAlive() can change asynchronously, but Thread::Destroy | 
|  | // will always acquire and notify lock after isAlive() changes to false. | 
|  | // public final synchronized void join(long millis) | 
|  | public final void join(long millis) | 
|  | throws InterruptedException { | 
|  | synchronized(lock) { | 
|  | long base = System.currentTimeMillis(); | 
|  | long now = 0; | 
|  |  | 
|  | if (millis < 0) { | 
|  | throw new IllegalArgumentException("timeout value is negative"); | 
|  | } | 
|  |  | 
|  | if (millis == 0) { | 
|  | while (isAlive()) { | 
|  | lock.wait(0); | 
|  | } | 
|  | } else { | 
|  | while (isAlive()) { | 
|  | long delay = millis - now; | 
|  | if (delay <= 0) { | 
|  | break; | 
|  | } | 
|  | lock.wait(delay); | 
|  | now = System.currentTimeMillis() - base; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | // END Android-changed: Synchronize on separate lock object not this Thread. | 
|  |  | 
|  | /** | 
|  | * Waits at most {@code millis} milliseconds plus | 
|  | * {@code nanos} nanoseconds for this thread to die. | 
|  | * | 
|  | * <p> This implementation uses a loop of {@code this.wait} calls | 
|  | * conditioned on {@code this.isAlive}. As a thread terminates the | 
|  | * {@code this.notifyAll} method is invoked. It is recommended that | 
|  | * applications not use {@code wait}, {@code notify}, or | 
|  | * {@code notifyAll} on {@code Thread} instances. | 
|  | * | 
|  | * @param  millis | 
|  | *         the time to wait in milliseconds | 
|  | * | 
|  | * @param  nanos | 
|  | *         {@code 0-999999} additional nanoseconds to wait | 
|  | * | 
|  | * @throws  IllegalArgumentException | 
|  | *          if the value of {@code millis} is negative, or the value | 
|  | *          of {@code nanos} is not in the range {@code 0-999999} | 
|  | * | 
|  | * @throws  InterruptedException | 
|  | *          if any thread has interrupted the current thread. The | 
|  | *          <i>interrupted status</i> of the current thread is | 
|  | *          cleared when this exception is thrown. | 
|  | */ | 
|  | // BEGIN Android-changed: Synchronize on separate lock object not this Thread. | 
|  | // public final synchronized void join(long millis, int nanos) | 
|  | public final void join(long millis, int nanos) | 
|  | throws InterruptedException { | 
|  |  | 
|  | synchronized(lock) { | 
|  | if (millis < 0) { | 
|  | throw new IllegalArgumentException("timeout value is negative"); | 
|  | } | 
|  |  | 
|  | if (nanos < 0 || nanos > 999999) { | 
|  | throw new IllegalArgumentException( | 
|  | "nanosecond timeout value out of range"); | 
|  | } | 
|  |  | 
|  | if (nanos >= 500000 || (nanos != 0 && millis == 0)) { | 
|  | millis++; | 
|  | } | 
|  |  | 
|  | join(millis); | 
|  | } | 
|  | } | 
|  | // END Android-changed: Synchronize on separate lock object not this Thread. | 
|  |  | 
|  | /** | 
|  | * Waits for this thread to die. | 
|  | * | 
|  | * <p> An invocation of this method behaves in exactly the same | 
|  | * way as the invocation | 
|  | * | 
|  | * <blockquote> | 
|  | * {@linkplain #join(long) join}{@code (0)} | 
|  | * </blockquote> | 
|  | * | 
|  | * @throws  InterruptedException | 
|  | *          if any thread has interrupted the current thread. The | 
|  | *          <i>interrupted status</i> of the current thread is | 
|  | *          cleared when this exception is thrown. | 
|  | */ | 
|  | public final void join() throws InterruptedException { | 
|  | join(0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Prints a stack trace of the current thread to the standard error stream. | 
|  | * This method is used only for debugging. | 
|  | * | 
|  | * @see     Throwable#printStackTrace() | 
|  | */ | 
|  | public static void dumpStack() { | 
|  | new Exception("Stack trace").printStackTrace(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Marks this thread as either a {@linkplain #isDaemon daemon} thread | 
|  | * or a user thread. The Java Virtual Machine exits when the only | 
|  | * threads running are all daemon threads. | 
|  | * | 
|  | * <p> This method must be invoked before the thread is started. | 
|  | * | 
|  | * @param  on | 
|  | *         if {@code true}, marks this thread as a daemon thread | 
|  | * | 
|  | * @throws  IllegalThreadStateException | 
|  | *          if this thread is {@linkplain #isAlive alive} | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if {@link #checkAccess} determines that the current | 
|  | *          thread cannot modify this thread | 
|  | */ | 
|  | public final void setDaemon(boolean on) { | 
|  | checkAccess(); | 
|  | if (isAlive()) { | 
|  | throw new IllegalThreadStateException(); | 
|  | } | 
|  | daemon = on; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Tests if this thread is a daemon thread. | 
|  | * | 
|  | * @return  <code>true</code> if this thread is a daemon thread; | 
|  | *          <code>false</code> otherwise. | 
|  | * @see     #setDaemon(boolean) | 
|  | */ | 
|  | public final boolean isDaemon() { | 
|  | return daemon; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Determines if the currently running thread has permission to | 
|  | * modify this thread. | 
|  | * <p> | 
|  | * If there is a security manager, its <code>checkAccess</code> method | 
|  | * is called with this thread as its argument. This may result in | 
|  | * throwing a <code>SecurityException</code>. | 
|  | * | 
|  | * @exception  SecurityException  if the current thread is not allowed to | 
|  | *               access this thread. | 
|  | * @see        SecurityManager#checkAccess(Thread) | 
|  | */ | 
|  | public final void checkAccess() { | 
|  | // Android-removed: SecurityManager stubbed out on Android. | 
|  | // SecurityManager security = System.getSecurityManager(); | 
|  | // if (security != null) { | 
|  | //     security.checkAccess(this); | 
|  | // } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a string representation of this thread, including the | 
|  | * thread's name, priority, and thread group. | 
|  | * | 
|  | * @return  a string representation of this thread. | 
|  | */ | 
|  | public String toString() { | 
|  | ThreadGroup group = getThreadGroup(); | 
|  | if (group != null) { | 
|  | return "Thread[" + getName() + "," + getPriority() + "," + | 
|  | group.getName() + "]"; | 
|  | } else { | 
|  | return "Thread[" + getName() + "," + getPriority() + "," + | 
|  | "" + "]"; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the context ClassLoader for this Thread. The context | 
|  | * ClassLoader is provided by the creator of the thread for use | 
|  | * by code running in this thread when loading classes and resources. | 
|  | * If not {@linkplain #setContextClassLoader set}, the default is the | 
|  | * ClassLoader context of the parent Thread. The context ClassLoader of the | 
|  | * primordial thread is typically set to the class loader used to load the | 
|  | * application. | 
|  | * | 
|  | * <p>If a security manager is present, and the invoker's class loader is not | 
|  | * {@code null} and is not the same as or an ancestor of the context class | 
|  | * loader, then this method invokes the security manager's {@link | 
|  | * SecurityManager#checkPermission(java.security.Permission) checkPermission} | 
|  | * method with a {@link RuntimePermission RuntimePermission}{@code | 
|  | * ("getClassLoader")} permission to verify that retrieval of the context | 
|  | * class loader is permitted. | 
|  | * | 
|  | * @return  the context ClassLoader for this Thread, or {@code null} | 
|  | *          indicating the system class loader (or, failing that, the | 
|  | *          bootstrap class loader) | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if the current thread cannot get the context ClassLoader | 
|  | * | 
|  | * @since 1.2 | 
|  | */ | 
|  | @CallerSensitive | 
|  | public ClassLoader getContextClassLoader() { | 
|  | // Android-removed: SecurityManager stubbed out on Android. | 
|  | /* | 
|  | if (contextClassLoader == null) | 
|  | return null; | 
|  | SecurityManager sm = System.getSecurityManager(); | 
|  | if (sm != null) { | 
|  | ClassLoader.checkClassLoaderPermission(contextClassLoader, | 
|  | Reflection.getCallerClass()); | 
|  | } | 
|  | */ | 
|  | return contextClassLoader; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the context ClassLoader for this Thread. The context | 
|  | * ClassLoader can be set when a thread is created, and allows | 
|  | * the creator of the thread to provide the appropriate class loader, | 
|  | * through {@code getContextClassLoader}, to code running in the thread | 
|  | * when loading classes and resources. | 
|  | * | 
|  | * <p>If a security manager is present, its {@link | 
|  | * SecurityManager#checkPermission(java.security.Permission) checkPermission} | 
|  | * method is invoked with a {@link RuntimePermission RuntimePermission}{@code | 
|  | * ("setContextClassLoader")} permission to see if setting the context | 
|  | * ClassLoader is permitted. | 
|  | * | 
|  | * @param  cl | 
|  | *         the context ClassLoader for this Thread, or null  indicating the | 
|  | *         system class loader (or, failing that, the bootstrap class loader) | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if the current thread cannot set the context ClassLoader | 
|  | * | 
|  | * @since 1.2 | 
|  | */ | 
|  | public void setContextClassLoader(ClassLoader cl) { | 
|  | // Android-removed: SecurityManager stubbed out on Android. | 
|  | // SecurityManager sm = System.getSecurityManager(); | 
|  | // if (sm != null) { | 
|  | //     sm.checkPermission(new RuntimePermission("setContextClassLoader")); | 
|  | // } | 
|  | contextClassLoader = cl; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns <tt>true</tt> if and only if the current thread holds the | 
|  | * monitor lock on the specified object. | 
|  | * | 
|  | * <p>This method is designed to allow a program to assert that | 
|  | * the current thread already holds a specified lock: | 
|  | * <pre> | 
|  | *     assert Thread.holdsLock(obj); | 
|  | * </pre> | 
|  | * | 
|  | * @param  obj the object on which to test lock ownership | 
|  | * @throws NullPointerException if obj is <tt>null</tt> | 
|  | * @return <tt>true</tt> if the current thread holds the monitor lock on | 
|  | *         the specified object. | 
|  | * @since 1.4 | 
|  | */ | 
|  | public static native boolean holdsLock(Object obj); | 
|  |  | 
|  | private static final StackTraceElement[] EMPTY_STACK_TRACE | 
|  | = new StackTraceElement[0]; | 
|  |  | 
|  | /** | 
|  | * Returns an array of stack trace elements representing the stack dump | 
|  | * of this thread.  This method will return a zero-length array if | 
|  | * this thread has not started, has started but has not yet been | 
|  | * scheduled to run by the system, or has terminated. | 
|  | * If the returned array is of non-zero length then the first element of | 
|  | * the array represents the top of the stack, which is the most recent | 
|  | * method invocation in the sequence.  The last element of the array | 
|  | * represents the bottom of the stack, which is the least recent method | 
|  | * invocation in the sequence. | 
|  | * | 
|  | * <p>If there is a security manager, and this thread is not | 
|  | * the current thread, then the security manager's | 
|  | * <tt>checkPermission</tt> method is called with a | 
|  | * <tt>RuntimePermission("getStackTrace")</tt> permission | 
|  | * to see if it's ok to get the stack trace. | 
|  | * | 
|  | * <p>Some virtual machines may, under some circumstances, omit one | 
|  | * or more stack frames from the stack trace.  In the extreme case, | 
|  | * a virtual machine that has no stack trace information concerning | 
|  | * this thread is permitted to return a zero-length array from this | 
|  | * method. | 
|  | * | 
|  | * @return an array of <tt>StackTraceElement</tt>, | 
|  | * each represents one stack frame. | 
|  | * | 
|  | * @throws SecurityException | 
|  | *        if a security manager exists and its | 
|  | *        <tt>checkPermission</tt> method doesn't allow | 
|  | *        getting the stack trace of thread. | 
|  | * @see SecurityManager#checkPermission | 
|  | * @see RuntimePermission | 
|  | * @see Throwable#getStackTrace | 
|  | * | 
|  | * @since 1.5 | 
|  | */ | 
|  | public StackTraceElement[] getStackTrace() { | 
|  | // Android-changed: Use native VMStack to get stack trace. | 
|  | StackTraceElement ste[] = VMStack.getThreadStackTrace(this); | 
|  | return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a map of stack traces for all live threads. | 
|  | * The map keys are threads and each map value is an array of | 
|  | * <tt>StackTraceElement</tt> that represents the stack dump | 
|  | * of the corresponding <tt>Thread</tt>. | 
|  | * The returned stack traces are in the format specified for | 
|  | * the {@link #getStackTrace getStackTrace} method. | 
|  | * | 
|  | * <p>The threads may be executing while this method is called. | 
|  | * The stack trace of each thread only represents a snapshot and | 
|  | * each stack trace may be obtained at different time.  A zero-length | 
|  | * array will be returned in the map value if the virtual machine has | 
|  | * no stack trace information about a thread. | 
|  | * | 
|  | * <p>If there is a security manager, then the security manager's | 
|  | * <tt>checkPermission</tt> method is called with a | 
|  | * <tt>RuntimePermission("getStackTrace")</tt> permission as well as | 
|  | * <tt>RuntimePermission("modifyThreadGroup")</tt> permission | 
|  | * to see if it is ok to get the stack trace of all threads. | 
|  | * | 
|  | * @return a <tt>Map</tt> from <tt>Thread</tt> to an array of | 
|  | * <tt>StackTraceElement</tt> that represents the stack trace of | 
|  | * the corresponding thread. | 
|  | * | 
|  | * @throws SecurityException | 
|  | *        if a security manager exists and its | 
|  | *        <tt>checkPermission</tt> method doesn't allow | 
|  | *        getting the stack trace of thread. | 
|  | * @see #getStackTrace | 
|  | * @see SecurityManager#checkPermission | 
|  | * @see RuntimePermission | 
|  | * @see Throwable#getStackTrace | 
|  | * | 
|  | * @since 1.5 | 
|  | */ | 
|  | public static Map<Thread, StackTraceElement[]> getAllStackTraces() { | 
|  | // Android-removed: SecurityManager stubbed out on Android. | 
|  | /* | 
|  | // check for getStackTrace permission | 
|  | SecurityManager security = System.getSecurityManager(); | 
|  | if (security != null) { | 
|  | security.checkPermission( | 
|  | SecurityConstants.GET_STACK_TRACE_PERMISSION); | 
|  | security.checkPermission( | 
|  | SecurityConstants.MODIFY_THREADGROUP_PERMISSION); | 
|  | } | 
|  | */ | 
|  |  | 
|  | // Get a snapshot of the list of all threads | 
|  | // BEGIN Android-changed: Use ThreadGroup and getStackTrace() instead of native methods. | 
|  | // Allocate a bit more space than needed, in case new ones are just being created. | 
|  | /* | 
|  | Thread[] threads = getThreads(); | 
|  | StackTraceElement[][] traces = dumpThreads(threads); | 
|  | Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length); | 
|  | for (int i = 0; i < threads.length; i++) { | 
|  | StackTraceElement[] stackTrace = traces[i]; | 
|  | if (stackTrace != null) { | 
|  | m.put(threads[i], stackTrace); | 
|  | } | 
|  | // else terminated so we don't put it in the map | 
|  | } | 
|  | */ | 
|  | int count = ThreadGroup.systemThreadGroup.activeCount(); | 
|  | Thread[] threads = new Thread[count + count / 2]; | 
|  |  | 
|  | // Enumerate the threads. | 
|  | count = ThreadGroup.systemThreadGroup.enumerate(threads); | 
|  |  | 
|  | // Collect the stacktraces | 
|  | Map<Thread, StackTraceElement[]> m = new HashMap<Thread, StackTraceElement[]>(); | 
|  | for (int i = 0; i < count; i++) { | 
|  | StackTraceElement[] stackTrace = threads[i].getStackTrace(); | 
|  | m.put(threads[i], stackTrace); | 
|  | } | 
|  | // END Android-changed: Use ThreadGroup and getStackTrace() instead of native methods. | 
|  | return m; | 
|  | } | 
|  |  | 
|  |  | 
|  | private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION = | 
|  | new RuntimePermission("enableContextClassLoaderOverride"); | 
|  |  | 
|  | /** cache of subclass security audit results */ | 
|  | /* Replace with ConcurrentReferenceHashMap when/if it appears in a future | 
|  | * release */ | 
|  | private static class Caches { | 
|  | /** cache of subclass security audit results */ | 
|  | static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = | 
|  | new ConcurrentHashMap<>(); | 
|  |  | 
|  | /** queue for WeakReferences to audited subclasses */ | 
|  | static final ReferenceQueue<Class<?>> subclassAuditsQueue = | 
|  | new ReferenceQueue<>(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Verifies that this (possibly subclass) instance can be constructed | 
|  | * without violating security constraints: the subclass must not override | 
|  | * security-sensitive non-final methods, or else the | 
|  | * "enableContextClassLoaderOverride" RuntimePermission is checked. | 
|  | */ | 
|  | private static boolean isCCLOverridden(Class<?> cl) { | 
|  | if (cl == Thread.class) | 
|  | return false; | 
|  |  | 
|  | processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); | 
|  | WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); | 
|  | Boolean result = Caches.subclassAudits.get(key); | 
|  | if (result == null) { | 
|  | result = Boolean.valueOf(auditSubclass(cl)); | 
|  | Caches.subclassAudits.putIfAbsent(key, result); | 
|  | } | 
|  |  | 
|  | return result.booleanValue(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Performs reflective checks on given subclass to verify that it doesn't | 
|  | * override security-sensitive non-final methods.  Returns true if the | 
|  | * subclass overrides any of the methods, false otherwise. | 
|  | */ | 
|  | private static boolean auditSubclass(final Class<?> subcl) { | 
|  | Boolean result = AccessController.doPrivileged( | 
|  | new PrivilegedAction<Boolean>() { | 
|  | public Boolean run() { | 
|  | for (Class<?> cl = subcl; | 
|  | cl != Thread.class; | 
|  | cl = cl.getSuperclass()) | 
|  | { | 
|  | try { | 
|  | cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]); | 
|  | return Boolean.TRUE; | 
|  | } catch (NoSuchMethodException ex) { | 
|  | } | 
|  | try { | 
|  | Class<?>[] params = {ClassLoader.class}; | 
|  | cl.getDeclaredMethod("setContextClassLoader", params); | 
|  | return Boolean.TRUE; | 
|  | } catch (NoSuchMethodException ex) { | 
|  | } | 
|  | } | 
|  | return Boolean.FALSE; | 
|  | } | 
|  | } | 
|  | ); | 
|  | return result.booleanValue(); | 
|  | } | 
|  |  | 
|  | // Android-removed: Native methods that are unused on Android. | 
|  | // private native static StackTraceElement[][] dumpThreads(Thread[] threads); | 
|  | // private native static Thread[] getThreads(); | 
|  |  | 
|  | /** | 
|  | * Returns the identifier of this Thread.  The thread ID is a positive | 
|  | * <tt>long</tt> number generated when this thread was created. | 
|  | * The thread ID is unique and remains unchanged during its lifetime. | 
|  | * When a thread is terminated, this thread ID may be reused. | 
|  | * | 
|  | * @return this thread's ID. | 
|  | * @since 1.5 | 
|  | */ | 
|  | public long getId() { | 
|  | return tid; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * A thread state.  A thread can be in one of the following states: | 
|  | * <ul> | 
|  | * <li>{@link #NEW}<br> | 
|  | *     A thread that has not yet started is in this state. | 
|  | *     </li> | 
|  | * <li>{@link #RUNNABLE}<br> | 
|  | *     A thread executing in the Java virtual machine is in this state. | 
|  | *     </li> | 
|  | * <li>{@link #BLOCKED}<br> | 
|  | *     A thread that is blocked waiting for a monitor lock | 
|  | *     is in this state. | 
|  | *     </li> | 
|  | * <li>{@link #WAITING}<br> | 
|  | *     A thread that is waiting indefinitely for another thread to | 
|  | *     perform a particular action is in this state. | 
|  | *     </li> | 
|  | * <li>{@link #TIMED_WAITING}<br> | 
|  | *     A thread that is waiting for another thread to perform an action | 
|  | *     for up to a specified waiting time is in this state. | 
|  | *     </li> | 
|  | * <li>{@link #TERMINATED}<br> | 
|  | *     A thread that has exited is in this state. | 
|  | *     </li> | 
|  | * </ul> | 
|  | * | 
|  | * <p> | 
|  | * A thread can be in only one state at a given point in time. | 
|  | * These states are virtual machine states which do not reflect | 
|  | * any operating system thread states. | 
|  | * | 
|  | * @since   1.5 | 
|  | * @see #getState | 
|  | */ | 
|  | public enum State { | 
|  | /** | 
|  | * Thread state for a thread which has not yet started. | 
|  | */ | 
|  | NEW, | 
|  |  | 
|  | /** | 
|  | * Thread state for a runnable thread.  A thread in the runnable | 
|  | * state is executing in the Java virtual machine but it may | 
|  | * be waiting for other resources from the operating system | 
|  | * such as processor. | 
|  | */ | 
|  | RUNNABLE, | 
|  |  | 
|  | /** | 
|  | * Thread state for a thread blocked waiting for a monitor lock. | 
|  | * A thread in the blocked state is waiting for a monitor lock | 
|  | * to enter a synchronized block/method or | 
|  | * reenter a synchronized block/method after calling | 
|  | * {@link Object#wait() Object.wait}. | 
|  | */ | 
|  | BLOCKED, | 
|  |  | 
|  | /** | 
|  | * Thread state for a waiting thread. | 
|  | * A thread is in the waiting state due to calling one of the | 
|  | * following methods: | 
|  | * <ul> | 
|  | *   <li>{@link Object#wait() Object.wait} with no timeout</li> | 
|  | *   <li>{@link #join() Thread.join} with no timeout</li> | 
|  | *   <li>{@link LockSupport#park() LockSupport.park}</li> | 
|  | * </ul> | 
|  | * | 
|  | * <p>A thread in the waiting state is waiting for another thread to | 
|  | * perform a particular action. | 
|  | * | 
|  | * For example, a thread that has called <tt>Object.wait()</tt> | 
|  | * on an object is waiting for another thread to call | 
|  | * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on | 
|  | * that object. A thread that has called <tt>Thread.join()</tt> | 
|  | * is waiting for a specified thread to terminate. | 
|  | */ | 
|  | WAITING, | 
|  |  | 
|  | /** | 
|  | * Thread state for a waiting thread with a specified waiting time. | 
|  | * A thread is in the timed waiting state due to calling one of | 
|  | * the following methods with a specified positive waiting time: | 
|  | * <ul> | 
|  | *   <li>{@link #sleep Thread.sleep}</li> | 
|  | *   <li>{@link Object#wait(long) Object.wait} with timeout</li> | 
|  | *   <li>{@link #join(long) Thread.join} with timeout</li> | 
|  | *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> | 
|  | *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> | 
|  | * </ul> | 
|  | */ | 
|  | TIMED_WAITING, | 
|  |  | 
|  | /** | 
|  | * Thread state for a terminated thread. | 
|  | * The thread has completed execution. | 
|  | */ | 
|  | TERMINATED; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the state of this thread. | 
|  | * This method is designed for use in monitoring of the system state, | 
|  | * not for synchronization control. | 
|  | * | 
|  | * @return this thread's state. | 
|  | * @since 1.5 | 
|  | */ | 
|  | public State getState() { | 
|  | // get current thread state | 
|  | // Android-changed: Replace unused threadStatus field with started field. | 
|  | // Use Android specific nativeGetStatus() method. See comment on started field for more | 
|  | // information. | 
|  | // return sun.misc.VM.toThreadState(threadStatus); | 
|  | return State.values()[nativeGetStatus(started)]; | 
|  | } | 
|  |  | 
|  | // Added in JSR-166 | 
|  |  | 
|  | /** | 
|  | * Interface for handlers invoked when a <tt>Thread</tt> abruptly | 
|  | * terminates due to an uncaught exception. | 
|  | * <p>When a thread is about to terminate due to an uncaught exception | 
|  | * the Java Virtual Machine will query the thread for its | 
|  | * <tt>UncaughtExceptionHandler</tt> using | 
|  | * {@link #getUncaughtExceptionHandler} and will invoke the handler's | 
|  | * <tt>uncaughtException</tt> method, passing the thread and the | 
|  | * exception as arguments. | 
|  | * If a thread has not had its <tt>UncaughtExceptionHandler</tt> | 
|  | * explicitly set, then its <tt>ThreadGroup</tt> object acts as its | 
|  | * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object | 
|  | * has no | 
|  | * special requirements for dealing with the exception, it can forward | 
|  | * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler | 
|  | * default uncaught exception handler}. | 
|  | * | 
|  | * @see #setDefaultUncaughtExceptionHandler | 
|  | * @see #setUncaughtExceptionHandler | 
|  | * @see ThreadGroup#uncaughtException | 
|  | * @since 1.5 | 
|  | */ | 
|  | @FunctionalInterface | 
|  | public interface UncaughtExceptionHandler { | 
|  | /** | 
|  | * Method invoked when the given thread terminates due to the | 
|  | * given uncaught exception. | 
|  | * <p>Any exception thrown by this method will be ignored by the | 
|  | * Java Virtual Machine. | 
|  | * @param t the thread | 
|  | * @param e the exception | 
|  | */ | 
|  | void uncaughtException(Thread t, Throwable e); | 
|  | } | 
|  |  | 
|  | // null unless explicitly set | 
|  | private volatile UncaughtExceptionHandler uncaughtExceptionHandler; | 
|  |  | 
|  | // null unless explicitly set | 
|  | private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler; | 
|  |  | 
|  | /** | 
|  | * Set the default handler invoked when a thread abruptly terminates | 
|  | * due to an uncaught exception, and no other handler has been defined | 
|  | * for that thread. | 
|  | * | 
|  | * <p>Uncaught exception handling is controlled first by the thread, then | 
|  | * by the thread's {@link ThreadGroup} object and finally by the default | 
|  | * uncaught exception handler. If the thread does not have an explicit | 
|  | * uncaught exception handler set, and the thread's thread group | 
|  | * (including parent thread groups)  does not specialize its | 
|  | * <tt>uncaughtException</tt> method, then the default handler's | 
|  | * <tt>uncaughtException</tt> method will be invoked. | 
|  | * <p>By setting the default uncaught exception handler, an application | 
|  | * can change the way in which uncaught exceptions are handled (such as | 
|  | * logging to a specific device, or file) for those threads that would | 
|  | * already accept whatever "default" behavior the system | 
|  | * provided. | 
|  | * | 
|  | * <p>Note that the default uncaught exception handler should not usually | 
|  | * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause | 
|  | * infinite recursion. | 
|  | * | 
|  | * @param eh the object to use as the default uncaught exception handler. | 
|  | * If <tt>null</tt> then there is no default handler. | 
|  | * | 
|  | * @throws SecurityException if a security manager is present and it | 
|  | *         denies <tt>{@link RuntimePermission} | 
|  | *         ("setDefaultUncaughtExceptionHandler")</tt> | 
|  | * | 
|  | * @see #setUncaughtExceptionHandler | 
|  | * @see #getUncaughtExceptionHandler | 
|  | * @see ThreadGroup#uncaughtException | 
|  | * @since 1.5 | 
|  | */ | 
|  | public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { | 
|  | // Android-removed: SecurityManager stubbed out on Android. | 
|  | /* | 
|  | SecurityManager sm = System.getSecurityManager(); | 
|  | if (sm != null) { | 
|  | sm.checkPermission( | 
|  | new RuntimePermission("setDefaultUncaughtExceptionHandler") | 
|  | ); | 
|  | } | 
|  | */ | 
|  |  | 
|  | defaultUncaughtExceptionHandler = eh; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the default handler invoked when a thread abruptly terminates | 
|  | * due to an uncaught exception. If the returned value is <tt>null</tt>, | 
|  | * there is no default. | 
|  | * @since 1.5 | 
|  | * @see #setDefaultUncaughtExceptionHandler | 
|  | * @return the default uncaught exception handler for all threads | 
|  | */ | 
|  | public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){ | 
|  | return defaultUncaughtExceptionHandler; | 
|  | } | 
|  |  | 
|  | // BEGIN Android-added: The concept of an uncaughtExceptionPreHandler for use by platform. | 
|  | // See http://b/29624607 for background information. | 
|  | // null unless explicitly set | 
|  | private static volatile UncaughtExceptionHandler uncaughtExceptionPreHandler; | 
|  |  | 
|  | /** | 
|  | * Sets an {@link UncaughtExceptionHandler} that will be called before any | 
|  | * returned by {@link #getUncaughtExceptionHandler()}. To allow the standard | 
|  | * handlers to run, this handler should never terminate this process. Any | 
|  | * throwables thrown by the handler will be ignored by | 
|  | * {@link #dispatchUncaughtException(Throwable)}. | 
|  | * | 
|  | * @hide used when configuring the runtime for exception logging; see | 
|  | *     {@link dalvik.system.RuntimeHooks} b/29624607 | 
|  | */ | 
|  | public static void setUncaughtExceptionPreHandler(UncaughtExceptionHandler eh) { | 
|  | uncaughtExceptionPreHandler = eh; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets an {@link UncaughtExceptionHandler} that will be called before any | 
|  | * returned by {@link #getUncaughtExceptionHandler()}. Can be {@code null} if | 
|  | * was not explicitly set with | 
|  | * {@link #setUncaughtExceptionPreHandler(UncaughtExceptionHandler)}. | 
|  | * | 
|  | * @return the uncaught exception prehandler for this thread | 
|  | * | 
|  | * @hide | 
|  | */ | 
|  | public static UncaughtExceptionHandler getUncaughtExceptionPreHandler() { | 
|  | return uncaughtExceptionPreHandler; | 
|  | } | 
|  | // END Android-added: The concept of an uncaughtExceptionPreHandler for use by platform. | 
|  |  | 
|  | /** | 
|  | * Returns the handler invoked when this thread abruptly terminates | 
|  | * due to an uncaught exception. If this thread has not had an | 
|  | * uncaught exception handler explicitly set then this thread's | 
|  | * <tt>ThreadGroup</tt> object is returned, unless this thread | 
|  | * has terminated, in which case <tt>null</tt> is returned. | 
|  | * @since 1.5 | 
|  | * @return the uncaught exception handler for this thread | 
|  | */ | 
|  | public UncaughtExceptionHandler getUncaughtExceptionHandler() { | 
|  | return uncaughtExceptionHandler != null ? | 
|  | uncaughtExceptionHandler : group; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Set the handler invoked when this thread abruptly terminates | 
|  | * due to an uncaught exception. | 
|  | * <p>A thread can take full control of how it responds to uncaught | 
|  | * exceptions by having its uncaught exception handler explicitly set. | 
|  | * If no such handler is set then the thread's <tt>ThreadGroup</tt> | 
|  | * object acts as its handler. | 
|  | * @param eh the object to use as this thread's uncaught exception | 
|  | * handler. If <tt>null</tt> then this thread has no explicit handler. | 
|  | * @throws  SecurityException  if the current thread is not allowed to | 
|  | *          modify this thread. | 
|  | * @see #setDefaultUncaughtExceptionHandler | 
|  | * @see ThreadGroup#uncaughtException | 
|  | * @since 1.5 | 
|  | */ | 
|  | public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) { | 
|  | checkAccess(); | 
|  | uncaughtExceptionHandler = eh; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Dispatch an uncaught exception to the handler. This method is | 
|  | * intended to be called only by the runtime and by tests. | 
|  | * | 
|  | * @hide | 
|  | */ | 
|  | // Android-changed: Make dispatchUncaughtException() public, for use by tests. | 
|  | public final void dispatchUncaughtException(Throwable e) { | 
|  | // BEGIN Android-added: uncaughtExceptionPreHandler for use by platform. | 
|  | Thread.UncaughtExceptionHandler initialUeh = | 
|  | Thread.getUncaughtExceptionPreHandler(); | 
|  | if (initialUeh != null) { | 
|  | try { | 
|  | initialUeh.uncaughtException(this, e); | 
|  | } catch (RuntimeException | Error ignored) { | 
|  | // Throwables thrown by the initial handler are ignored | 
|  | } | 
|  | } | 
|  | // END Android-added: uncaughtExceptionPreHandler for use by platform. | 
|  | getUncaughtExceptionHandler().uncaughtException(this, e); | 
|  | } | 
|  |  | 
|  | // BEGIN Android-added: The concept of "system-daemon" threads. See java.lang.Daemons. | 
|  | /** | 
|  | * Marks this thread as either a special runtime-managed ("system daemon") | 
|  | * thread or a normal (i.e. app code created) daemon thread.) | 
|  | * | 
|  | * <p>System daemon threads get special handling when starting up in some | 
|  | * cases. | 
|  | * | 
|  | * <p>This method must be invoked before the thread is started. | 
|  | * | 
|  | * <p>This method must only be invoked on Thread instances that have already | 
|  | * had {@code setDaemon(true)} called on them. | 
|  | * | 
|  | * <p>Package-private since only {@link java.lang.Daemons} needs to call | 
|  | * this. | 
|  | * | 
|  | * @param  on if {@code true}, marks this thread as a system daemon thread | 
|  | * | 
|  | * @throws  IllegalThreadStateException | 
|  | *          if this thread is {@linkplain #isAlive alive} or not a | 
|  | *          {@linkplain #isDaemon daemon} | 
|  | * | 
|  | * @throws  SecurityException | 
|  | *          if {@link #checkAccess} determines that the current | 
|  | *          thread cannot modify this thread | 
|  | * | 
|  | * @hide For use by Daemons.java only. | 
|  | */ | 
|  | final void setSystemDaemon(boolean on) { | 
|  | checkAccess(); | 
|  | if (isAlive() || !isDaemon()) { | 
|  | throw new IllegalThreadStateException(); | 
|  | } | 
|  | systemDaemon = on; | 
|  | } | 
|  | // END Android-added: The concept of "system-daemon" threads. See java.lang.Daemons. | 
|  |  | 
|  | /** | 
|  | * Removes from the specified map any keys that have been enqueued | 
|  | * on the specified reference queue. | 
|  | */ | 
|  | static void processQueue(ReferenceQueue<Class<?>> queue, | 
|  | ConcurrentMap<? extends | 
|  | WeakReference<Class<?>>, ?> map) | 
|  | { | 
|  | Reference<? extends Class<?>> ref; | 
|  | while((ref = queue.poll()) != null) { | 
|  | map.remove(ref); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | *  Weak key for Class objects. | 
|  | **/ | 
|  | static class WeakClassKey extends WeakReference<Class<?>> { | 
|  | /** | 
|  | * saved value of the referent's identity hash code, to maintain | 
|  | * a consistent hash code after the referent has been cleared | 
|  | */ | 
|  | private final int hash; | 
|  |  | 
|  | /** | 
|  | * Create a new WeakClassKey to the given object, registered | 
|  | * with a queue. | 
|  | */ | 
|  | WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) { | 
|  | super(cl, refQueue); | 
|  | hash = System.identityHashCode(cl); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the identity hash code of the original referent. | 
|  | */ | 
|  | @Override | 
|  | public int hashCode() { | 
|  | return hash; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns true if the given object is this identical | 
|  | * WeakClassKey instance, or, if this object's referent has not | 
|  | * been cleared, if the given object is another WeakClassKey | 
|  | * instance with the identical non-null referent as this one. | 
|  | */ | 
|  | @Override | 
|  | public boolean equals(Object obj) { | 
|  | if (obj == this) | 
|  | return true; | 
|  |  | 
|  | if (obj instanceof WeakClassKey) { | 
|  | Object referent = get(); | 
|  | return (referent != null) && | 
|  | (referent == ((WeakClassKey) obj).get()); | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // The following three initially uninitialized fields are exclusively | 
|  | // managed by class java.util.concurrent.ThreadLocalRandom. These | 
|  | // fields are used to build the high-performance PRNGs in the | 
|  | // concurrent code, and we can not risk accidental false sharing. | 
|  | // Hence, the fields are isolated with @Contended. | 
|  |  | 
|  | // BEGIN Android-changed: @sun.misc.Contended is not supported on Android. | 
|  | /** The current seed for a ThreadLocalRandom */ | 
|  | // @sun.misc.Contended("tlr") | 
|  | long threadLocalRandomSeed; | 
|  |  | 
|  | /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ | 
|  | // @sun.misc.Contended("tlr") | 
|  | int threadLocalRandomProbe; | 
|  |  | 
|  | /** Secondary seed isolated from public ThreadLocalRandom sequence */ | 
|  | //  @sun.misc.Contended("tlr") | 
|  | int threadLocalRandomSecondarySeed; | 
|  | // END Android-changed: @sun.misc.Contended is not supported on Android. | 
|  |  | 
|  | /* Some private helper methods */ | 
|  | private native void setPriority0(int newPriority); | 
|  |  | 
|  | // BEGIN Android-removed: Native methods that are unused on Android. | 
|  | /* | 
|  | private native void stop0(Object o); | 
|  | private native void suspend0(); | 
|  | private native void resume0(); | 
|  | */ | 
|  | // END Android-removed: Native methods that are unused on Android. | 
|  |  | 
|  | @FastNative | 
|  | private native void interrupt0(); | 
|  | private native void setNativeName(String name); | 
|  |  | 
|  | // Android-added: Android specific nativeGetStatus() method. | 
|  | private native int nativeGetStatus(boolean hasBeenStarted); | 
|  | } |