content: /*
   * 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.RuntimeHooks;
  import dalvik.system.ThreadPrioritySetter;
  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
   *             &nbsp;.&nbsp;.&nbsp;.
   *         }
   *     }
   * </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
   *             &nbsp;.&nbsp;.&nbsp;.
   *         }
   *     }
   * </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;
          long start = System.nanoTime();
          long duration = (millis * nanosPerMilli) + nanos;
  
          Object lock = currentThread().lock;
  
          // The native sleep(...) method actually performs a special type of wait, which may return
          // early, so loop until sleep duration passes.
          synchronized (lock) {
              while (true) {
                  sleep(lock, millis, nanos);
  
                  long now = System.nanoTime();
                  long elapsed = now - start;
  
                  if (elapsed >= duration) {
                      break;
                  }
  
                  duration -= elapsed;
                  start = now;
                  millis = duration / nanosPerMilli;
                  nanos = (int) (duration % nanosPerMilli);
              }
          }
          // 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) {
              //创建了ThreadLocalMap，想一下 handler 的 threadlocal
              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.
       *
       * @throws 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="{@docRoot}/../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="{@docRoot}/../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.
       * @revised 6.0
       * @see #isInterrupted()
       */
      // 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.
       * @revised 6.0
       * @see #interrupted()
       */
      // 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}.
       *
       * @throws UnsupportedOperationException always
       * @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="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
       * Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
       */
      @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}.
       *
       * @throws UnsupportedOperationException always
       * @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="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
       * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
       */
      @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}.
       *
       * @throws UnsupportedOperationException always
       * @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="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
       * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
       */
      @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
       * @throws IllegalArgumentException If the priority is not in the
       *                                  range <code>MIN_PRIORITY</code> to
       *                                  <code>MAX_PRIORITY</code>.
       * @throws 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()) {
                      // BEGIN Android-added: Customize behavior of Thread.setPriority().
                      // http://b/139521784
                      // setPriority0(newPriority);
                      ThreadPrioritySetter threadPrioritySetter =
                              RuntimeHooks.getThreadPrioritySetter();
                      int nativeTid = this.getNativeTid();
                      if (threadPrioritySetter != null && nativeTid != 0) {
                          threadPrioritySetter.setPriority(nativeTid, newPriority);
                      } else {
                          setPriority0(newPriority);
                      }
                      // END Android-added: Customize behavior of Thread.setPriority().
                  }
              }
          }
      }
  
      /**
       * 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.
       * @throws 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() == 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 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 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 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.
       * @throws 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.
      // 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>.
       *
       * @throws 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
       * @return <tt>true</tt> if the current thread holds the monitor lock on
       * the specified object.
       * @throws NullPointerException if obj is <tt>null</tt>
       * @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.
       *
       * @see #getState
       * @since 1.5
       */
      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.
           * <p>
           * 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 &quot;default&quot; 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}
       *                           (&quot;setDefaultUncaughtExceptionHandler&quot;)</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.
       *
       * @return the default uncaught exception handler for all threads
       * @see #setDefaultUncaughtExceptionHandler
       * @since 1.5
       */
      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;
      }
  
      /**
       * @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.
       *
       * @return the uncaught exception handler for this thread
       * @since 1.5
       */
      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.
          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);
  
      // BEGIN Android-added: Customize behavior of Thread.setPriority(). http://b/139521784
  
      /**
       * Returns the thread ID of the underlying native thread -- which is different from
       * the {@link #getId() managed thread ID} -- or 0 if the native thread is not
       * started or has stopped.
       */
      @FastNative
      private native int getNativeTid();
      // END Android-added: Customize behavior of Thread.setPriority(). http://b/139521784
  }
  