Loading core/java/android/widget/Chronometer.java +14 −5 Original line number Diff line number Diff line Loading @@ -289,8 +289,7 @@ public class Chronometer extends TextView { private synchronized void updateText(long now) { mNow = now; long seconds = mCountDown ? mBase - now : now - mBase; seconds /= 1000; long seconds = Math.round((mCountDown ? mBase - now - 499 : now - mBase) / 1000f); boolean negative = false; if (seconds < 0) { seconds = -seconds; Loading Loading @@ -348,9 +347,19 @@ public class Chronometer extends TextView { }; private void postTickOnNextSecond() { long nowMillis = SystemClock.elapsedRealtime(); int millis = (int) ((nowMillis - mBase) % 1000); postDelayed(mTickRunnable, 1000 - millis); long nowMillis = mNow; long delayMillis; if (mCountDown) { delayMillis = (mBase - nowMillis) % 1000; if (delayMillis <= 0) { delayMillis += 1000; } } else { delayMillis = 1000 - (Math.abs(nowMillis - mBase) % 1000); } // Aim for 1 millisecond into the next second so we don't update exactly on the second delayMillis++; postDelayed(mTickRunnable, delayMillis); } void dispatchChronometerTick() { Loading core/tests/coretests/src/android/widget/ChronometerTest.java +28 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.widget; import android.app.Activity; import android.os.SystemClock; import android.test.ActivityInstrumentationTestCase2; import androidx.test.filters.LargeTest; Loading @@ -28,7 +29,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Test {@link DatePicker} focus changes. * Test {@link Chronometer} counting up and down. */ @SuppressWarnings("deprecation") @LargeTest Loading @@ -50,26 +51,48 @@ public class ChronometerTest extends ActivityInstrumentationTestCase2<Chronomete } public void testChronometerTicksSequentially() throws Throwable { final CountDownLatch latch = new CountDownLatch(5); final CountDownLatch latch = new CountDownLatch(6); ArrayList<String> ticks = new ArrayList<>(); runOnUiThread(() -> { mChronometer.setOnChronometerTickListener((chronometer) -> { ticks.add(chronometer.getText().toString()); latch.countDown(); try { Thread.sleep(500); Thread.sleep(250); } catch (InterruptedException e) { } }); mChronometer.start(); }); assertTrue(latch.await(6, TimeUnit.SECONDS)); assertTrue(ticks.size() >= 5); assertTrue(latch.await(5500, TimeUnit.MILLISECONDS)); assertEquals("00:00", ticks.get(0)); assertEquals("00:01", ticks.get(1)); assertEquals("00:02", ticks.get(2)); assertEquals("00:03", ticks.get(3)); assertEquals("00:04", ticks.get(4)); assertEquals("00:05", ticks.get(5)); } public void testChronometerCountDown() throws Throwable { final CountDownLatch latch = new CountDownLatch(5); ArrayList<String> ticks = new ArrayList<>(); runOnUiThread(() -> { mChronometer.setBase(SystemClock.elapsedRealtime() + 3_000); mChronometer.setCountDown(true); mChronometer.post(() -> { mChronometer.setOnChronometerTickListener((chronometer) -> { ticks.add(chronometer.getText().toString()); latch.countDown(); }); mChronometer.start(); }); }); assertTrue(latch.await(4500, TimeUnit.MILLISECONDS)); assertEquals("00:02", ticks.get(0)); assertEquals("00:01", ticks.get(1)); assertEquals("00:00", ticks.get(2)); assertEquals("−00:01", ticks.get(3)); assertEquals("−00:02", ticks.get(4)); } private void runOnUiThread(Runnable runnable) throws InterruptedException { Loading Loading
core/java/android/widget/Chronometer.java +14 −5 Original line number Diff line number Diff line Loading @@ -289,8 +289,7 @@ public class Chronometer extends TextView { private synchronized void updateText(long now) { mNow = now; long seconds = mCountDown ? mBase - now : now - mBase; seconds /= 1000; long seconds = Math.round((mCountDown ? mBase - now - 499 : now - mBase) / 1000f); boolean negative = false; if (seconds < 0) { seconds = -seconds; Loading Loading @@ -348,9 +347,19 @@ public class Chronometer extends TextView { }; private void postTickOnNextSecond() { long nowMillis = SystemClock.elapsedRealtime(); int millis = (int) ((nowMillis - mBase) % 1000); postDelayed(mTickRunnable, 1000 - millis); long nowMillis = mNow; long delayMillis; if (mCountDown) { delayMillis = (mBase - nowMillis) % 1000; if (delayMillis <= 0) { delayMillis += 1000; } } else { delayMillis = 1000 - (Math.abs(nowMillis - mBase) % 1000); } // Aim for 1 millisecond into the next second so we don't update exactly on the second delayMillis++; postDelayed(mTickRunnable, delayMillis); } void dispatchChronometerTick() { Loading
core/tests/coretests/src/android/widget/ChronometerTest.java +28 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.widget; import android.app.Activity; import android.os.SystemClock; import android.test.ActivityInstrumentationTestCase2; import androidx.test.filters.LargeTest; Loading @@ -28,7 +29,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Test {@link DatePicker} focus changes. * Test {@link Chronometer} counting up and down. */ @SuppressWarnings("deprecation") @LargeTest Loading @@ -50,26 +51,48 @@ public class ChronometerTest extends ActivityInstrumentationTestCase2<Chronomete } public void testChronometerTicksSequentially() throws Throwable { final CountDownLatch latch = new CountDownLatch(5); final CountDownLatch latch = new CountDownLatch(6); ArrayList<String> ticks = new ArrayList<>(); runOnUiThread(() -> { mChronometer.setOnChronometerTickListener((chronometer) -> { ticks.add(chronometer.getText().toString()); latch.countDown(); try { Thread.sleep(500); Thread.sleep(250); } catch (InterruptedException e) { } }); mChronometer.start(); }); assertTrue(latch.await(6, TimeUnit.SECONDS)); assertTrue(ticks.size() >= 5); assertTrue(latch.await(5500, TimeUnit.MILLISECONDS)); assertEquals("00:00", ticks.get(0)); assertEquals("00:01", ticks.get(1)); assertEquals("00:02", ticks.get(2)); assertEquals("00:03", ticks.get(3)); assertEquals("00:04", ticks.get(4)); assertEquals("00:05", ticks.get(5)); } public void testChronometerCountDown() throws Throwable { final CountDownLatch latch = new CountDownLatch(5); ArrayList<String> ticks = new ArrayList<>(); runOnUiThread(() -> { mChronometer.setBase(SystemClock.elapsedRealtime() + 3_000); mChronometer.setCountDown(true); mChronometer.post(() -> { mChronometer.setOnChronometerTickListener((chronometer) -> { ticks.add(chronometer.getText().toString()); latch.countDown(); }); mChronometer.start(); }); }); assertTrue(latch.await(4500, TimeUnit.MILLISECONDS)); assertEquals("00:02", ticks.get(0)); assertEquals("00:01", ticks.get(1)); assertEquals("00:00", ticks.get(2)); assertEquals("−00:01", ticks.get(3)); assertEquals("−00:02", ticks.get(4)); } private void runOnUiThread(Runnable runnable) throws InterruptedException { Loading