Merge "Add time detector network behavior"
This commit is contained in:
@@ -124,7 +124,7 @@ public final class UnixEpochTime implements Parcelable {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UnixEpochTime{"
|
||||
+ "mElapsedRealtimeTimeMillis=" + mElapsedRealtimeMillis
|
||||
+ "mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
|
||||
+ ", mUnixEpochTimeMillis=" + mUnixEpochTimeMillis
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@@ -72,6 +72,18 @@ public interface TimeDetector {
|
||||
*/
|
||||
String SHELL_COMMAND_SUGGEST_NETWORK_TIME = "suggest_network_time";
|
||||
|
||||
/**
|
||||
* A shell command that prints the current network time information.
|
||||
* @hide
|
||||
*/
|
||||
String SHELL_COMMAND_GET_NETWORK_TIME = "get_network_time";
|
||||
|
||||
/**
|
||||
* A shell command that clears the detector's network time information.
|
||||
* @hide
|
||||
*/
|
||||
String SHELL_COMMAND_CLEAR_NETWORK_TIME = "clear_network_time";
|
||||
|
||||
/**
|
||||
* A shell command that injects a GNSS time suggestion.
|
||||
* @hide
|
||||
|
||||
@@ -143,7 +143,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
return getTimeCapabilitiesAndConfig(userId);
|
||||
}
|
||||
|
||||
TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig(@UserIdInt int userId) {
|
||||
private TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig(@UserIdInt int userId) {
|
||||
enforceManageTimeDetectorPermission();
|
||||
|
||||
final long token = mCallerIdentityInjector.clearCallingIdentity();
|
||||
@@ -163,6 +163,9 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
return updateConfiguration(callingUserId, configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the user's configuration. Exposed for use by {@link TimeDetectorShellCommand}.
|
||||
*/
|
||||
boolean updateConfiguration(@UserIdInt int userId, @NonNull TimeConfiguration configuration) {
|
||||
// Resolve constants like USER_CURRENT to the true user ID as needed.
|
||||
int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
|
||||
@@ -256,7 +259,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
void handleConfigurationInternalChangedOnHandlerThread() {
|
||||
private void handleConfigurationInternalChangedOnHandlerThread() {
|
||||
// Configuration has changed, but each user may have a different view of the configuration.
|
||||
// It's possible that this will cause unnecessary notifications but that shouldn't be a
|
||||
// problem.
|
||||
@@ -287,6 +290,10 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system time state. See {@link TimeState} for details. For use by {@link
|
||||
* TimeDetectorShellCommand}.
|
||||
*/
|
||||
void setTimeState(@NonNull TimeState timeState) {
|
||||
enforceManageTimeDetectorPermission();
|
||||
|
||||
@@ -353,6 +360,9 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests network time with permission checks. For use by {@link TimeDetectorShellCommand}.
|
||||
*/
|
||||
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal) {
|
||||
enforceSuggestNetworkTimePermission();
|
||||
Objects.requireNonNull(timeSignal);
|
||||
@@ -360,6 +370,23 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cached network time information. For use during tests to simulate when no network
|
||||
* time has been made available. For use by {@link TimeDetectorShellCommand}.
|
||||
*
|
||||
* <p>This operation takes place in the calling thread.
|
||||
*/
|
||||
void clearNetworkTime() {
|
||||
enforceSuggestNetworkTimePermission();
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mTimeDetectorStrategy.clearLatestNetworkSuggestion();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixEpochTime latestNetworkTime() {
|
||||
NetworkTimeSuggestion suggestion = getLatestNetworkSuggestion();
|
||||
@@ -388,6 +415,9 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests GNSS time with permission checks. For use by {@link TimeDetectorShellCommand}.
|
||||
*/
|
||||
void suggestGnssTime(@NonNull GnssTimeSuggestion timeSignal) {
|
||||
enforceSuggestGnssTimePermission();
|
||||
Objects.requireNonNull(timeSignal);
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_NETWORK_TIME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CONFIRM_TIME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_NETWORK_TIME;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_TIME_STATE;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
|
||||
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME;
|
||||
@@ -70,6 +72,10 @@ class TimeDetectorShellCommand extends ShellCommand {
|
||||
return runSuggestTelephonyTime();
|
||||
case SHELL_COMMAND_SUGGEST_NETWORK_TIME:
|
||||
return runSuggestNetworkTime();
|
||||
case SHELL_COMMAND_GET_NETWORK_TIME:
|
||||
return runGetNetworkTime();
|
||||
case SHELL_COMMAND_CLEAR_NETWORK_TIME:
|
||||
return runClearNetworkTime();
|
||||
case SHELL_COMMAND_SUGGEST_GNSS_TIME:
|
||||
return runSuggestGnssTime();
|
||||
case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME:
|
||||
@@ -122,6 +128,18 @@ class TimeDetectorShellCommand extends ShellCommand {
|
||||
mInterface::suggestNetworkTime);
|
||||
}
|
||||
|
||||
private int runGetNetworkTime() {
|
||||
NetworkTimeSuggestion networkTimeSuggestion = mInterface.getLatestNetworkSuggestion();
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
pw.println(networkTimeSuggestion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runClearNetworkTime() {
|
||||
mInterface.clearNetworkTime();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runSuggestGnssTime() {
|
||||
return runSuggestTime(
|
||||
() -> GnssTimeSuggestion.parseCommandLineArg(this),
|
||||
@@ -196,6 +214,10 @@ class TimeDetectorShellCommand extends ShellCommand {
|
||||
pw.printf(" Sets the current time state for tests.\n");
|
||||
pw.printf(" %s <unix epoch time options>\n", SHELL_COMMAND_CONFIRM_TIME);
|
||||
pw.printf(" Tries to confirms the time, raising the confidence.\n");
|
||||
pw.printf(" %s\n", SHELL_COMMAND_GET_NETWORK_TIME);
|
||||
pw.printf(" Prints the network time information held by the detector.\n");
|
||||
pw.printf(" %s\n", SHELL_COMMAND_CLEAR_NETWORK_TIME);
|
||||
pw.printf(" Clears the network time information held by the detector.\n");
|
||||
pw.println();
|
||||
ManualTimeSuggestion.printCommandLineOpts(pw);
|
||||
pw.println();
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.timedetector;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.time.TimeState;
|
||||
@@ -103,6 +104,20 @@ public interface TimeDetectorStrategy extends Dumpable {
|
||||
/** Processes the suggested time from network sources. */
|
||||
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
|
||||
|
||||
/**
|
||||
* Returns the latest (accepted) network time suggestion. Returns {@code null} if there isn't
|
||||
* one.
|
||||
*/
|
||||
@Nullable
|
||||
NetworkTimeSuggestion getLatestNetworkSuggestion();
|
||||
|
||||
/**
|
||||
* Clears the latest network time suggestion, leaving none. The remaining time signals from
|
||||
* other sources will be reassessed causing the device's time to be updated if config and
|
||||
* settings allow.
|
||||
*/
|
||||
void clearLatestNetworkSuggestion();
|
||||
|
||||
/** Processes the suggested time from gnss sources. */
|
||||
void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion);
|
||||
|
||||
|
||||
@@ -315,6 +315,21 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
doAutoTimeDetection(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public synchronized NetworkTimeSuggestion getLatestNetworkSuggestion() {
|
||||
return mLastNetworkSuggestion.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void clearLatestNetworkSuggestion() {
|
||||
mLastNetworkSuggestion.set(null);
|
||||
|
||||
// The loss of network time may change the time signal to use to set the system clock.
|
||||
String reason = "Network time cleared";
|
||||
doAutoTimeDetection(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public synchronized TimeState getTimeState() {
|
||||
@@ -1063,15 +1078,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
return mSuggestionBySlotIndex.get(slotIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* A method used to inspect state during tests. Not intended for general use.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@Nullable
|
||||
public synchronized NetworkTimeSuggestion getLatestNetworkSuggestion() {
|
||||
return mLastNetworkSuggestion.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* A method used to inspect state during tests. Not intended for general use.
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,15 @@ public class FakeTimeDetectorStrategy implements TimeDetectorStrategy {
|
||||
public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkTimeSuggestion getLatestNetworkSuggestion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLatestNetworkSuggestion() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) {
|
||||
}
|
||||
|
||||
@@ -379,6 +379,28 @@ public class TimeDetectorServiceTest {
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestExternalTime(externalTimeSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearNetworkTime_withoutPermission() {
|
||||
doThrow(new SecurityException("Mock"))
|
||||
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> mTimeDetectorService.clearNetworkTime());
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearNetworkTime() throws Exception {
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
|
||||
mTimeDetectorService.clearNetworkTime();
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME), anyString());
|
||||
verify(mFakeTimeDetectorStrategySpy).clearLatestNetworkSuggestion();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLatestNetworkTime() {
|
||||
NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult(
|
||||
|
||||
@@ -874,6 +874,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
@@ -891,9 +892,54 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
script.simulateTimePassing()
|
||||
.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(timeSuggestion)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearLatestNetworkSuggestion() {
|
||||
ConfigurationInternal configInternal =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setOriginPriorities(ORIGIN_NETWORK, ORIGIN_EXTERNAL)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
|
||||
// Create two different time suggestions for the current elapsedRealtimeMillis.
|
||||
ExternalTimeSuggestion externalTimeSuggestion =
|
||||
script.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
NetworkTimeSuggestion networkTimeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME.plus(Duration.ofHours(5)));
|
||||
script.simulateTimePassing();
|
||||
|
||||
// Suggest an external time: This should cause the device to change time.
|
||||
{
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(externalTimeSuggestion.getUnixEpochTime());
|
||||
script.simulateExternalTimeSuggestion(externalTimeSuggestion)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
|
||||
// Suggest a network time: This should cause the device to change time because
|
||||
// network > external.
|
||||
{
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(networkTimeSuggestion.getUnixEpochTime());
|
||||
script.simulateNetworkTimeSuggestion(networkTimeSuggestion)
|
||||
.assertLatestNetworkSuggestion(networkTimeSuggestion)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
|
||||
// Clear the network time. This should cause the device to change back to the external time,
|
||||
// which is now the best time available.
|
||||
{
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(externalTimeSuggestion.getUnixEpochTime());
|
||||
script.simulateClearLatestNetworkSuggestion()
|
||||
.assertLatestNetworkSuggestion(null)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestNetworkTime_rejectedBelowLowerBound() {
|
||||
ConfigurationInternal configInternal =
|
||||
@@ -908,6 +954,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(belowLowerBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(null)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
@@ -926,6 +973,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(aboveLowerBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
|
||||
}
|
||||
@@ -944,6 +992,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(aboveUpperBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(null)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
@@ -962,6 +1011,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(belowUpperBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
|
||||
}
|
||||
@@ -1745,7 +1795,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void suggestionsFromNetworkOriginNotInPriorityList_areIgnored() {
|
||||
public void suggestionsFromNetworkOriginNotInPriorityList_areNotUsed() {
|
||||
ConfigurationInternal configInternal =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setOriginPriorities(ORIGIN_TELEPHONY)
|
||||
@@ -1756,12 +1806,13 @@ public class TimeDetectorStrategyImplTest {
|
||||
ARBITRARY_TEST_TIME);
|
||||
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(timeSuggestion)
|
||||
.assertLatestNetworkSuggestion(timeSuggestion)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void suggestionsFromGnssOriginNotInPriorityList_areIgnored() {
|
||||
public void suggestionsFromGnssOriginNotInPriorityList_areNotUsed() {
|
||||
ConfigurationInternal configInternal =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setOriginPriorities(ORIGIN_TELEPHONY)
|
||||
@@ -1777,7 +1828,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void suggestionsFromExternalOriginNotInPriorityList_areIgnored() {
|
||||
public void suggestionsFromExternalOriginNotInPriorityList_areNotUsed() {
|
||||
ConfigurationInternal configInternal =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setOriginPriorities(ORIGIN_TELEPHONY)
|
||||
@@ -2015,6 +2066,11 @@ public class TimeDetectorStrategyImplTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
Script simulateClearLatestNetworkSuggestion() {
|
||||
mTimeDetectorStrategy.clearLatestNetworkSuggestion();
|
||||
return this;
|
||||
}
|
||||
|
||||
Script simulateGnssTimeSuggestion(GnssTimeSuggestion timeSuggestion) {
|
||||
mTimeDetectorStrategy.suggestGnssTime(timeSuggestion);
|
||||
return this;
|
||||
@@ -2056,6 +2112,12 @@ public class TimeDetectorStrategyImplTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Calls {@link TimeDetectorStrategy#confirmTime(UnixEpochTime)}. */
|
||||
Script simulateConfirmTime(UnixEpochTime confirmationTime, boolean expectedReturnValue) {
|
||||
assertEquals(expectedReturnValue, mTimeDetectorStrategy.confirmTime(confirmationTime));
|
||||
return this;
|
||||
}
|
||||
|
||||
Script verifySystemClockWasNotSetAndResetCallTracking() {
|
||||
mFakeEnvironment.verifySystemClockNotSet();
|
||||
mFakeEnvironment.resetCallTracking();
|
||||
@@ -2218,11 +2280,6 @@ public class TimeDetectorStrategyImplTest {
|
||||
long calculateTimeInMillisForNow(UnixEpochTime unixEpochTime) {
|
||||
return unixEpochTime.at(peekElapsedRealtimeMillis()).getUnixEpochTimeMillis();
|
||||
}
|
||||
|
||||
Script simulateConfirmTime(UnixEpochTime confirmationTime, boolean expectedReturnValue) {
|
||||
assertEquals(expectedReturnValue, mTimeDetectorStrategy.confirmTime(confirmationTime));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static TelephonyTimeSuggestion createTelephonyTimeSuggestion(int slotIndex,
|
||||
|
||||
Reference in New Issue
Block a user