Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4d26ca3 authored by Mustafa Acer's avatar Mustafa Acer
Browse files

Move suggestExternalTime to TimeManager

This CL moves suggestExternalTime method from TimeDetector to
TimeManager. Eventual goal is to make suggestExternalTime a System
API. Ideally all time related system APIs live in android.app.time
hence the move.

Test: atest android.app.time
Change-Id: I464545e77fdf68c35c8a338bfe5ac8b7535bc3e6
Bug: 177079827
parent 377af2a8
Loading
Loading
Loading
Loading
+44 −25
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.app.time;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -31,9 +33,9 @@ import java.util.Objects;
/**
 * A time signal from an External source.
 *
 * External time suggestions are for use in situations where the Android device is part of a wider
 * network of devices that are required to use a single time source, and where authority for the
 * time is external to the Android device. For example, for the Android Auto use case where the
 * <p>External time suggestions are for use in situations where the Android device is part of a
 * wider network of devices that are required to use a single time source, and where authority for
 * the time is external to the Android device. For example, for the Android Auto use case where the
 * Android device is part of a wider in-car network of devices that should display the same time.
 *
 * <p>Android allows for a single external source for time. If there are several external sources
@@ -49,19 +51,19 @@ import java.util.Objects;
 * capture the elapsed realtime reference clock, e.g. via {@link SystemClock#elapsedRealtime()},
 * when the UTC time is first obtained (usually under a wakelock). This enables Android to adjust
 * for latency introduced between suggestion creation and eventual use. Adjustments for other
 * sources of latency, i.e. those before the external time suggestion is created, must be handled
 * by the creator.
 * sources of latency, i.e. those before the external time suggestion is created, must be handled by
 * the creator.
 *
 * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
 * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
 * elapsed realtime clock when the {@code utcTime.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 elapsedRealtimeMillis} and {@code suggestionMillis} represent the suggested time.
 * {@code suggestionMillis} is the number of milliseconds elapsed since 1/1/1970 00:00:00 UTC.
 * {@code elapsedRealtimeMillis} is the value of the elapsed realtime clock when {@code
 * suggestionMillis} 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)}.
 * 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
 */
