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

Commit 3150e580 authored by Neil Fuller's avatar Neil Fuller Committed by android-build-merger
Browse files

Merge "Make TimeDetectorService more aware of origin"

am: 4ef2551d

Change-Id: I27866cf74b779bb0040f4ace384207047ca6838f
parents 81bad0f3 4ef2551d
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -16,10 +16,10 @@

package android.app.timedetector;

import android.app.timedetector.TimeSignal;
import android.app.timedetector.PhoneTimeSuggestion;

/**
 * System private API to comunicate with time detector service.
 * System private API to communicate with time detector service.
 *
 * <p>Used by parts of the Android system with signals associated with the device's time to provide
 * information to the Time Detector Service.
@@ -32,5 +32,5 @@ import android.app.timedetector.TimeSignal;
 * {@hide}
 */
interface ITimeDetectorService {
  void suggestTime(in TimeSignal timeSignal);
  void suggestPhoneTime(in PhoneTimeSuggestion timeSuggestion);
}
+1 −1
Original line number Diff line number Diff line
@@ -16,4 +16,4 @@

package android.app.timedetector;

parcelable TimeSignal;
 No newline at end of file
parcelable PhoneTimeSuggestion;
+137 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 * Copyright (C) 2019 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.
@@ -17,47 +17,57 @@
package android.app.timedetector;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.TimestampedValue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * A time signal from a named source. The value consists of the number of milliseconds elapsed since
 * 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number was
 * established. The elapsed realtime clock is considered accurate but volatile, so time signals
 * A time signal from a telephony source. The value consists of the number of milliseconds elapsed
 * since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number
 * was established. The elapsed realtime clock is considered accurate but volatile, so time signals
 * must not be persisted across device resets.
 *
 * @hide
 */
public final class TimeSignal implements Parcelable {
public final class PhoneTimeSuggestion implements Parcelable {

    public static final @android.annotation.NonNull Parcelable.Creator<TimeSignal> CREATOR =
            new Parcelable.Creator<TimeSignal>() {
                public TimeSignal createFromParcel(Parcel in) {
                    return TimeSignal.createFromParcel(in);
    public static final @NonNull Parcelable.Creator<PhoneTimeSuggestion> CREATOR =
            new Parcelable.Creator<PhoneTimeSuggestion>() {
                public PhoneTimeSuggestion createFromParcel(Parcel in) {
                    return PhoneTimeSuggestion.createFromParcel(in);
                }

                public TimeSignal[] newArray(int size) {
                    return new TimeSignal[size];
                public PhoneTimeSuggestion[] newArray(int size) {
                    return new PhoneTimeSuggestion[size];
                }
            };

    public static final String SOURCE_ID_NITZ = "nitz";

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

    public TimeSignal(String sourceId, TimestampedValue<Long> utcTime) {
        mSourceId = Objects.requireNonNull(sourceId);
    public PhoneTimeSuggestion(int phoneId, @NonNull TimestampedValue<Long> utcTime) {
        mPhoneId = phoneId;
        mUtcTime = Objects.requireNonNull(utcTime);
    }

    private static TimeSignal createFromParcel(Parcel in) {
        String sourceId = in.readString();
    private static PhoneTimeSuggestion createFromParcel(Parcel in) {
        int phoneId = in.readInt();
        TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
        return new TimeSignal(sourceId, utcTime);
        PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId, utcTime);
        @SuppressWarnings("unchecked")
        ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
        suggestion.mDebugInfo = debugInfo;
        return suggestion;
    }

    @Override
@@ -67,13 +77,13 @@ public final class TimeSignal implements Parcelable {

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeString(mSourceId);
        dest.writeInt(mPhoneId);
        dest.writeParcelable(mUtcTime, 0);
        dest.writeList(mDebugInfo);
    }

    @NonNull
    public String getSourceId() {
        return mSourceId;
    public int getPhoneId() {
        return mPhoneId;
    }

    @NonNull
@@ -81,6 +91,23 @@ public final class TimeSignal implements Parcelable {
        return mUtcTime;
    }

    @NonNull
    public List<String> getDebugInfo() {
        return 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()}.
     */
    public void addDebugInfo(String... debugInfos) {
        if (mDebugInfo == null) {
            mDebugInfo = new ArrayList<>();
        }
        mDebugInfo.addAll(Arrays.asList(debugInfos));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
@@ -89,21 +116,22 @@ public final class TimeSignal implements Parcelable {
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        TimeSignal that = (TimeSignal) o;
        return Objects.equals(mSourceId, that.mSourceId)
        PhoneTimeSuggestion that = (PhoneTimeSuggestion) o;
        return mPhoneId == that.mPhoneId
                && Objects.equals(mUtcTime, that.mUtcTime);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mSourceId, mUtcTime);
        return Objects.hash(mPhoneId, mUtcTime);
    }

    @Override
    public String toString() {
        return "TimeSignal{"
                + "mSourceId='" + mSourceId + '\''
        return "PhoneTimeSuggestion{"
                + "mPhoneId='" + mPhoneId + '\''
                + ", mUtcTime=" + mUtcTime
                + ", mDebugInfo=" + mDebugInfo
                + '}';
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -45,12 +45,12 @@ public final class TimeDetector {
     * signals are available such as those that come from more reliable sources or were
     * determined more recently.
     */
    public void suggestTime(@NonNull TimeSignal timeSignal) {
    public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
        if (DEBUG) {
            Log.d(TAG, "suggestTime called: " + timeSignal);
            Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion);
        }
        try {
            mITimeDetectorService.suggestTime(timeSignal);
            mITimeDetectorService.suggestPhoneTime(timeSuggestion);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.TimestampedValue;

import org.junit.Test;

public class PhoneTimeSuggestionTest {
    private static final int PHONE_ID = 99999;

    @Test
    public void testEquals() {
        PhoneTimeSuggestion one =
                new PhoneTimeSuggestion(PHONE_ID, new TimestampedValue<>(1111L, 2222L));
        assertEquals(one, one);

        PhoneTimeSuggestion two =
                new PhoneTimeSuggestion(PHONE_ID, new TimestampedValue<>(1111L, 2222L));
        assertEquals(one, two);
        assertEquals(two, one);

        PhoneTimeSuggestion three =
                new PhoneTimeSuggestion(PHONE_ID + 1, new TimestampedValue<>(1111L, 2222L));
        assertNotEquals(one, three);
        assertNotEquals(three, one);

        // DebugInfo must not be considered in equals().
        one.addDebugInfo("Debug info 1");
        two.addDebugInfo("Debug info 2");
        assertEquals(one, two);
    }

    @Test
    public void testParcelable() {
        PhoneTimeSuggestion one =
                new PhoneTimeSuggestion(PHONE_ID, new TimestampedValue<>(1111L, 2222L));
        assertEquals(one, roundTripParcelable(one));

        // DebugInfo should also be stored (but is not checked by equals()
        one.addDebugInfo("This is debug info");
        PhoneTimeSuggestion two = roundTripParcelable(one);
        assertEquals(one.getDebugInfo(), two.getDebugInfo());
    }

    @SuppressWarnings("unchecked")
    private static <T extends Parcelable> T roundTripParcelable(T one) {
        Parcel parcel = Parcel.obtain();
        parcel.writeTypedObject(one, 0);
        parcel.setDataPosition(0);

        T toReturn = (T) parcel.readTypedObject(PhoneTimeSuggestion.CREATOR);
        parcel.recycle();
        return toReturn;
    }
}
Loading