/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os; /*-[ #include "libcore/io/ErrnoException.h" #include <sys/types.h> #include <sys/sysctl.h> ]-*/ /** * Core timekeeping facilities. * * <p> Three different clocks are available, and they should not be confused: * * <ul> * <li> <p> {@link System#currentTimeMillis System.currentTimeMillis()} * is the standard "wall" clock (time and date) expressing milliseconds * since the epoch. The wall clock can be set by the user or the phone * network (see {@link #setCurrentTimeMillis}), so the time may jump * backwards or forwards unpredictably. This clock should only be used * when correspondence with real-world dates and times is important, such * as in a calendar or alarm clock application. Interval or elapsed * time measurements should use a different clock. * * <li> <p> {@link #uptimeMillis} is counted in milliseconds since the * system was booted. This clock stops when the system enters deep * sleep (CPU off, display dark, device waiting for external input), * but is not affected by clock scaling, idle, or other power saving * mechanisms. This is the basis for most interval timing * such as {@link Thread#sleep(long) Thread.sleep(millls)}, * {@link Object#wait(long) Object.wait(millis)}, and * {@link System#nanoTime System.nanoTime()}. This clock is guaranteed * to be monotonic, and is suitable for interval timing when the * interval does not span device sleep. Most methods that accept a * timestamp value currently expect the {@link #uptimeMillis} clock. * * <li> <p> {@link #elapsedRealtime} and {@link #elapsedRealtimeNanos} * return the time since the system was booted, and include deep sleep. * This clock is guaranteed to be monotonic, and continues to tick even * when the CPU is in power saving modes, so is the recommend basis * for general purpose interval timing. * * </ul> * * There are several mechanisms for controlling the timing of events: * * <ul> * <li> <p> Standard functions like {@link Thread#sleep(long) * Thread.sleep(millis)} and {@link Object#wait(long) Object.wait(millis)} * are always available. These functions use the {@link #uptimeMillis} * clock; if the device enters sleep, the remainder of the time will be * postponed until the device wakes up. These synchronous functions may * be interrupted with {@link Thread#interrupt Thread.interrupt()}, and * you must handle {@link InterruptedException}. * * <li> <p> {@link #sleep SystemClock.sleep(millis)} is a utility function * very similar to {@link Thread#sleep(long) Thread.sleep(millis)}, but it * ignores {@link InterruptedException}. Use this function for delays if * you do not use {@link Thread#interrupt Thread.interrupt()}, as it will * preserve the interrupted state of the thread. * </ul> */ public final class SystemClock { private static final String TAG = "SystemClock"; /** * This class is uninstantiable. */ private SystemClock() { // This space intentionally left blank. } /** * Waits a given number of milliseconds (of uptimeMillis) before returning. * Similar to {@link java.lang.Thread#sleep(long)}, but does not throw * {@link InterruptedException}; {@link Thread#interrupt()} events are * deferred until the next interruptible operation. Does not return until * at least the specified number of milliseconds has elapsed. * * @param ms to sleep before returning, in milliseconds of uptime. */ public static void sleep(long ms) { long start = uptimeMillis(); long duration = ms; boolean interrupted = false; do { try { Thread.sleep(duration); } catch (InterruptedException e) { interrupted = true; } duration = start + ms - uptimeMillis(); } while (duration > 0); if (interrupted) { // Important: we don't want to quietly eat an interrupt() event, // so we make sure to re-interrupt the thread so that the next // call to Thread.sleep() or Object.wait() will be interrupted. Thread.currentThread().interrupt(); } } /** * Sets the current wall time, in milliseconds. Requires the calling * process to have appropriate permissions. * * @return if the clock was successfully set to the specified time. */ public static boolean setCurrentTimeMillis(long millis) { // TODO(tball): implement on iOS only if any customers need it. return false; } /** * Returns milliseconds since boot, not counting time spent in deep sleep. * * @return milliseconds of non-sleep uptime since boot. */ public static long uptimeMillis() { return elapsedRealtime(); // Not aware of any iOS API to track deep sleep time. } /*-[ static long long boottime_usec() { // MIB = Management Information Base (man sysctl). #define MIB_SIZE 2 int mib[MIB_SIZE]; size_t size; struct timeval boottime; mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; size = sizeof(boottime); if (sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) == -1) { @throw AUTORELEASE([[LibcoreIoErrnoException alloc] initWithNSString:@"sysctl" withInt:errno]); } return ((long long) boottime.tv_sec) * 1.e6 + boottime.tv_usec; } static long long uptime_usec() { // source: http://stackoverflow.com/a/40497811 long long before_now; long long after_now; struct timeval now; after_now = boottime_usec(); do { before_now = after_now; gettimeofday(&now, NULL); after_now = boottime_usec(); } while (after_now != before_now); return ((long long) now.tv_sec) * 1.e6 + now.tv_usec - before_now; } ]-*/ /** * Returns milliseconds since boot, including time spent in sleep. * * @return elapsed milliseconds since boot. */ public native static long elapsedRealtime() /*-[ return (long long)(uptime_usec() / 1000.0); ]-*/; /** * Returns nanoseconds since boot, including time spent in sleep. * * @return elapsed nanoseconds since boot. */ public static native long elapsedRealtimeNanos() /*-[ return uptime_usec() * 1000; ]-*/; /** * Returns current wall time in microseconds. * * @return elapsed microseconds in wall time * * @hide */ public static native long currentTimeMicro() /*-[ return (long long) [[NSDate date] timeIntervalSince1970]; ]-*/; // Not available on iOS. /** * Returns milliseconds running in the current thread. * * @return elapsed milliseconds in the thread * public static native long currentThreadTimeMillis(); /** * Returns microseconds running in the current thread. * * @return elapsed microseconds in the thread * * @hide * public static native long currentThreadTimeMicro(); */ }