Merge "Make TimeDetectorService more aware of origin" am: 4ef2551dfa
am: 3150e58082
Change-Id: Ia70f69e226a7800e82e29dd504351aef65048ed3
This commit is contained in:
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package android.app.timedetector;
|
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
|
* <p>Used by parts of the Android system with signals associated with the device's time to provide
|
||||||
* information to the Time Detector Service.
|
* information to the Time Detector Service.
|
||||||
@@ -32,5 +32,5 @@ import android.app.timedetector.TimeSignal;
|
|||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
interface ITimeDetectorService {
|
interface ITimeDetectorService {
|
||||||
void suggestTime(in TimeSignal timeSignal);
|
void suggestPhoneTime(in PhoneTimeSuggestion timeSuggestion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,4 +16,4 @@
|
|||||||
|
|
||||||
package android.app.timedetector;
|
package android.app.timedetector;
|
||||||
|
|
||||||
parcelable TimeSignal;
|
parcelable PhoneTimeSuggestion;
|
||||||
137
core/java/android/app/timedetector/PhoneTimeSuggestion.java
Normal file
137
core/java/android/app/timedetector/PhoneTimeSuggestion.java
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* 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.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 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 PhoneTimeSuggestion implements Parcelable {
|
||||||
|
|
||||||
|
public static final @NonNull Parcelable.Creator<PhoneTimeSuggestion> CREATOR =
|
||||||
|
new Parcelable.Creator<PhoneTimeSuggestion>() {
|
||||||
|
public PhoneTimeSuggestion createFromParcel(Parcel in) {
|
||||||
|
return PhoneTimeSuggestion.createFromParcel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhoneTimeSuggestion[] newArray(int size) {
|
||||||
|
return new PhoneTimeSuggestion[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final int mPhoneId;
|
||||||
|
@NonNull
|
||||||
|
private final TimestampedValue<Long> mUtcTime;
|
||||||
|
@Nullable
|
||||||
|
private ArrayList<String> mDebugInfo;
|
||||||
|
|
||||||
|
public PhoneTimeSuggestion(int phoneId, @NonNull TimestampedValue<Long> utcTime) {
|
||||||
|
mPhoneId = phoneId;
|
||||||
|
mUtcTime = Objects.requireNonNull(utcTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PhoneTimeSuggestion createFromParcel(Parcel in) {
|
||||||
|
int phoneId = in.readInt();
|
||||||
|
TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
|
||||||
|
PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId, utcTime);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
|
||||||
|
suggestion.mDebugInfo = debugInfo;
|
||||||
|
return suggestion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||||
|
dest.writeInt(mPhoneId);
|
||||||
|
dest.writeParcelable(mUtcTime, 0);
|
||||||
|
dest.writeList(mDebugInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPhoneId() {
|
||||||
|
return mPhoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public TimestampedValue<Long> getUtcTime() {
|
||||||
|
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) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PhoneTimeSuggestion that = (PhoneTimeSuggestion) o;
|
||||||
|
return mPhoneId == that.mPhoneId
|
||||||
|
&& Objects.equals(mUtcTime, that.mUtcTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(mPhoneId, mUtcTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PhoneTimeSuggestion{"
|
||||||
|
+ "mPhoneId='" + mPhoneId + '\''
|
||||||
|
+ ", mUtcTime=" + mUtcTime
|
||||||
|
+ ", mDebugInfo=" + mDebugInfo
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,12 +45,12 @@ public final class TimeDetector {
|
|||||||
* signals are available such as those that come from more reliable sources or were
|
* signals are available such as those that come from more reliable sources or were
|
||||||
* determined more recently.
|
* determined more recently.
|
||||||
*/
|
*/
|
||||||
public void suggestTime(@NonNull TimeSignal timeSignal) {
|
public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "suggestTime called: " + timeSignal);
|
Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mITimeDetectorService.suggestTime(timeSignal);
|
mITimeDetectorService.suggestPhoneTime(timeSuggestion);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 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.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.util.TimestampedValue;
|
|
||||||
|
|
||||||
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
|
|
||||||
* must not be persisted across device resets.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public final class TimeSignal 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 TimeSignal[] newArray(int size) {
|
|
||||||
return new TimeSignal[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final String SOURCE_ID_NITZ = "nitz";
|
|
||||||
|
|
||||||
private final String mSourceId;
|
|
||||||
private final TimestampedValue<Long> mUtcTime;
|
|
||||||
|
|
||||||
public TimeSignal(String sourceId, TimestampedValue<Long> utcTime) {
|
|
||||||
mSourceId = Objects.requireNonNull(sourceId);
|
|
||||||
mUtcTime = Objects.requireNonNull(utcTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TimeSignal createFromParcel(Parcel in) {
|
|
||||||
String sourceId = in.readString();
|
|
||||||
TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
|
|
||||||
return new TimeSignal(sourceId, utcTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
|
||||||
dest.writeString(mSourceId);
|
|
||||||
dest.writeParcelable(mUtcTime, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String getSourceId() {
|
|
||||||
return mSourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public TimestampedValue<Long> getUtcTime() {
|
|
||||||
return mUtcTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TimeSignal that = (TimeSignal) o;
|
|
||||||
return Objects.equals(mSourceId, that.mSourceId)
|
|
||||||
&& Objects.equals(mUtcTime, that.mUtcTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(mSourceId, mUtcTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TimeSignal{"
|
|
||||||
+ "mSourceId='" + mSourceId + '\''
|
|
||||||
+ ", mUtcTime=" + mUtcTime
|
|
||||||
+ '}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ package com.android.server.timedetector;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.timedetector.TimeSignal;
|
import android.app.timedetector.PhoneTimeSuggestion;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.TimestampedValue;
|
import android.util.TimestampedValue;
|
||||||
@@ -48,9 +48,8 @@ public final class SimpleTimeDetectorStrategy implements TimeDetectorStrategy {
|
|||||||
// @NonNull after initialize()
|
// @NonNull after initialize()
|
||||||
private Callback mCallback;
|
private Callback mCallback;
|
||||||
|
|
||||||
// NITZ state.
|
// Last phone suggestion.
|
||||||
@Nullable private TimestampedValue<Long> mLastNitzTime;
|
@Nullable private PhoneTimeSuggestion mLastPhoneSuggestion;
|
||||||
|
|
||||||
|
|
||||||
// Information about the last time signal received: Used when toggling auto-time.
|
// Information about the last time signal received: Used when toggling auto-time.
|
||||||
@Nullable private TimestampedValue<Long> mLastSystemClockTime;
|
@Nullable private TimestampedValue<Long> mLastSystemClockTime;
|
||||||
@@ -65,46 +64,40 @@ public final class SimpleTimeDetectorStrategy implements TimeDetectorStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suggestTime(@NonNull TimeSignal timeSignal) {
|
public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
|
||||||
if (!TimeSignal.SOURCE_ID_NITZ.equals(timeSignal.getSourceId())) {
|
|
||||||
Slog.w(TAG, "Ignoring signal from unsupported source: " + timeSignal);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NITZ logic
|
// NITZ logic
|
||||||
|
|
||||||
TimestampedValue<Long> newNitzUtcTime = timeSignal.getUtcTime();
|
boolean timeSuggestionIsValid =
|
||||||
boolean nitzTimeIsValid = validateNewNitzTime(newNitzUtcTime, mLastNitzTime);
|
validateNewPhoneSuggestion(timeSuggestion, mLastPhoneSuggestion);
|
||||||
if (!nitzTimeIsValid) {
|
if (!timeSuggestionIsValid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Always store the last NITZ value received, regardless of whether we go on to use it to
|
// Always store the last NITZ value received, regardless of whether we go on to use it to
|
||||||
// update the system clock. This is so that we can validate future NITZ signals.
|
// update the system clock. This is so that we can validate future NITZ signals.
|
||||||
mLastNitzTime = newNitzUtcTime;
|
mLastPhoneSuggestion = timeSuggestion;
|
||||||
|
|
||||||
// System clock update logic.
|
// System clock update logic.
|
||||||
|
|
||||||
// Historically, Android has sent a telephony broadcast only when setting the time using
|
// Historically, Android has sent a telephony broadcast only when setting the time using
|
||||||
// NITZ.
|
// NITZ.
|
||||||
final boolean sendNetworkBroadcast =
|
final boolean sendNetworkBroadcast = true;
|
||||||
TimeSignal.SOURCE_ID_NITZ.equals(timeSignal.getSourceId());
|
|
||||||
|
|
||||||
final TimestampedValue<Long> newUtcTime = newNitzUtcTime;
|
final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
|
||||||
setSystemClockIfRequired(newUtcTime, sendNetworkBroadcast);
|
setSystemClockIfRequired(newUtcTime, sendNetworkBroadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean validateNewNitzTime(TimestampedValue<Long> newNitzUtcTime,
|
private static boolean validateNewPhoneSuggestion(@NonNull PhoneTimeSuggestion newSuggestion,
|
||||||
TimestampedValue<Long> lastNitzTime) {
|
@Nullable PhoneTimeSuggestion lastSuggestion) {
|
||||||
|
|
||||||
if (lastNitzTime != null) {
|
if (lastSuggestion != null) {
|
||||||
long referenceTimeDifference =
|
long referenceTimeDifference = TimestampedValue.referenceTimeDifference(
|
||||||
TimestampedValue.referenceTimeDifference(newNitzUtcTime, lastNitzTime);
|
newSuggestion.getUtcTime(), lastSuggestion.getUtcTime());
|
||||||
if (referenceTimeDifference < 0 || referenceTimeDifference > Integer.MAX_VALUE) {
|
if (referenceTimeDifference < 0 || referenceTimeDifference > Integer.MAX_VALUE) {
|
||||||
// Out of order or bogus.
|
// Out of order or bogus.
|
||||||
Slog.w(TAG, "validateNewNitzTime: Bad NITZ signal received."
|
Slog.w(TAG, "validateNewNitzTime: Bad NITZ signal received."
|
||||||
+ " referenceTimeDifference=" + referenceTimeDifference
|
+ " referenceTimeDifference=" + referenceTimeDifference
|
||||||
+ " lastNitzTime=" + lastNitzTime
|
+ " lastSuggestion=" + lastSuggestion
|
||||||
+ " newNitzUtcTime=" + newNitzUtcTime);
|
+ " newSuggestion=" + newSuggestion);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,7 +175,7 @@ public final class SimpleTimeDetectorStrategy implements TimeDetectorStrategy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(@NonNull PrintWriter pw, @Nullable String[] args) {
|
public void dump(@NonNull PrintWriter pw, @Nullable String[] args) {
|
||||||
pw.println("mLastNitzTime=" + mLastNitzTime);
|
pw.println("mLastPhoneSuggestion=" + mLastPhoneSuggestion);
|
||||||
pw.println("mLastSystemClockTimeSet=" + mLastSystemClockTimeSet);
|
pw.println("mLastSystemClockTimeSet=" + mLastSystemClockTimeSet);
|
||||||
pw.println("mLastSystemClockTime=" + mLastSystemClockTime);
|
pw.println("mLastSystemClockTime=" + mLastSystemClockTime);
|
||||||
pw.println("mLastSystemClockTimeSendNetworkBroadcast="
|
pw.println("mLastSystemClockTimeSendNetworkBroadcast="
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.android.server.timedetector;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.timedetector.ITimeDetectorService;
|
import android.app.timedetector.ITimeDetectorService;
|
||||||
import android.app.timedetector.TimeSignal;
|
import android.app.timedetector.PhoneTimeSuggestion;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
@@ -96,14 +96,14 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suggestTime(@NonNull TimeSignal timeSignal) {
|
public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSignal) {
|
||||||
enforceSetTimePermission();
|
enforceSetTimePermission();
|
||||||
Objects.requireNonNull(timeSignal);
|
Objects.requireNonNull(timeSignal);
|
||||||
|
|
||||||
long idToken = Binder.clearCallingIdentity();
|
long idToken = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
synchronized (mStrategyLock) {
|
synchronized (mStrategyLock) {
|
||||||
mTimeDetectorStrategy.suggestTime(timeSignal);
|
mTimeDetectorStrategy.suggestPhoneTime(timeSignal);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(idToken);
|
Binder.restoreCallingIdentity(idToken);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package com.android.server.timedetector;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.timedetector.TimeSignal;
|
import android.app.timedetector.PhoneTimeSuggestion;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.TimestampedValue;
|
import android.util.TimestampedValue;
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ public interface TimeDetectorStrategy {
|
|||||||
void initialize(@NonNull Callback callback);
|
void initialize(@NonNull Callback callback);
|
||||||
|
|
||||||
/** Process the suggested time. */
|
/** Process the suggested time. */
|
||||||
void suggestTime(@NonNull TimeSignal timeSignal);
|
void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion);
|
||||||
|
|
||||||
/** Handle the auto-time setting being toggled on or off. */
|
/** Handle the auto-time setting being toggled on or off. */
|
||||||
void handleAutoTimeDetectionToggle(boolean enabled);
|
void handleAutoTimeDetectionToggle(boolean enabled);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import android.app.timedetector.TimeSignal;
|
import android.app.timedetector.PhoneTimeSuggestion;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.icu.util.Calendar;
|
import android.icu.util.Calendar;
|
||||||
import android.icu.util.GregorianCalendar;
|
import android.icu.util.GregorianCalendar;
|
||||||
@@ -45,6 +45,8 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
.setActualTimeUtc(2018, 1, 1, 12, 0, 0)
|
.setActualTimeUtc(2018, 1, 1, 12, 0, 0)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
private static final int ARBITRARY_PHONE_ID = 123456;
|
||||||
|
|
||||||
private Script mScript;
|
private Script mScript;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -53,30 +55,32 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestTime_nitz_timeDetectionEnabled() {
|
public void testSuggestPhoneTime_nitz_timeDetectionEnabled() {
|
||||||
Scenario scenario = SCENARIO_1;
|
Scenario scenario = SCENARIO_1;
|
||||||
mScript.pokeFakeClocks(scenario)
|
mScript.pokeFakeClocks(scenario)
|
||||||
.pokeTimeDetectionEnabled(true);
|
.pokeTimeDetectionEnabled(true);
|
||||||
|
|
||||||
TimeSignal timeSignal = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
|
PhoneTimeSuggestion timeSuggestion =
|
||||||
|
scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
|
||||||
final int clockIncrement = 1000;
|
final int clockIncrement = 1000;
|
||||||
long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
|
long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
|
||||||
|
|
||||||
mScript.simulateTimePassing(clockIncrement)
|
mScript.simulateTimePassing(clockIncrement)
|
||||||
.simulateTimeSignalReceived(timeSignal)
|
.simulatePhoneTimeSuggestion(timeSuggestion)
|
||||||
.verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis);
|
.verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestTime_systemClockThreshold() {
|
public void testSuggestPhoneTime_systemClockThreshold() {
|
||||||
Scenario scenario = SCENARIO_1;
|
Scenario scenario = SCENARIO_1;
|
||||||
final int systemClockUpdateThresholdMillis = 1000;
|
final int systemClockUpdateThresholdMillis = 1000;
|
||||||
mScript.pokeFakeClocks(scenario)
|
mScript.pokeFakeClocks(scenario)
|
||||||
.pokeThresholds(systemClockUpdateThresholdMillis)
|
.pokeThresholds(systemClockUpdateThresholdMillis)
|
||||||
.pokeTimeDetectionEnabled(true);
|
.pokeTimeDetectionEnabled(true);
|
||||||
|
|
||||||
TimeSignal timeSignal1 = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
|
PhoneTimeSuggestion timeSuggestion1 =
|
||||||
TimestampedValue<Long> utcTime1 = timeSignal1.getUtcTime();
|
scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
|
||||||
|
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
|
||||||
|
|
||||||
final int clockIncrement = 100;
|
final int clockIncrement = 100;
|
||||||
// Increment the the device clocks to simulate the passage of time.
|
// Increment the the device clocks to simulate the passage of time.
|
||||||
@@ -86,7 +90,7 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
|
TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
|
||||||
|
|
||||||
// Send the first time signal. It should be used.
|
// Send the first time signal. It should be used.
|
||||||
mScript.simulateTimeSignalReceived(timeSignal1)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
|
||||||
.verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis1);
|
.verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis1);
|
||||||
|
|
||||||
// Now send another time signal, but one that is too similar to the last one and should be
|
// Now send another time signal, but one that is too similar to the last one and should be
|
||||||
@@ -95,9 +99,9 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
|
TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
|
||||||
mScript.peekElapsedRealtimeMillis(),
|
mScript.peekElapsedRealtimeMillis(),
|
||||||
mScript.peekSystemClockMillis() + underThresholdMillis);
|
mScript.peekSystemClockMillis() + underThresholdMillis);
|
||||||
TimeSignal timeSignal2 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime2);
|
PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
|
||||||
mScript.simulateTimePassing(clockIncrement)
|
mScript.simulateTimePassing(clockIncrement)
|
||||||
.simulateTimeSignalReceived(timeSignal2)
|
.simulatePhoneTimeSuggestion(timeSuggestion2)
|
||||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||||
|
|
||||||
// Now send another time signal, but one that is on the threshold and so should be used.
|
// Now send another time signal, but one that is on the threshold and so should be used.
|
||||||
@@ -105,42 +109,44 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
mScript.peekElapsedRealtimeMillis(),
|
mScript.peekElapsedRealtimeMillis(),
|
||||||
mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
|
mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
|
||||||
|
|
||||||
TimeSignal timeSignal3 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime3);
|
PhoneTimeSuggestion timeSuggestion3 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
|
||||||
mScript.simulateTimePassing(clockIncrement);
|
mScript.simulateTimePassing(clockIncrement);
|
||||||
|
|
||||||
long expectSystemClockMillis3 =
|
long expectSystemClockMillis3 =
|
||||||
TimeDetectorStrategy.getTimeAt(utcTime3, mScript.peekElapsedRealtimeMillis());
|
TimeDetectorStrategy.getTimeAt(utcTime3, mScript.peekElapsedRealtimeMillis());
|
||||||
|
|
||||||
mScript.simulateTimeSignalReceived(timeSignal3)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
|
||||||
.verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis3);
|
.verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestTime_nitz_timeDetectionDisabled() {
|
public void testSuggestPhoneTime_nitz_timeDetectionDisabled() {
|
||||||
Scenario scenario = SCENARIO_1;
|
Scenario scenario = SCENARIO_1;
|
||||||
mScript.pokeFakeClocks(scenario)
|
mScript.pokeFakeClocks(scenario)
|
||||||
.pokeTimeDetectionEnabled(false);
|
.pokeTimeDetectionEnabled(false);
|
||||||
|
|
||||||
TimeSignal timeSignal = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
|
PhoneTimeSuggestion timeSuggestion =
|
||||||
mScript.simulateTimeSignalReceived(timeSignal)
|
scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
|
||||||
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion)
|
||||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestTime_nitz_invalidNitzReferenceTimesIgnored() {
|
public void testSuggestPhoneTime_nitz_invalidNitzReferenceTimesIgnored() {
|
||||||
Scenario scenario = SCENARIO_1;
|
Scenario scenario = SCENARIO_1;
|
||||||
final int systemClockUpdateThreshold = 2000;
|
final int systemClockUpdateThreshold = 2000;
|
||||||
mScript.pokeFakeClocks(scenario)
|
mScript.pokeFakeClocks(scenario)
|
||||||
.pokeThresholds(systemClockUpdateThreshold)
|
.pokeThresholds(systemClockUpdateThreshold)
|
||||||
.pokeTimeDetectionEnabled(true);
|
.pokeTimeDetectionEnabled(true);
|
||||||
TimeSignal timeSignal1 = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
|
PhoneTimeSuggestion timeSuggestion1 =
|
||||||
TimestampedValue<Long> utcTime1 = timeSignal1.getUtcTime();
|
scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
|
||||||
|
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
|
||||||
|
|
||||||
// Initialize the strategy / device with a time set from NITZ.
|
// Initialize the strategy / device with a time set from NITZ.
|
||||||
mScript.simulateTimePassing(100);
|
mScript.simulateTimePassing(100);
|
||||||
long expectedSystemClockMillis1 =
|
long expectedSystemClockMillis1 =
|
||||||
TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
|
TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
|
||||||
mScript.simulateTimeSignalReceived(timeSignal1)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
|
||||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1);
|
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1);
|
||||||
|
|
||||||
// The UTC time increment should be larger than the system clock update threshold so we
|
// The UTC time increment should be larger than the system clock update threshold so we
|
||||||
@@ -152,8 +158,8 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
|
long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
|
||||||
TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
|
TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
|
||||||
referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
|
referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
|
||||||
TimeSignal timeSignal2 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime2);
|
PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
|
||||||
mScript.simulateTimeSignalReceived(timeSignal2)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
|
||||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||||
|
|
||||||
// Now supply a new signal that has an obviously bogus reference time : substantially in the
|
// Now supply a new signal that has an obviously bogus reference time : substantially in the
|
||||||
@@ -162,8 +168,8 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
|
utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
|
||||||
TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
|
TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
|
||||||
referenceTimeInFutureMillis, validUtcTimeMillis);
|
referenceTimeInFutureMillis, validUtcTimeMillis);
|
||||||
TimeSignal timeSignal3 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime3);
|
PhoneTimeSuggestion timeSuggestion3 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
|
||||||
mScript.simulateTimeSignalReceived(timeSignal3)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
|
||||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||||
|
|
||||||
// Just to prove validUtcTimeMillis is valid.
|
// Just to prove validUtcTimeMillis is valid.
|
||||||
@@ -172,13 +178,13 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
validReferenceTimeMillis, validUtcTimeMillis);
|
validReferenceTimeMillis, validUtcTimeMillis);
|
||||||
long expectedSystemClockMillis4 =
|
long expectedSystemClockMillis4 =
|
||||||
TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
|
TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
|
||||||
TimeSignal timeSignal4 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime4);
|
PhoneTimeSuggestion timeSuggestion4 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime4);
|
||||||
mScript.simulateTimeSignalReceived(timeSignal4)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
|
||||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4);
|
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestTime_timeDetectionToggled() {
|
public void testSuggestPhoneTime_timeDetectionToggled() {
|
||||||
Scenario scenario = SCENARIO_1;
|
Scenario scenario = SCENARIO_1;
|
||||||
final int clockIncrementMillis = 100;
|
final int clockIncrementMillis = 100;
|
||||||
final int systemClockUpdateThreshold = 2000;
|
final int systemClockUpdateThreshold = 2000;
|
||||||
@@ -186,15 +192,16 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
.pokeThresholds(systemClockUpdateThreshold)
|
.pokeThresholds(systemClockUpdateThreshold)
|
||||||
.pokeTimeDetectionEnabled(false);
|
.pokeTimeDetectionEnabled(false);
|
||||||
|
|
||||||
TimeSignal timeSignal1 = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
|
PhoneTimeSuggestion timeSuggestion1 =
|
||||||
TimestampedValue<Long> utcTime1 = timeSignal1.getUtcTime();
|
scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
|
||||||
|
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
|
||||||
|
|
||||||
// Simulate time passing.
|
// Simulate time passing.
|
||||||
mScript.simulateTimePassing(clockIncrementMillis);
|
mScript.simulateTimePassing(clockIncrementMillis);
|
||||||
|
|
||||||
// Simulate the time signal being received. It should not be used because auto time
|
// Simulate the time signal being received. It should not be used because auto time
|
||||||
// detection is off but it should be recorded.
|
// detection is off but it should be recorded.
|
||||||
mScript.simulateTimeSignalReceived(timeSignal1)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
|
||||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||||
|
|
||||||
// Simulate more time passing.
|
// Simulate more time passing.
|
||||||
@@ -216,7 +223,7 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
|
TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
|
||||||
mScript.peekElapsedRealtimeMillis(),
|
mScript.peekElapsedRealtimeMillis(),
|
||||||
mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
|
mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
|
||||||
TimeSignal timeSignal2 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime2);
|
PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
|
||||||
|
|
||||||
// Simulate more time passing.
|
// Simulate more time passing.
|
||||||
mScript.simulateTimePassing(clockIncrementMillis);
|
mScript.simulateTimePassing(clockIncrementMillis);
|
||||||
@@ -226,7 +233,7 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
|
|
||||||
// The new time, though valid, should not be set in the system clock because auto time is
|
// The new time, though valid, should not be set in the system clock because auto time is
|
||||||
// disabled.
|
// disabled.
|
||||||
mScript.simulateTimeSignalReceived(timeSignal2)
|
mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
|
||||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||||
|
|
||||||
// Turn on auto time detection.
|
// Turn on auto time detection.
|
||||||
@@ -234,17 +241,6 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2);
|
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuggestTime_unknownSource() {
|
|
||||||
Scenario scenario = SCENARIO_1;
|
|
||||||
mScript.pokeFakeClocks(scenario)
|
|
||||||
.pokeTimeDetectionEnabled(true);
|
|
||||||
|
|
||||||
TimeSignal timeSignal = scenario.createTimeSignalForActual("unknown");
|
|
||||||
mScript.simulateTimeSignalReceived(timeSignal)
|
|
||||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
|
* A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
|
||||||
* like the real thing should, it also asserts preconditions.
|
* like the real thing should, it also asserts preconditions.
|
||||||
@@ -407,8 +403,8 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
return mFakeCallback.peekSystemClockMillis();
|
return mFakeCallback.peekSystemClockMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
Script simulateTimeSignalReceived(TimeSignal timeSignal) {
|
Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
|
||||||
mSimpleTimeDetectorStrategy.suggestTime(timeSignal);
|
mSimpleTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,10 +462,10 @@ public class SimpleTimeZoneDetectorStrategyTest {
|
|||||||
return mActualTimeMillis;
|
return mActualTimeMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeSignal createTimeSignalForActual(String sourceId) {
|
PhoneTimeSuggestion createPhoneTimeSuggestionForActual(int phoneId) {
|
||||||
TimestampedValue<Long> time = new TimestampedValue<>(
|
TimestampedValue<Long> time = new TimestampedValue<>(
|
||||||
mInitialDeviceRealtimeMillis, mActualTimeMillis);
|
mInitialDeviceRealtimeMillis, mActualTimeMillis);
|
||||||
return new TimeSignal(sourceId, time);
|
return new PhoneTimeSuggestion(phoneId, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Builder {
|
static class Builder {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.timedetector.TimeSignal;
|
import android.app.timedetector.PhoneTimeSuggestion;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.util.TimestampedValue;
|
import android.util.TimestampedValue;
|
||||||
@@ -67,10 +67,10 @@ public class TimeDetectorServiceTest {
|
|||||||
public void testStubbedCall_withoutPermission() {
|
public void testStubbedCall_withoutPermission() {
|
||||||
doThrow(new SecurityException("Mock"))
|
doThrow(new SecurityException("Mock"))
|
||||||
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||||
TimeSignal timeSignal = createNitzTimeSignal();
|
PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mTimeDetectorService.suggestTime(timeSignal);
|
mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
|
||||||
} finally {
|
} finally {
|
||||||
verify(mMockContext).enforceCallingPermission(
|
verify(mMockContext).enforceCallingPermission(
|
||||||
eq(android.Manifest.permission.SET_TIME), anyString());
|
eq(android.Manifest.permission.SET_TIME), anyString());
|
||||||
@@ -78,15 +78,15 @@ public class TimeDetectorServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestTime() {
|
public void testSuggestPhoneTime() {
|
||||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||||
|
|
||||||
TimeSignal timeSignal = createNitzTimeSignal();
|
PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
|
||||||
mTimeDetectorService.suggestTime(timeSignal);
|
mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
|
||||||
|
|
||||||
verify(mMockContext)
|
verify(mMockContext)
|
||||||
.enforceCallingPermission(eq(android.Manifest.permission.SET_TIME), anyString());
|
.enforceCallingPermission(eq(android.Manifest.permission.SET_TIME), anyString());
|
||||||
mStubbedTimeDetectorStrategy.verifySuggestTimeCalled(timeSignal);
|
mStubbedTimeDetectorStrategy.verifySuggestPhoneTimeCalled(phoneTimeSuggestion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -115,15 +115,16 @@ public class TimeDetectorServiceTest {
|
|||||||
mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionToggleCalled(false);
|
mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionToggleCalled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TimeSignal createNitzTimeSignal() {
|
private static PhoneTimeSuggestion createPhoneTimeSuggestion() {
|
||||||
|
int phoneId = 1234;
|
||||||
TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
|
TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
|
||||||
return new TimeSignal(TimeSignal.SOURCE_ID_NITZ, timeValue);
|
return new PhoneTimeSuggestion(phoneId, timeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
|
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
|
||||||
|
|
||||||
// Call tracking.
|
// Call tracking.
|
||||||
private TimeSignal mLastSuggestedTime;
|
private PhoneTimeSuggestion mLastPhoneSuggestion;
|
||||||
private Boolean mLastAutoTimeDetectionToggle;
|
private Boolean mLastAutoTimeDetectionToggle;
|
||||||
private boolean mDumpCalled;
|
private boolean mDumpCalled;
|
||||||
|
|
||||||
@@ -132,9 +133,9 @@ public class TimeDetectorServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suggestTime(TimeSignal timeSignal) {
|
public void suggestPhoneTime(PhoneTimeSuggestion timeSuggestion) {
|
||||||
resetCallTracking();
|
resetCallTracking();
|
||||||
mLastSuggestedTime = timeSignal;
|
mLastPhoneSuggestion = timeSuggestion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -150,13 +151,13 @@ public class TimeDetectorServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resetCallTracking() {
|
void resetCallTracking() {
|
||||||
mLastSuggestedTime = null;
|
mLastPhoneSuggestion = null;
|
||||||
mLastAutoTimeDetectionToggle = null;
|
mLastAutoTimeDetectionToggle = null;
|
||||||
mDumpCalled = false;
|
mDumpCalled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void verifySuggestTimeCalled(TimeSignal expectedSignal) {
|
void verifySuggestPhoneTimeCalled(PhoneTimeSuggestion expectedSignal) {
|
||||||
assertEquals(expectedSignal, mLastSuggestedTime);
|
assertEquals(expectedSignal, mLastPhoneSuggestion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void verifyHandleAutoTimeDetectionToggleCalled(boolean expectedEnable) {
|
void verifyHandleAutoTimeDetectionToggleCalled(boolean expectedEnable) {
|
||||||
|
|||||||
Reference in New Issue
Block a user