TimeStamp.java
/*
* Copyright (C) 2021 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 androidx.test.services.events;
import static androidx.test.internal.util.Checks.checkNotNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import java.time.Clock;
import java.time.Instant;
/**
* Denotes an android test error. Has details of the error including stack trace, type, and message.
*/
public final class TimeStamp implements Parcelable {
/** Represents sends of UTC time since the Unix epoch. */
@NonNull public final Long seconds;
/** Timestamp nanoseconds - must be non negative even if seconds is negative. */
@NonNull public final Integer nanos;
/** Clock, package-private for testing. */
@SuppressWarnings("AndroidJdkLibsChecker")
static Clock clock = null;
/** Constructor to create a {@link TimeStamp}. */
public TimeStamp(@NonNull Long seconds, @NonNull Integer nanos) {
this.seconds = checkNotNull(seconds, "seconds cannot be null");
this.nanos = checkNotNull(nanos, "nanos cannot be null");
}
/**
* Creates a {@link TimeStamp} from android {@link Parcel}.
*
* @param source the android Parcel.
*/
public TimeStamp(@NonNull Parcel source) {
checkNotNull(source, "source cannot be null");
seconds = checkNotNull(source.readLong(), "seconds cannot be null");
nanos = checkNotNull(source.readInt(), "nanos cannot be null");
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(seconds);
parcel.writeInt(nanos);
}
public static final Parcelable.Creator<TimeStamp> CREATOR =
new Parcelable.Creator<TimeStamp>() {
@Override
public TimeStamp createFromParcel(Parcel source) {
return new TimeStamp(source);
}
@Override
public TimeStamp[] newArray(int size) {
return new TimeStamp[size];
}
};
@TargetApi(Build.VERSION_CODES.O)
@SuppressWarnings("AndroidJdkLibsChecker")
private static TimeStamp modernNow() {
if (clock == null) {
clock = Clock.systemUTC();
}
Instant now = Instant.now(clock);
return new TimeStamp(now.getEpochSecond(), now.getNano());
}
@TargetApi(Build.VERSION_CODES.N_MR1)
@SuppressWarnings({"MillisTo_Seconds", "MillisTo_Nanos", "SecondsTo_Nanos"})
private static TimeStamp legacyNow() {
// System.nanoTime() only gives you a high-resolution time source and makes no guarantees
// about the event it references; it can be negative!
long now = System.currentTimeMillis();
long seconds = MILLISECONDS.toSeconds(now);
long nanosOffset = MILLISECONDS.toNanos(now) - SECONDS.toNanos(seconds);
return new TimeStamp(seconds, (int) nanosOffset);
}
public static TimeStamp now() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return modernNow();
} else {
return legacyNow();
}
}
}