Make ReferenceWithHistory output easier to use
Make ReferenceWithHistory easier to use by outputting a timestamp for each set() operation, and providing a stable "set id" for historic entries. This means consecutive dump() calls will assign the same ID to the same historic entry, enabling easier comparison. This doesn't change the contract of the storage, just the dump() output. Test: treehugger Bug: 149014708 Change-Id: I28919a25b09b70910873c40562b51fa6664103b0
This commit is contained in:
@@ -19,8 +19,11 @@ package com.android.server.timezonedetector;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.SystemClock;
|
||||
import android.os.TimestampedValue;
|
||||
import android.util.IndentingPrintWriter;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
/**
|
||||
@@ -49,18 +52,15 @@ import java.util.ArrayDeque;
|
||||
*/
|
||||
public final class ReferenceWithHistory<V> {
|
||||
|
||||
private static final Object NULL_MARKER = "{null marker}";
|
||||
|
||||
/** The maximum number of references to store. */
|
||||
private final int mMaxHistorySize;
|
||||
|
||||
/**
|
||||
* The history storage. Note that ArrayDeque doesn't support {@code null} so this stores Object
|
||||
* and not V. Use {@link #packNullIfRequired(Object)} and {@link #unpackNullIfRequired(Object)}
|
||||
* to convert to / from the storage object.
|
||||
*/
|
||||
/** The number of times {@link #set(Object)} has been called. */
|
||||
private int mSetCount;
|
||||
|
||||
/** The history storage. */
|
||||
@Nullable
|
||||
private ArrayDeque<Object> mValues;
|
||||
private ArrayDeque<TimestampedValue<V>> mValues;
|
||||
|
||||
/**
|
||||
* Creates an instance that records, at most, the specified number of values.
|
||||
@@ -78,8 +78,8 @@ public final class ReferenceWithHistory<V> {
|
||||
if (mValues == null || mValues.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Object value = mValues.getFirst();
|
||||
return unpackNullIfRequired(value);
|
||||
TimestampedValue<V> valueHolder = mValues.getFirst();
|
||||
return valueHolder.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,8 +98,10 @@ public final class ReferenceWithHistory<V> {
|
||||
|
||||
V previous = get();
|
||||
|
||||
Object nullSafeValue = packNullIfRequired(newValue);
|
||||
mValues.addFirst(nullSafeValue);
|
||||
TimestampedValue<V> valueHolder =
|
||||
new TimestampedValue<>(SystemClock.elapsedRealtime(), newValue);
|
||||
mValues.addFirst(valueHolder);
|
||||
mSetCount++;
|
||||
return previous;
|
||||
}
|
||||
|
||||
@@ -110,10 +112,13 @@ public final class ReferenceWithHistory<V> {
|
||||
if (mValues == null) {
|
||||
ipw.println("{Empty}");
|
||||
} else {
|
||||
int i = 0;
|
||||
for (Object value : mValues) {
|
||||
ipw.println(i + ": " + unpackNullIfRequired(value));
|
||||
i++;
|
||||
int i = mSetCount;
|
||||
for (TimestampedValue<V> valueHolder : mValues) {
|
||||
ipw.print(--i);
|
||||
ipw.print("@");
|
||||
ipw.print(Duration.ofMillis(valueHolder.getReferenceTimeMillis()).toString());
|
||||
ipw.print(": ");
|
||||
ipw.println(valueHolder.getValue());
|
||||
}
|
||||
}
|
||||
ipw.flush();
|
||||
@@ -130,23 +135,4 @@ public final class ReferenceWithHistory<V> {
|
||||
public String toString() {
|
||||
return String.valueOf(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a non-nullable Object into a nullable value. See also
|
||||
* {@link #packNullIfRequired(Object)}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private V unpackNullIfRequired(@NonNull Object value) {
|
||||
return value == NULL_MARKER ? null : (V) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a nullable value into a non-nullable Object. See also
|
||||
* {@link #unpackNullIfRequired(Object)}.
|
||||
*/
|
||||
@NonNull
|
||||
private Object packNullIfRequired(@Nullable V value) {
|
||||
return value == null ? NULL_MARKER : value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user