@@ -78,17 +80,28 @@ public final class ExternalTimeSuggestion implements Parcelable {
                }
            };

    @NonNull private final TimestampedValue<Long> mUtcTime;
    @Nullable private ArrayList<String> mDebugInfo;
    @NonNull
    private final TimestampedValue<Long> mUtcTime;
    @Nullable
    private ArrayList<String> mDebugInfo;

    public ExternalTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
        mUtcTime = Objects.requireNonNull(utcTime);
        Objects.requireNonNull(utcTime.getValue());
    /**
     * Creates a time suggestion cross-referenced to the elapsed realtime clock. See {@link
     * ExternalTimeSuggestion} for more details.
     *
     * @param elapsedRealtimeMillis the elapsed realtime clock reference for the suggestion
     * @param suggestionMillis      the suggested UTC time in milliseconds since the start of the
     *                              Unix epoch
     */
    public ExternalTimeSuggestion(@ElapsedRealtimeLong long elapsedRealtimeMillis,
            @CurrentTimeMillisLong long suggestionMillis) {
        mUtcTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
    }

    private static ExternalTimeSuggestion createFromParcel(Parcel in) {
        TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
        ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(utcTime);
        ExternalTimeSuggestion suggestion =
                new ExternalTimeSuggestion(utcTime.getReferenceTimeMillis(), utcTime.getValue());
        @SuppressWarnings("unchecked")
        ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
        suggestion.mDebugInfo = debugInfo;
@@ -106,23 +119,31 @@ public final class ExternalTimeSuggestion implements Parcelable {
        dest.writeList(mDebugInfo);
    }

    /**
     * {@hide}
     */
    @NonNull
    public TimestampedValue<Long> getUtcTime() {
        return mUtcTime;
    }

    /**
     * Returns information that can be useful for debugging / logging. See {@link #addDebugInfo}.
     * {@hide}
     */
    @NonNull
    public List<String> getDebugInfo() {
        return mDebugInfo == null
                ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
                ? Collections.emptyList()
                : Collections.unmodifiableList(mDebugInfo);
    }

    /**
     * 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) {
    public void addDebugInfo(@NonNull String... debugInfos) {
        if (mDebugInfo == null) {
            mDebugInfo = new ArrayList<>();
        }
@@ -148,9 +169,7 @@ public final class ExternalTimeSuggestion implements Parcelable {

    @Override
    public String toString() {
        return "ExternalTimeSuggestion{"
                + "mUtcTime=" + mUtcTime
                + ", mDebugInfo=" + mDebugInfo
        return "ExternalTimeSuggestion{" + "mUtcTime=" + mUtcTime + ", mDebugInfo=" + mDebugInfo
                + '}';
    }
}
+23 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.timedetector.ITimeDetectorService;
import android.app.timezonedetector.ITimeZoneDetectorService;
import android.content.Context;
import android.os.RemoteException;
@@ -45,6 +46,7 @@ public final class TimeManager {

    private final Object mLock = new Object();
    private final ITimeZoneDetectorService mITimeZoneDetectorService;
    private final ITimeDetectorService mITimeDetectorService;

    @GuardedBy("mLock")
    private ITimeZoneDetectorListener mTimeZoneDetectorReceiver;
@@ -62,6 +64,8 @@ public final class TimeManager {
        // internal refactoring.
        mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
                ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
        mITimeDetectorService = ITimeDetectorService.Stub.asInterface(
                ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE));
    }

    /**
@@ -214,4 +218,23 @@ public final class TimeManager {
            }
        }
    }

    /**
     * Suggests the current time from an external time source. For example, a form factor-specific
     * HAL. This time <em>may</em> be used to set the device system clock, depending on the device
     * configuration and user settings. This method call is processed asynchronously.
     * See {@link ExternalTimeSuggestion} for more details.
     * {@hide}
     */
    @RequiresPermission(android.Manifest.permission.SET_TIME)
    public void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
        if (DEBUG) {
            Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
        }
        try {
            mITimeDetectorService.suggestExternalTime(timeSuggestion);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
+0 −9
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package android.app.timedetector;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.app.time.ExternalTimeSuggestion;
import android.content.Context;
import android.os.SystemClock;
import android.os.TimestampedValue;
@@ -80,12 +79,4 @@ public interface TimeDetector {
     */
    @RequiresPermission(android.Manifest.permission.SET_TIME)
    void suggestGnssTime(GnssTimeSuggestion timeSuggestion);

    /**
     * Suggests the time according to an external time source (form factor specific HAL, etc).
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.SET_TIME)
    void suggestExternalTime(ExternalTimeSuggestion timeSuggestion);
}
+0 −13
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package android.app.timedetector;

import android.annotation.NonNull;
import android.app.time.ExternalTimeSuggestion;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -87,16 +86,4 @@ public final class TimeDetectorImpl implements TimeDetector {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    public void suggestExternalTime(ExternalTimeSuggestion timeSuggestion) {
        if (DEBUG) {
            Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
        }
        try {
            mITimeDetectorService.suggestExternalTime(timeSuggestion);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
+10 −5
Original line number Diff line number Diff line
@@ -33,17 +33,20 @@ public class ExternalTimeSuggestionTest {

    @Test
    public void testEquals() {
        ExternalTimeSuggestion one = new ExternalTimeSuggestion(ARBITRARY_TIME);
        ExternalTimeSuggestion one = new ExternalTimeSuggestion(
                ARBITRARY_TIME.getReferenceTimeMillis(),
                ARBITRARY_TIME.getValue());
        assertEquals(one, one);

        ExternalTimeSuggestion two = new ExternalTimeSuggestion(ARBITRARY_TIME);
        ExternalTimeSuggestion two = new ExternalTimeSuggestion(
                ARBITRARY_TIME.getReferenceTimeMillis(),
                ARBITRARY_TIME.getValue());
        assertEquals(one, two);
        assertEquals(two, one);

        TimestampedValue<Long> differentTime = new TimestampedValue<>(
        ExternalTimeSuggestion three = new ExternalTimeSuggestion(
                ARBITRARY_TIME.getReferenceTimeMillis() + 1,
                ARBITRARY_TIME.getValue());
        ExternalTimeSuggestion three = new ExternalTimeSuggestion(differentTime);
        assertNotEquals(one, three);
        assertNotEquals(three, one);

@@ -55,7 +58,9 @@ public class ExternalTimeSuggestionTest {

    @Test
    public void testParcelable() {
        ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(ARBITRARY_TIME);
        ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(
                ARBITRARY_TIME.getReferenceTimeMillis(),
                ARBITRARY_TIME.getValue());
        assertRoundTripParcelable(suggestion);

        // DebugInfo should also be stored (but is not checked by equals())
Loading