Fix Thread.sleep(0) of an interrupted thread

Bug: 12929305
Change-Id: I3061c3345c68de8bcf438e6935446b4f7cd76001
diff --git a/libart/src/main/java/java/lang/Thread.java b/libart/src/main/java/java/lang/Thread.java
index 2cc2857..b826e66 100644
--- a/libart/src/main/java/java/lang/Thread.java
+++ b/libart/src/main/java/java/lang/Thread.java
@@ -993,9 +993,23 @@
      * @see Thread#interrupt()
      */
     public static void sleep(long millis, int nanos) throws InterruptedException {
+        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);
+        }
+
         // 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;
         }
 
diff --git a/luni/src/test/java/libcore/java/lang/ThreadTest.java b/luni/src/test/java/libcore/java/lang/ThreadTest.java
index 68ad795..8545a20 100644
--- a/luni/src/test/java/libcore/java/lang/ThreadTest.java
+++ b/luni/src/test/java/libcore/java/lang/ThreadTest.java
@@ -59,15 +59,46 @@
     }
 
     public void testThreadSleep() throws Exception {
-       int millis = 1000;
-       long start = System.currentTimeMillis();
+        int millis = 1000;
+        long start = System.currentTimeMillis();
 
-       Thread.sleep(millis);
+        Thread.sleep(millis);
 
-       long elapsed = System.currentTimeMillis() - start;
-       long offBy = Math.abs(elapsed - millis);
+        long elapsed = System.currentTimeMillis() - start;
+        long offBy = Math.abs(elapsed - millis);
 
-       assertTrue("Actual sleep off by " + offBy + " ms", offBy <= 250);
+        assertTrue("Actual sleep off by " + offBy + " ms", offBy <= 250);
+    }
+
+    public void testThreadInterrupted() throws Exception {
+        Thread.currentThread().interrupt();
+        try {
+            Thread.sleep(0);
+            fail();
+        } catch (InterruptedException e) {
+            assertFalse(Thread.currentThread().isInterrupted());
+        }
+    }
+
+    public void testThreadSleepIllegalArguments() throws Exception {
+
+        try {
+            Thread.sleep(-1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            Thread.sleep(0, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            Thread.sleep(0, 1000000);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
     }
 
     public void testThreadWakeup() throws Exception {