Merge "Add a Y2038 check into the time_detector"
This commit is contained in:
@@ -19,15 +19,14 @@ package android.app.time;
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.app.timedetector.TimeSuggestionHelper;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -75,7 +74,9 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
public static final @NonNull Creator<ExternalTimeSuggestion> CREATOR =
|
||||
new Creator<ExternalTimeSuggestion>() {
|
||||
public ExternalTimeSuggestion createFromParcel(Parcel in) {
|
||||
return ExternalTimeSuggestion.createFromParcel(in);
|
||||
TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
|
||||
ExternalTimeSuggestion.class, in);
|
||||
return new ExternalTimeSuggestion(helper);
|
||||
}
|
||||
|
||||
public ExternalTimeSuggestion[] newArray(int size) {
|
||||
@@ -83,10 +84,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private final TimestampedValue<Long> mUnixEpochTime;
|
||||
@Nullable
|
||||
private ArrayList<String> mDebugInfo;
|
||||
@NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
|
||||
|
||||
/**
|
||||
* Creates a time suggestion cross-referenced to the elapsed realtime clock. See {@link
|
||||
@@ -98,17 +96,12 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
*/
|
||||
public ExternalTimeSuggestion(@ElapsedRealtimeLong long elapsedRealtimeMillis,
|
||||
@CurrentTimeMillisLong long suggestionMillis) {
|
||||
mUnixEpochTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
|
||||
mTimeSuggestionHelper = new TimeSuggestionHelper(ExternalTimeSuggestion.class,
|
||||
new TimestampedValue<>(elapsedRealtimeMillis, suggestionMillis));
|
||||
}
|
||||
|
||||
private static ExternalTimeSuggestion createFromParcel(Parcel in) {
|
||||
TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
|
||||
ExternalTimeSuggestion suggestion =
|
||||
new ExternalTimeSuggestion(utcTime.getReferenceTimeMillis(), utcTime.getValue());
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
|
||||
suggestion.mDebugInfo = debugInfo;
|
||||
return suggestion;
|
||||
private ExternalTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
|
||||
mTimeSuggestionHelper = Objects.requireNonNull(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,8 +111,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeParcelable(mUnixEpochTime, 0);
|
||||
dest.writeList(mDebugInfo);
|
||||
mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +119,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
*/
|
||||
@NonNull
|
||||
public TimestampedValue<Long> getUnixEpochTime() {
|
||||
return mUnixEpochTime;
|
||||
return mTimeSuggestionHelper.getUnixEpochTime();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,9 +127,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
*/
|
||||
@NonNull
|
||||
public List<String> getDebugInfo() {
|
||||
return mDebugInfo == null
|
||||
? Collections.emptyList()
|
||||
: Collections.unmodifiableList(mDebugInfo);
|
||||
return mTimeSuggestionHelper.getDebugInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,10 +136,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
* #equals(Object)} and {@link #hashCode()}.
|
||||
*/
|
||||
public void addDebugInfo(@NonNull String... debugInfos) {
|
||||
if (mDebugInfo == null) {
|
||||
mDebugInfo = new ArrayList<>();
|
||||
}
|
||||
mDebugInfo.addAll(Arrays.asList(debugInfos));
|
||||
mTimeSuggestionHelper.addDebugInfo(debugInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,18 +148,29 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
ExternalTimeSuggestion that = (ExternalTimeSuggestion) o;
|
||||
return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExternalTimeSuggestion{" + "mUnixEpochTime=" + mUnixEpochTime
|
||||
+ ", mDebugInfo=" + mDebugInfo
|
||||
+ '}';
|
||||
return mTimeSuggestionHelper.handleToString();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static ExternalTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
|
||||
throws IllegalArgumentException {
|
||||
return new ExternalTimeSuggestion(
|
||||
TimeSuggestionHelper.handleParseCommandLineArg(ExternalTimeSuggestion.class, cmd));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void printCommandLineOpts(PrintWriter pw) {
|
||||
TimeSuggestionHelper.handlePrintCommandLineOpts(
|
||||
pw, "External", ExternalTimeSuggestion.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,30 +17,19 @@
|
||||
package android.app.timedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A time signal from a GNSS source.
|
||||
*
|
||||
* <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
|
||||
* milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system. The {@code
|
||||
* unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when the {@code
|
||||
* unixEpochTime.value} was established. Note that the elapsed realtime clock is considered accurate
|
||||
* but it is volatile, so time suggestions cannot be persisted across device resets.
|
||||
*
|
||||
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
|
||||
* record why the suggestion exists and how it was entered. This information exists only to aid in
|
||||
* debugging and therefore is used by {@link #toString()}, but it is not for use in detection
|
||||
* logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
|
||||
* <p>See {@link TimeSuggestionHelper} for property information.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@@ -49,7 +38,9 @@ public final class GnssTimeSuggestion implements Parcelable {
|
||||
public static final @NonNull Creator<GnssTimeSuggestion> CREATOR =
|
||||
new Creator<GnssTimeSuggestion>() {
|
||||
public GnssTimeSuggestion createFromParcel(Parcel in) {
|
||||
return GnssTimeSuggestion.createFromParcel(in);
|
||||
TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
|
||||
GnssTimeSuggestion.class, in);
|
||||
return new GnssTimeSuggestion(helper);
|
||||
}
|
||||
|
||||
public GnssTimeSuggestion[] newArray(int size) {
|
||||
@@ -57,21 +48,14 @@ public final class GnssTimeSuggestion implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull private final TimestampedValue<Long> mUnixEpochTime;
|
||||
@Nullable private ArrayList<String> mDebugInfo;
|
||||
@NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
|
||||
|
||||
public GnssTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
|
||||
mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
|
||||
Objects.requireNonNull(unixEpochTime.getValue());
|
||||
mTimeSuggestionHelper = new TimeSuggestionHelper(GnssTimeSuggestion.class, unixEpochTime);
|
||||
}
|
||||
|
||||
private static GnssTimeSuggestion createFromParcel(Parcel in) {
|
||||
TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
|
||||
GnssTimeSuggestion suggestion = new GnssTimeSuggestion(unixEpochTime);
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
|
||||
suggestion.mDebugInfo = debugInfo;
|
||||
return suggestion;
|
||||
private GnssTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
|
||||
mTimeSuggestionHelper = Objects.requireNonNull(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,19 +65,17 @@ public final class GnssTimeSuggestion implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeParcelable(mUnixEpochTime, 0);
|
||||
dest.writeList(mDebugInfo);
|
||||
mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TimestampedValue<Long> getUnixEpochTime() {
|
||||
return mUnixEpochTime;
|
||||
return mTimeSuggestionHelper.getUnixEpochTime();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<String> getDebugInfo() {
|
||||
return mDebugInfo == null
|
||||
? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
|
||||
return mTimeSuggestionHelper.getDebugInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,10 +84,7 @@ public final class GnssTimeSuggestion implements Parcelable {
|
||||
* {@link #equals(Object)} and {@link #hashCode()}.
|
||||
*/
|
||||
public void addDebugInfo(String... debugInfos) {
|
||||
if (mDebugInfo == null) {
|
||||
mDebugInfo = new ArrayList<>();
|
||||
}
|
||||
mDebugInfo.addAll(Arrays.asList(debugInfos));
|
||||
mTimeSuggestionHelper.addDebugInfo(debugInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,19 +96,29 @@ public final class GnssTimeSuggestion implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
GnssTimeSuggestion that = (GnssTimeSuggestion) o;
|
||||
return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GnssTimeSuggestion{"
|
||||
+ "mUnixEpochTime=" + mUnixEpochTime
|
||||
+ ", mDebugInfo=" + mDebugInfo
|
||||
+ '}';
|
||||
return mTimeSuggestionHelper.handleToString();
|
||||
}
|
||||
|
||||
/** Parses command line args to create a {@link GnssTimeSuggestion}. */
|
||||
public static GnssTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
|
||||
throws IllegalArgumentException {
|
||||
TimeSuggestionHelper suggestionHelper =
|
||||
TimeSuggestionHelper.handleParseCommandLineArg(GnssTimeSuggestion.class, cmd);
|
||||
return new GnssTimeSuggestion(suggestionHelper);
|
||||
}
|
||||
|
||||
/** Prints the command line args needed to create a {@link GnssTimeSuggestion}. */
|
||||
public static void printCommandLineOpts(PrintWriter pw) {
|
||||
TimeSuggestionHelper.handlePrintCommandLineOpts(pw, "GNSS", GnssTimeSuggestion.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,27 +20,17 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A time signal from a manual (user provided) source.
|
||||
*
|
||||
* <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
|
||||
* milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code unixEpochTime.referenceTimeMillis}
|
||||
* is the value of the elapsed realtime clock when the {@code unixEpochTime.value} was established.
|
||||
* Note that the elapsed realtime clock is considered accurate but it is volatile, so time
|
||||
* suggestions cannot be persisted across device resets.
|
||||
*
|
||||
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
|
||||
* record why the suggestion exists and how it was entered. This information exists only to aid in
|
||||
* debugging and therefore is used by {@link #toString()}, but it is not for use in detection
|
||||
* logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
|
||||
* <p>See {@link TimeSuggestionHelper} for property information.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@@ -49,7 +39,9 @@ public final class ManualTimeSuggestion implements Parcelable {
|
||||
public static final @NonNull Creator<ManualTimeSuggestion> CREATOR =
|
||||
new Creator<ManualTimeSuggestion>() {
|
||||
public ManualTimeSuggestion createFromParcel(Parcel in) {
|
||||
return ManualTimeSuggestion.createFromParcel(in);
|
||||
TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
|
||||
ManualTimeSuggestion.class, in);
|
||||
return new ManualTimeSuggestion(helper);
|
||||
}
|
||||
|
||||
public ManualTimeSuggestion[] newArray(int size) {
|
||||
@@ -57,21 +49,14 @@ public final class ManualTimeSuggestion implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull private final TimestampedValue<Long> mUnixEpochTime;
|
||||
@Nullable private ArrayList<String> mDebugInfo;
|
||||
@NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
|
||||
|
||||
public ManualTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
|
||||
mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
|
||||
Objects.requireNonNull(unixEpochTime.getValue());
|
||||
mTimeSuggestionHelper = new TimeSuggestionHelper(ManualTimeSuggestion.class, unixEpochTime);
|
||||
}
|
||||
|
||||
private static ManualTimeSuggestion createFromParcel(Parcel in) {
|
||||
TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
|
||||
ManualTimeSuggestion suggestion = new ManualTimeSuggestion(unixEpochTime);
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
|
||||
suggestion.mDebugInfo = debugInfo;
|
||||
return suggestion;
|
||||
private ManualTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
|
||||
mTimeSuggestionHelper = Objects.requireNonNull(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,19 +66,17 @@ public final class ManualTimeSuggestion implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeParcelable(mUnixEpochTime, 0);
|
||||
dest.writeList(mDebugInfo);
|
||||
mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TimestampedValue<Long> getUnixEpochTime() {
|
||||
return mUnixEpochTime;
|
||||
return mTimeSuggestionHelper.getUnixEpochTime();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<String> getDebugInfo() {
|
||||
return mDebugInfo == null
|
||||
? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
|
||||
return mTimeSuggestionHelper.getDebugInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,10 +85,7 @@ public final class ManualTimeSuggestion implements Parcelable {
|
||||
* {@link #equals(Object)} and {@link #hashCode()}.
|
||||
*/
|
||||
public void addDebugInfo(String... debugInfos) {
|
||||
if (mDebugInfo == null) {
|
||||
mDebugInfo = new ArrayList<>();
|
||||
}
|
||||
mDebugInfo.addAll(Arrays.asList(debugInfos));
|
||||
mTimeSuggestionHelper.addDebugInfo(debugInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,19 +97,28 @@ public final class ManualTimeSuggestion implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
ManualTimeSuggestion that = (ManualTimeSuggestion) o;
|
||||
return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ManualTimeSuggestion{"
|
||||
+ "mUnixEpochTime=" + mUnixEpochTime
|
||||
+ ", mDebugInfo=" + mDebugInfo
|
||||
+ '}';
|
||||
return mTimeSuggestionHelper.handleToString();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static ManualTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
|
||||
throws IllegalArgumentException {
|
||||
return new ManualTimeSuggestion(
|
||||
TimeSuggestionHelper.handleParseCommandLineArg(ManualTimeSuggestion.class, cmd));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void printCommandLineOpts(PrintWriter pw) {
|
||||
TimeSuggestionHelper.handlePrintCommandLineOpts(pw, "Manual", ManualTimeSuggestion.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,31 +17,19 @@
|
||||
package android.app.timedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A time signal from a network time source like NTP.
|
||||
*
|
||||
* <p>{@code unixEpochTime} contains the suggested time. The {@code unixEpochTime.value} is the
|
||||
* number of milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system.
|
||||
* The {@code unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when
|
||||
* the {@code unixEpochTime.value} was established. Note that the elapsed realtime clock is
|
||||
* considered accurate but it is volatile, so time suggestions cannot be persisted across device
|
||||
* resets.
|
||||
*
|
||||
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
|
||||
* record why the suggestion exists and how it was determined. This information exists only to aid
|
||||
* in debugging and therefore is used by {@link #toString()}, but it is not for use in detection
|
||||
* logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
|
||||
* <p>See {@link TimeSuggestionHelper} for property information.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@@ -50,7 +38,9 @@ public final class NetworkTimeSuggestion implements Parcelable {
|
||||
public static final @NonNull Creator<NetworkTimeSuggestion> CREATOR =
|
||||
new Creator<NetworkTimeSuggestion>() {
|
||||
public NetworkTimeSuggestion createFromParcel(Parcel in) {
|
||||
return NetworkTimeSuggestion.createFromParcel(in);
|
||||
TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
|
||||
NetworkTimeSuggestion.class, in);
|
||||
return new NetworkTimeSuggestion(helper);
|
||||
}
|
||||
|
||||
public NetworkTimeSuggestion[] newArray(int size) {
|
||||
@@ -58,21 +48,15 @@ public final class NetworkTimeSuggestion implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull private final TimestampedValue<Long> mUnixEpochTime;
|
||||
@Nullable private ArrayList<String> mDebugInfo;
|
||||
@NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
|
||||
|
||||
public NetworkTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
|
||||
mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
|
||||
Objects.requireNonNull(unixEpochTime.getValue());
|
||||
mTimeSuggestionHelper = new TimeSuggestionHelper(
|
||||
NetworkTimeSuggestion.class, unixEpochTime);
|
||||
}
|
||||
|
||||
private static NetworkTimeSuggestion createFromParcel(Parcel in) {
|
||||
TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
|
||||
NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(unixEpochTime);
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
|
||||
suggestion.mDebugInfo = debugInfo;
|
||||
return suggestion;
|
||||
private NetworkTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
|
||||
mTimeSuggestionHelper = Objects.requireNonNull(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,35 +66,30 @@ public final class NetworkTimeSuggestion implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeParcelable(mUnixEpochTime, 0);
|
||||
dest.writeList(mDebugInfo);
|
||||
mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TimestampedValue<Long> getUnixEpochTime() {
|
||||
return mUnixEpochTime;
|
||||
return mTimeSuggestionHelper.getUnixEpochTime();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<String> getDebugInfo() {
|
||||
return mDebugInfo == null
|
||||
? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
|
||||
return mTimeSuggestionHelper.getDebugInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates information with the instance that can be useful for debugging / logging. The
|
||||
* information is present in {@link #toString()} but is not considered for
|
||||
* {@link #equals(Object)} and {@link #hashCode()}.
|
||||
* information is present in {@link #toString()} but is not considered for {@link
|
||||
* #equals(Object)} and {@link #hashCode()}.
|
||||
*/
|
||||
public void addDebugInfo(String... debugInfos) {
|
||||
if (mDebugInfo == null) {
|
||||
mDebugInfo = new ArrayList<>();
|
||||
}
|
||||
mDebugInfo.addAll(Arrays.asList(debugInfos));
|
||||
mTimeSuggestionHelper.addDebugInfo(debugInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@@ -118,19 +97,28 @@ public final class NetworkTimeSuggestion implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
NetworkTimeSuggestion that = (NetworkTimeSuggestion) o;
|
||||
return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mUnixEpochTime);
|
||||
return mTimeSuggestionHelper.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NetworkTimeSuggestion{"
|
||||
+ "mUnixEpochTime=" + mUnixEpochTime
|
||||
+ ", mDebugInfo=" + mDebugInfo
|
||||
+ '}';
|
||||
return mTimeSuggestionHelper.handleToString();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static NetworkTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
|
||||
throws IllegalArgumentException {
|
||||
return new NetworkTimeSuggestion(
|
||||
TimeSuggestionHelper.handleParseCommandLineArg(NetworkTimeSuggestion.class, cmd));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void printCommandLineOpts(PrintWriter pw) {
|
||||
TimeSuggestionHelper.handlePrintCommandLineOpts(pw, "Network", NetworkTimeSuggestion.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -88,6 +90,61 @@ public final class TelephonyTimeSuggestion implements Parcelable {
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static TelephonyTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
|
||||
throws IllegalArgumentException {
|
||||
Integer slotIndex = null;
|
||||
Long referenceTimeMillis = null;
|
||||
Long unixEpochTimeMillis = null;
|
||||
String opt;
|
||||
while ((opt = cmd.getNextArg()) != null) {
|
||||
switch (opt) {
|
||||
case "--slot_index": {
|
||||
slotIndex = Integer.parseInt(cmd.getNextArgRequired());
|
||||
break;
|
||||
}
|
||||
case "--reference_time": {
|
||||
referenceTimeMillis = Long.parseLong(cmd.getNextArgRequired());
|
||||
break;
|
||||
}
|
||||
case "--unix_epoch_time": {
|
||||
unixEpochTimeMillis = Long.parseLong(cmd.getNextArgRequired());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("Unknown option: " + opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slotIndex == null) {
|
||||
throw new IllegalArgumentException("No slotIndex specified.");
|
||||
}
|
||||
if (referenceTimeMillis == null) {
|
||||
throw new IllegalArgumentException("No referenceTimeMillis specified.");
|
||||
}
|
||||
if (unixEpochTimeMillis == null) {
|
||||
throw new IllegalArgumentException("No unixEpochTimeMillis specified.");
|
||||
}
|
||||
|
||||
TimestampedValue<Long> timeSignal =
|
||||
new TimestampedValue<>(referenceTimeMillis, unixEpochTimeMillis);
|
||||
Builder builder = new Builder(slotIndex)
|
||||
.setUnixEpochTime(timeSignal)
|
||||
.addDebugInfo("Command line injection");
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void printCommandLineOpts(PrintWriter pw) {
|
||||
pw.println("Telephony suggestion options:");
|
||||
pw.println(" --slot_index <number>");
|
||||
pw.println(" --reference_time <elapsed realtime millis>");
|
||||
pw.println(" --unix_epoch_time <Unix epoch time millis>");
|
||||
pw.println();
|
||||
pw.println("See " + TelephonyTimeSuggestion.class.getName() + " for more information");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
||||
@@ -43,6 +43,36 @@ public interface TimeDetector {
|
||||
*/
|
||||
String SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED = "is_auto_detection_enabled";
|
||||
|
||||
/**
|
||||
* A shell command that injects a manual time suggestion.
|
||||
* @hide
|
||||
*/
|
||||
String SHELL_COMMAND_SUGGEST_MANUAL_TIME = "suggest_manual_time";
|
||||
|
||||
/**
|
||||
* A shell command that injects a telephony time suggestion.
|
||||
* @hide
|
||||
*/
|
||||
String SHELL_COMMAND_SUGGEST_TELEPHONY_TIME = "suggest_telephony_time";
|
||||
|
||||
/**
|
||||
* A shell command that injects a network time suggestion.
|
||||
* @hide
|
||||
*/
|
||||
String SHELL_COMMAND_SUGGEST_NETWORK_TIME = "suggest_network_time";
|
||||
|
||||
/**
|
||||
* A shell command that injects a GNSS time suggestion.
|
||||
* @hide
|
||||
*/
|
||||
String SHELL_COMMAND_SUGGEST_GNSS_TIME = "suggest_gnss_time";
|
||||
|
||||
/**
|
||||
* A shell command that injects a external time suggestion.
|
||||
* @hide
|
||||
*/
|
||||
String SHELL_COMMAND_SUGGEST_EXTERNAL_TIME = "suggest_external_time";
|
||||
|
||||
/**
|
||||
* A shared utility method to create a {@link ManualTimeSuggestion}.
|
||||
*
|
||||
|
||||
209
core/java/android/app/timedetector/TimeSuggestionHelper.java
Normal file
209
core/java/android/app/timedetector/TimeSuggestionHelper.java
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.app.timedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A delegate class to support time suggestion classes that could diverge in the future. This class
|
||||
* exists purely for code re-use and provides support methods. It avoids class inheritance
|
||||
* deliberately to allow each suggestion to evolve in different directions later without affecting
|
||||
* SDK APIs.
|
||||
*
|
||||
* <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
|
||||
* milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system. The {@code
|
||||
* unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when the {@code
|
||||
* unixEpochTime.value} was established. Note that the elapsed realtime clock is considered accurate
|
||||
* but it is volatile, so time suggestions cannot be persisted across device resets.
|
||||
*
|
||||
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
|
||||
* record why the suggestion exists and how it was entered. This information exists only to aid in
|
||||
* debugging and therefore is used by {@link #toString()}, but it is not for use in detection
|
||||
* logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class TimeSuggestionHelper {
|
||||
|
||||
@NonNull private final Class<?> mHelpedClass;
|
||||
@NonNull private final TimestampedValue<Long> mUnixEpochTime;
|
||||
@Nullable private ArrayList<String> mDebugInfo;
|
||||
|
||||
/** Creates a helper for the specified class, containing the supplied properties. */
|
||||
public TimeSuggestionHelper(@NonNull Class<?> helpedClass,
|
||||
@NonNull TimestampedValue<Long> unixEpochTime) {
|
||||
mHelpedClass = Objects.requireNonNull(helpedClass);
|
||||
mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
|
||||
Objects.requireNonNull(unixEpochTime.getValue());
|
||||
}
|
||||
|
||||
/** See {@link TimeSuggestionHelper} for property details. */
|
||||
@NonNull
|
||||
public TimestampedValue<Long> getUnixEpochTime() {
|
||||
return mUnixEpochTime;
|
||||
}
|
||||
|
||||
/** See {@link TimeSuggestionHelper} for information about {@code debugInfo}. */
|
||||
@NonNull
|
||||
public List<String> getDebugInfo() {
|
||||
return mDebugInfo == null
|
||||
? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates information with the instance that can be useful for debugging / logging.
|
||||
*
|
||||
* <p>See {@link TimeSuggestionHelper} for more information about {@code debugInfo}.
|
||||
*/
|
||||
public void addDebugInfo(@NonNull String debugInfo) {
|
||||
if (mDebugInfo == null) {
|
||||
mDebugInfo = new ArrayList<>();
|
||||
}
|
||||
mDebugInfo.add(debugInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates information with the instance that can be useful for debugging / logging. The
|
||||
* information is present in {@link #toString()} but is not considered for
|
||||
* {@link #equals(Object)} and {@link #hashCode()}.
|
||||
*/
|
||||
public void addDebugInfo(String... debugInfos) {
|
||||
addDebugInfo(Arrays.asList(debugInfos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates information with the instance that can be useful for debugging / logging.
|
||||
*
|
||||
* <p>See {@link TimeSuggestionHelper} for more information about {@code debugInfo}.
|
||||
*/
|
||||
public void addDebugInfo(@NonNull List<String> debugInfo) {
|
||||
if (mDebugInfo == null) {
|
||||
mDebugInfo = new ArrayList<>(debugInfo.size());
|
||||
}
|
||||
mDebugInfo.addAll(debugInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented in case users call this insteam of {@link #handleEquals(TimeSuggestionHelper)}.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
TimeSuggestionHelper that = (TimeSuggestionHelper) o;
|
||||
return handleEquals(that);
|
||||
}
|
||||
|
||||
/** Used to implement {@link Object#equals(Object)}. */
|
||||
public boolean handleEquals(TimeSuggestionHelper o) {
|
||||
return Objects.equals(mHelpedClass, o.mHelpedClass)
|
||||
&& Objects.equals(mUnixEpochTime, o.mUnixEpochTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mUnixEpochTime);
|
||||
}
|
||||
|
||||
/** Used to implement {@link Object#toString()}. */
|
||||
public String handleToString() {
|
||||
return mHelpedClass.getSimpleName() + "{"
|
||||
+ "mUnixEpochTime=" + mUnixEpochTime
|
||||
+ ", mDebugInfo=" + mDebugInfo
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/** Constructs a helper with suggestion state from a Parcel. */
|
||||
public static TimeSuggestionHelper handleCreateFromParcel(@NonNull Class<?> helpedClass,
|
||||
@NonNull Parcel in) {
|
||||
@SuppressWarnings("unchecked")
|
||||
TimestampedValue<Long> unixEpochTime = in.readParcelable(
|
||||
null /* classLoader */, TimestampedValue.class);
|
||||
TimeSuggestionHelper suggestionHelper =
|
||||
new TimeSuggestionHelper(helpedClass, unixEpochTime);
|
||||
suggestionHelper.mDebugInfo = in.readArrayList(null /* classLoader */, String.class);
|
||||
return suggestionHelper;
|
||||
}
|
||||
|
||||
/** Writes the helper suggestion state to a Parcel. */
|
||||
public void handleWriteToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeParcelable(mUnixEpochTime, 0);
|
||||
dest.writeList(mDebugInfo);
|
||||
}
|
||||
|
||||
/** Parses command line args to create a {@link TimeSuggestionHelper}. */
|
||||
public static TimeSuggestionHelper handleParseCommandLineArg(
|
||||
@NonNull Class<?> helpedClass, @NonNull ShellCommand cmd)
|
||||
throws IllegalArgumentException {
|
||||
Long referenceTimeMillis = null;
|
||||
Long unixEpochTimeMillis = null;
|
||||
String opt;
|
||||
while ((opt = cmd.getNextArg()) != null) {
|
||||
switch (opt) {
|
||||
case "--reference_time": {
|
||||
referenceTimeMillis = Long.parseLong(cmd.getNextArgRequired());
|
||||
break;
|
||||
}
|
||||
case "--unix_epoch_time": {
|
||||
unixEpochTimeMillis = Long.parseLong(cmd.getNextArgRequired());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("Unknown option: " + opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (referenceTimeMillis == null) {
|
||||
throw new IllegalArgumentException("No referenceTimeMillis specified.");
|
||||
}
|
||||
if (unixEpochTimeMillis == null) {
|
||||
throw new IllegalArgumentException("No unixEpochTimeMillis specified.");
|
||||
}
|
||||
|
||||
TimestampedValue<Long> timeSignal =
|
||||
new TimestampedValue<>(referenceTimeMillis, unixEpochTimeMillis);
|
||||
TimeSuggestionHelper suggestionHelper = new TimeSuggestionHelper(helpedClass, timeSignal);
|
||||
suggestionHelper.addDebugInfo("Command line injection");
|
||||
return suggestionHelper;
|
||||
}
|
||||
|
||||
/** Prints the command line args needed to create a {@link TimeSuggestionHelper}. */
|
||||
public static void handlePrintCommandLineOpts(
|
||||
@NonNull PrintWriter pw, @NonNull String typeName, @NonNull Class<?> clazz) {
|
||||
pw.printf("%s suggestion options:\n", typeName);
|
||||
pw.println(" --reference_time <elapsed realtime millis>");
|
||||
pw.println(" --unix_epoch_time <Unix epoch time millis>");
|
||||
pw.println();
|
||||
pw.println("See " + clazz.getName() + " for more information");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2022 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.app.time;
|
||||
|
||||
import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.os.ShellCommand;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests for non-SDK methods on {@link ExternalTimeSuggestion}.
|
||||
* Also see {@link android.app.time.cts.ExternalTimeSuggestionTest}
|
||||
*/
|
||||
public class ExternalTimeSuggestionTest {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noReferenceTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--unix_epoch_time 12345");
|
||||
ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noUnixEpochTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321");
|
||||
ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCommandLineArg_validSuggestion() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345");
|
||||
ExternalTimeSuggestion expectedSuggestion = new ExternalTimeSuggestion(54321L, 12345L);
|
||||
ExternalTimeSuggestion actualSuggestion =
|
||||
ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
assertEquals(expectedSuggestion, actualSuggestion);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_unknownArgument() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
|
||||
ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
}
|
||||
@@ -18,10 +18,12 @@ package android.app.timedetector;
|
||||
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
|
||||
import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -63,4 +65,36 @@ public class GnssTimeSuggestionTest {
|
||||
GnssTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
|
||||
assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noReferenceTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--unix_epoch_time 12345");
|
||||
GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noUnixEpochTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321");
|
||||
GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCommandLineArg_validSuggestion() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345");
|
||||
TimestampedValue<Long> timeSignal = new TimestampedValue<>(54321L, 12345L);
|
||||
GnssTimeSuggestion expectedSuggestion = new GnssTimeSuggestion(timeSignal);
|
||||
GnssTimeSuggestion actualSuggestion =
|
||||
GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
assertEquals(expectedSuggestion, actualSuggestion);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_unknownArgument() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
|
||||
GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ package android.app.timedetector;
|
||||
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
|
||||
import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -63,4 +65,36 @@ public class ManualTimeSuggestionTest {
|
||||
ManualTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
|
||||
assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noReferenceTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--unix_epoch_time 12345");
|
||||
ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noUnixEpochTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321");
|
||||
ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCommandLineArg_validSuggestion() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345");
|
||||
TimestampedValue<Long> timeSignal = new TimestampedValue<>(54321L, 12345L);
|
||||
ManualTimeSuggestion expectedSuggestion = new ManualTimeSuggestion(timeSignal);
|
||||
ManualTimeSuggestion actualSuggestion =
|
||||
ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
assertEquals(expectedSuggestion, actualSuggestion);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_unknownArgument() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
|
||||
ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ package android.app.timedetector;
|
||||
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
|
||||
import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -63,4 +65,36 @@ public class NetworkTimeSuggestionTest {
|
||||
NetworkTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
|
||||
assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noReferenceTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--unix_epoch_time 12345");
|
||||
NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noUnixEpochTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321");
|
||||
NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCommandLineArg_validSuggestion() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345");
|
||||
TimestampedValue<Long> timeSignal = new TimestampedValue<>(54321L, 12345L);
|
||||
NetworkTimeSuggestion expectedSuggestion = new NetworkTimeSuggestion(timeSignal);
|
||||
NetworkTimeSuggestion actualSuggestion =
|
||||
NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
assertEquals(expectedSuggestion, actualSuggestion);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_unknownArgument() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
|
||||
NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ package android.app.timedetector;
|
||||
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
|
||||
import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import android.os.ShellCommand;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -95,4 +97,45 @@ public class TelephonyTimeSuggestionTest {
|
||||
assertEquals(suggestion1.getDebugInfo(), rtSuggestion1.getDebugInfo());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noSlotIndex() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--reference_time 54321 --unix_epoch_time 12345");
|
||||
TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noReferenceTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--slot_index 0 --unix_epoch_time 12345");
|
||||
TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_noUnixEpochTime() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--slot_index 0 --reference_time 54321");
|
||||
TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCommandLineArg_validSuggestion() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--slot_index 0 --reference_time 54321 --unix_epoch_time 12345");
|
||||
TelephonyTimeSuggestion expectedSuggestion =
|
||||
new TelephonyTimeSuggestion.Builder(0)
|
||||
.setUnixEpochTime(new TimestampedValue<>(54321L, 12345L))
|
||||
.build();
|
||||
TelephonyTimeSuggestion actualSuggestion =
|
||||
TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
assertEquals(expectedSuggestion, actualSuggestion);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testParseCommandLineArg_unknownArgument() {
|
||||
ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
|
||||
"--slot_index 0 --reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
|
||||
TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,14 +26,14 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/** Utility methods related to {@link ShellCommand} objects used in several tests. */
|
||||
final class ShellCommandTestSupport {
|
||||
public final class ShellCommandTestSupport {
|
||||
private ShellCommandTestSupport() {}
|
||||
|
||||
static ShellCommand createShellCommandWithArgsAndOptions(String argsWithSpaces) {
|
||||
public static ShellCommand createShellCommandWithArgsAndOptions(String argsWithSpaces) {
|
||||
return createShellCommandWithArgsAndOptions(Arrays.asList(argsWithSpaces.split(" ")));
|
||||
}
|
||||
|
||||
static ShellCommand createShellCommandWithArgsAndOptions(List<String> args) {
|
||||
public static ShellCommand createShellCommandWithArgsAndOptions(List<String> args) {
|
||||
ShellCommand command = mock(ShellCommand.class);
|
||||
class ArgProvider {
|
||||
private int mCount;
|
||||
|
||||
@@ -478,6 +478,12 @@
|
||||
<uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
|
||||
<uses-permission android:name="android.permission.SUGGEST_EXTERNAL_TIME" />
|
||||
|
||||
<!-- Permissions used for manual testing of time detection behavior. -->
|
||||
<uses-permission android:name="android.permission.SUGGEST_MANUAL_TIME" />
|
||||
<uses-permission android:name="android.permission.SUGGEST_TELEPHONY_TIME" />
|
||||
<uses-permission android:name="android.permission.SUGGEST_NETWORK_TIME" />
|
||||
<uses-permission android:name="android.permission.SUGGEST_GNSS_TIME" />
|
||||
|
||||
<!-- Permission required for CTS test - android.server.biometrics -->
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.app.AlarmManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
@@ -166,6 +167,11 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
|
||||
mWakeLock.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deviceHasY2038Issue() {
|
||||
return Build.SUPPORTED_32_BIT_ABIS.length > 0;
|
||||
}
|
||||
|
||||
private void checkWakeLockHeld() {
|
||||
if (!mWakeLock.isHeld()) {
|
||||
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " not held");
|
||||
|
||||
@@ -17,14 +17,26 @@ package com.android.server.timedetector;
|
||||
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_EXTERNAL_TIME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_GNSS_TIME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_MANUAL_TIME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_NETWORK_TIME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_TELEPHONY_TIME;
|
||||
import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
|
||||
|
||||
import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE;
|
||||
import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE;
|
||||
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.timedetector.GnssTimeSuggestion;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.app.timedetector.NetworkTimeSuggestion;
|
||||
import android.app.timedetector.TelephonyTimeSuggestion;
|
||||
import android.os.ShellCommand;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/** Implements the shell command interface for {@link TimeDetectorService}. */
|
||||
class TimeDetectorShellCommand extends ShellCommand {
|
||||
@@ -44,6 +56,16 @@ class TimeDetectorShellCommand extends ShellCommand {
|
||||
switch (cmd) {
|
||||
case SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED:
|
||||
return runIsAutoDetectionEnabled();
|
||||
case SHELL_COMMAND_SUGGEST_MANUAL_TIME:
|
||||
return runSuggestManualTime();
|
||||
case SHELL_COMMAND_SUGGEST_TELEPHONY_TIME:
|
||||
return runSuggestTelephonyTime();
|
||||
case SHELL_COMMAND_SUGGEST_NETWORK_TIME:
|
||||
return runSuggestNetworkTime();
|
||||
case SHELL_COMMAND_SUGGEST_GNSS_TIME:
|
||||
return runSuggestGnssTime();
|
||||
case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME:
|
||||
return runSuggestExternalTime();
|
||||
default: {
|
||||
return handleDefaultCommands(cmd);
|
||||
}
|
||||
@@ -59,6 +81,53 @@ class TimeDetectorShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runSuggestManualTime() {
|
||||
return runSuggestTime(
|
||||
() -> ManualTimeSuggestion.parseCommandLineArg(this),
|
||||
mInterface::suggestManualTime);
|
||||
}
|
||||
|
||||
private int runSuggestTelephonyTime() {
|
||||
return runSuggestTime(
|
||||
() -> TelephonyTimeSuggestion.parseCommandLineArg(this),
|
||||
mInterface::suggestTelephonyTime);
|
||||
}
|
||||
|
||||
private int runSuggestNetworkTime() {
|
||||
return runSuggestTime(
|
||||
() -> NetworkTimeSuggestion.parseCommandLineArg(this),
|
||||
mInterface::suggestNetworkTime);
|
||||
}
|
||||
|
||||
private int runSuggestGnssTime() {
|
||||
return runSuggestTime(
|
||||
() -> GnssTimeSuggestion.parseCommandLineArg(this),
|
||||
mInterface::suggestGnssTime);
|
||||
}
|
||||
|
||||
private int runSuggestExternalTime() {
|
||||
return runSuggestTime(
|
||||
() -> ExternalTimeSuggestion.parseCommandLineArg(this),
|
||||
mInterface::suggestExternalTime);
|
||||
}
|
||||
|
||||
private <T> int runSuggestTime(Supplier<T> suggestionParser, Consumer<T> invoker) {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
try {
|
||||
T suggestion = suggestionParser.get();
|
||||
if (suggestion == null) {
|
||||
pw.println("Error: suggestion not specified");
|
||||
return 1;
|
||||
}
|
||||
invoker.accept(suggestion);
|
||||
pw.println("Suggestion " + suggestion + " injected.");
|
||||
return 0;
|
||||
} catch (RuntimeException e) {
|
||||
pw.println(e);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHelp() {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
@@ -68,6 +137,22 @@ class TimeDetectorShellCommand extends ShellCommand {
|
||||
pw.printf(" %s\n", SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED);
|
||||
pw.printf(" Prints true/false according to the automatic time detection setting.\n");
|
||||
pw.println();
|
||||
pw.printf(" %s <manual suggestion opts>\n", SHELL_COMMAND_SUGGEST_MANUAL_TIME);
|
||||
pw.printf(" %s <telephony suggestion opts>\n", SHELL_COMMAND_SUGGEST_TELEPHONY_TIME);
|
||||
pw.printf(" %s <network suggestion opts>\n", SHELL_COMMAND_SUGGEST_NETWORK_TIME);
|
||||
pw.printf(" %s <gnss suggestion opts>\n", SHELL_COMMAND_SUGGEST_GNSS_TIME);
|
||||
pw.printf(" %s <external suggestion opts>\n", SHELL_COMMAND_SUGGEST_EXTERNAL_TIME);
|
||||
pw.println();
|
||||
ManualTimeSuggestion.printCommandLineOpts(pw);
|
||||
pw.println();
|
||||
TelephonyTimeSuggestion.printCommandLineOpts(pw);
|
||||
pw.println();
|
||||
NetworkTimeSuggestion.printCommandLineOpts(pw);
|
||||
pw.println();
|
||||
GnssTimeSuggestion.printCommandLineOpts(pw);
|
||||
pw.println();
|
||||
ExternalTimeSuggestion.printCommandLineOpts(pw);
|
||||
pw.println();
|
||||
pw.printf("This service is also affected by the following device_config flags in the"
|
||||
+ " %s namespace:\n", NAMESPACE_SYSTEM_TIME);
|
||||
pw.printf(" %s\n", KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE);
|
||||
|
||||
@@ -85,6 +85,9 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
*/
|
||||
private static final int KEEP_SUGGESTION_HISTORY_SIZE = 10;
|
||||
|
||||
/** The value in Unix epoch milliseconds of the Y2038 issue. */
|
||||
private static final long Y2038_LIMIT_IN_MILLIS = 1000L * Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* A log that records the decisions / decision metadata that affected the device's system clock
|
||||
* time. This is logged in bug reports to assist with debugging issues with detection.
|
||||
@@ -185,6 +188,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
|
||||
/** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
|
||||
void releaseWakeLock();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the device may be at risk of time_t overflow (because bionic
|
||||
* defines time_t as a 32-bit signed integer for 32-bit processes).
|
||||
*/
|
||||
boolean deviceHasY2038Issue();
|
||||
}
|
||||
|
||||
static TimeDetectorStrategy create(
|
||||
@@ -333,6 +342,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
.mapToObj(TimeDetectorStrategy::originToString)
|
||||
.collect(joining(",", "[", "]"));
|
||||
ipw.println("mEnvironment.autoOriginPriorities()=" + priorities);
|
||||
ipw.println("mEnvironment.deviceHasY2038Issue()=" + mEnvironment.deviceHasY2038Issue());
|
||||
|
||||
ipw.println("Time change log:");
|
||||
ipw.increaseIndent(); // level 2
|
||||
@@ -413,6 +423,16 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
+ ", suggestion=" + suggestion);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newUnixEpochTime.getValue() > Y2038_LIMIT_IN_MILLIS
|
||||
&& mEnvironment.deviceHasY2038Issue()) {
|
||||
// This check won't prevent a device's system clock exceeding Integer.MAX_VALUE Unix
|
||||
// seconds through the normal passage of time, but it will stop it jumping above 2038
|
||||
// because of a "bad" suggestion. b/204193177
|
||||
Slog.w(LOG_TAG, "Suggested value is above max time supported by this device."
|
||||
+ " suggestion=" + suggestion);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1131,6 +1131,49 @@ public class TimeDetectorStrategyImplTest {
|
||||
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void manualY2038SuggestionsAreRejectedOnAffectedDevices() {
|
||||
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
|
||||
.pokeAutoTimeDetectionEnabled(false)
|
||||
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
|
||||
.pokeDeviceHasY2038Issues(true);
|
||||
|
||||
Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
|
||||
ManualTimeSuggestion timeSuggestion = mScript.generateManualTimeSuggestion(y2038IssueTime);
|
||||
mScript.simulateManualTimeSuggestion(timeSuggestion, false /* expectedResult */)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void telephonyY2038SuggestionsAreRejectedOnAffectedDevices() {
|
||||
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
|
||||
.pokeAutoTimeDetectionEnabled(true)
|
||||
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
|
||||
.pokeDeviceHasY2038Issues(true);
|
||||
|
||||
final int slotIndex = 0;
|
||||
Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
mScript.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
|
||||
mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void telephonyY2038SuggestionsAreNotRejectedOnUnaffectedDevices() {
|
||||
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
|
||||
.pokeAutoTimeDetectionEnabled(true)
|
||||
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
|
||||
.pokeDeviceHasY2038Issues(false);
|
||||
|
||||
final int slotIndex = 0;
|
||||
Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
mScript.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
|
||||
mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockWasSetAndResetCallTracking(y2038IssueTime.toEpochMilli());
|
||||
}
|
||||
|
||||
/**
|
||||
* A fake implementation of {@link TimeDetectorStrategyImpl.Environment}. Besides tracking
|
||||
* changes and behaving like the real thing should, it also asserts preconditions.
|
||||
@@ -1143,6 +1186,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
private int mSystemClockUpdateThresholdMillis = 2000;
|
||||
private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY;
|
||||
private ConfigurationChangeListener mConfigChangeListener;
|
||||
private boolean mDeviceHas2038Issues = false;
|
||||
|
||||
// Tracking operations.
|
||||
private boolean mSystemClockWasSet;
|
||||
@@ -1208,6 +1252,15 @@ public class TimeDetectorStrategyImplTest {
|
||||
mWakeLockAcquired = false;
|
||||
}
|
||||
|
||||
public void setDeviceHas2038Issues(boolean hasIssues) {
|
||||
mDeviceHas2038Issues = hasIssues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deviceHasY2038Issue() {
|
||||
return mDeviceHas2038Issues;
|
||||
}
|
||||
|
||||
// Methods below are for managing the fake's behavior.
|
||||
|
||||
void pokeSystemClockUpdateThreshold(int thresholdMillis) {
|
||||
@@ -1304,6 +1357,11 @@ public class TimeDetectorStrategyImplTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
Script pokeDeviceHasY2038Issues(boolean hasIssues) {
|
||||
mFakeEnvironment.setDeviceHas2038Issues(hasIssues);
|
||||
return this;
|
||||
}
|
||||
|
||||
long peekElapsedRealtimeMillis() {
|
||||
return mFakeEnvironment.peekElapsedRealtimeMillis();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user