Merge "Make CTS tests ambivalent to server impl" into udc-dev am: f589331297

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21508484

Change-Id: Ib8bba6730a116ddc1d7294b5a3b2bc04d4d55194
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Neil Fuller
2023-02-24 18:31:55 +00:00
committed by Automerger Merge Worker
7 changed files with 159 additions and 91 deletions

View File

@@ -114,6 +114,20 @@ public interface TimeDetector {
*/ */
String SHELL_COMMAND_CONFIRM_TIME = "confirm_time"; String SHELL_COMMAND_CONFIRM_TIME = "confirm_time";
/**
* A shell command that clears the network time signal used by {@link
* SystemClock#currentNetworkTimeClock()}.
* @hide
*/
String SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME = "clear_system_clock_network_time";
/**
* A shell command that sets the network time signal used by {@link
* SystemClock#currentNetworkTimeClock()}.
* @hide
*/
String SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME = "set_system_clock_network_time";
/** /**
* A shared utility method to create a {@link ManualTimeSuggestion}. * A shared utility method to create a {@link ManualTimeSuggestion}.
* *

View File

@@ -477,7 +477,14 @@ public abstract class NtpTrustedTime implements TrustedTime {
return mTimeResult; return mTimeResult;
} }
/** Clears the last received NTP. Intended for use during tests. */ /** Sets the last received NTP time. Intended for use during tests. */
public void setCachedTimeResult(TimeResult timeResult) {
synchronized (this) {
mTimeResult = timeResult;
}
}
/** Clears the last received NTP time. Intended for use during tests. */
public void clearCachedTimeResult() { public void clearCachedTimeResult() {
synchronized (this) { synchronized (this) {
mTimeResult = null; mTimeResult = null;

View File

@@ -180,24 +180,6 @@ public class NetworkTimeUpdateService extends Binder {
} }
} }
/**
* Clears the cached NTP time. For use during tests to simulate when no NTP time is available.
*
* <p>This operation takes place in the calling thread rather than the service's handler thread.
*/
@RequiresPermission(android.Manifest.permission.SET_TIME)
void clearTimeForTests() {
mContext.enforceCallingPermission(
android.Manifest.permission.SET_TIME, "clear latest network time");
final long token = Binder.clearCallingIdentity();
try {
mNtpTrustedTime.clearCachedTimeResult();
} finally {
Binder.restoreCallingIdentity(token);
}
}
/** /**
* Forces the service to refresh the NTP time. * Forces the service to refresh the NTP time.
* *

View File

@@ -36,11 +36,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
*/ */
private static final String SHELL_COMMAND_SERVICE_NAME = "network_time_update_service"; private static final String SHELL_COMMAND_SERVICE_NAME = "network_time_update_service";
/**
* A shell command that clears the time signal received from the network.
*/
private static final String SHELL_COMMAND_CLEAR_TIME = "clear_time";
/** /**
* A shell command that forces the time signal to be refreshed from the network. * A shell command that forces the time signal to be refreshed from the network.
*/ */
@@ -73,8 +68,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
} }
switch (cmd) { switch (cmd) {
case SHELL_COMMAND_CLEAR_TIME:
return runClearTime();
case SHELL_COMMAND_FORCE_REFRESH: case SHELL_COMMAND_FORCE_REFRESH:
return runForceRefresh(); return runForceRefresh();
case SHELL_COMMAND_SET_SERVER_CONFIG: case SHELL_COMMAND_SET_SERVER_CONFIG:
@@ -87,11 +80,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
} }
} }
private int runClearTime() {
mNetworkTimeUpdateService.clearTimeForTests();
return 0;
}
private int runForceRefresh() { private int runForceRefresh() {
boolean success = mNetworkTimeUpdateService.forceRefreshForTests(); boolean success = mNetworkTimeUpdateService.forceRefreshForTests();
getOutPrintWriter().println(success); getOutPrintWriter().println(success);
@@ -147,8 +135,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
pw.printf("Network Time Update Service (%s) commands:\n", SHELL_COMMAND_SERVICE_NAME); pw.printf("Network Time Update Service (%s) commands:\n", SHELL_COMMAND_SERVICE_NAME);
pw.printf(" help\n"); pw.printf(" help\n");
pw.printf(" Print this help text.\n"); pw.printf(" Print this help text.\n");
pw.printf(" %s\n", SHELL_COMMAND_CLEAR_TIME);
pw.printf(" Clears the latest time.\n");
pw.printf(" %s\n", SHELL_COMMAND_FORCE_REFRESH); pw.printf(" %s\n", SHELL_COMMAND_FORCE_REFRESH);
pw.printf(" Refreshes the latest time. Prints whether it was successful.\n"); pw.printf(" Refreshes the latest time. Prints whether it was successful.\n");
pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG); pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);

View File

@@ -37,6 +37,7 @@ import android.os.ParcelableException;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.ShellCallback; import android.os.ShellCallback;
import android.os.SystemClock;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.IndentingPrintWriter; import android.util.IndentingPrintWriter;
import android.util.NtpTrustedTime; import android.util.NtpTrustedTime;
@@ -53,6 +54,7 @@ import com.android.server.timezonedetector.CurrentUserIdentityInjector;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.time.DateTimeException; import java.time.DateTimeException;
import java.util.Objects; import java.util.Objects;
@@ -377,7 +379,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
* *
* <p>This operation takes place in the calling thread. * <p>This operation takes place in the calling thread.
*/ */
void clearNetworkTime() { void clearLatestNetworkTime() {
enforceSuggestNetworkTimePermission(); enforceSuggestNetworkTimePermission();
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
@@ -390,12 +392,29 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
@Override @Override
public UnixEpochTime latestNetworkTime() { public UnixEpochTime latestNetworkTime() {
NetworkTimeSuggestion suggestion = getLatestNetworkSuggestion(); NetworkTimeSuggestion latestNetworkTime;
if (suggestion != null) { // TODO(b/222295093): Remove this condition once we can be sure that all uses of
return suggestion.getUnixEpochTime(); // NtpTrustedTime result in a suggestion being made to the time detector.
// mNtpTrustedTime can be removed once this happens.
if (TimeDetectorNetworkTimeHelper.isInUse()) {
// The new implementation.
latestNetworkTime = mTimeDetectorStrategy.getLatestNetworkSuggestion();
} else { } else {
// The old implementation.
NtpTrustedTime.TimeResult ntpResult = mNtpTrustedTime.getCachedTimeResult();
if (ntpResult != null) {
latestNetworkTime = new NetworkTimeSuggestion(
new UnixEpochTime(
ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis()),
ntpResult.getUncertaintyMillis());
} else {
latestNetworkTime = null;
}
}
if (latestNetworkTime == null) {
throw new ParcelableException(new DateTimeException("Missing network time fix")); throw new ParcelableException(new DateTimeException("Missing network time fix"));
} }
return latestNetworkTime.getUnixEpochTime();
} }
/** /**
@@ -403,23 +422,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
*/ */
@Nullable @Nullable
NetworkTimeSuggestion getLatestNetworkSuggestion() { NetworkTimeSuggestion getLatestNetworkSuggestion() {
// TODO(b/222295093): Return the latest network time from mTimeDetectorStrategy once we can return mTimeDetectorStrategy.getLatestNetworkSuggestion();
// be sure that all uses of NtpTrustedTime results in a suggestion being made to the time
// detector. mNtpTrustedTime can be removed once this happens.
if (TimeDetectorNetworkTimeHelper.isInUse()) {
// The new implementation.
return mTimeDetectorStrategy.getLatestNetworkSuggestion();
} else {
// The old implementation.
NtpTrustedTime.TimeResult ntpResult = mNtpTrustedTime.getCachedTimeResult();
if (ntpResult != null) {
UnixEpochTime unixEpochTime = new UnixEpochTime(
ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
return new NetworkTimeSuggestion(unixEpochTime, ntpResult.getUncertaintyMillis());
} else {
return null;
}
}
} }
/** /**
@@ -440,6 +443,57 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
mHandler.post(() -> mTimeDetectorStrategy.suggestExternalTime(timeSignal)); mHandler.post(() -> mTimeDetectorStrategy.suggestExternalTime(timeSignal));
} }
/**
* Sets the network time for testing {@link SystemClock#currentNetworkTimeClock()}.
*
* <p>This operation takes place in the calling thread.
*/
void setNetworkTimeForSystemClockForTests(
@NonNull UnixEpochTime unixEpochTime, int uncertaintyMillis) {
enforceSuggestNetworkTimePermission();
// TODO(b/222295093): Remove this condition once we can be sure that all uses of
// NtpTrustedTime result in a suggestion being made to the time detector.
// mNtpTrustedTime can be removed once this happens.
if (TimeDetectorNetworkTimeHelper.isInUse()) {
NetworkTimeSuggestion suggestion =
new NetworkTimeSuggestion(unixEpochTime, uncertaintyMillis);
suggestion.addDebugInfo("Injected for tests");
mTimeDetectorStrategy.suggestNetworkTime(suggestion);
} else {
NtpTrustedTime.TimeResult timeResult = new NtpTrustedTime.TimeResult(
unixEpochTime.getUnixEpochTimeMillis(),
unixEpochTime.getElapsedRealtimeMillis(),
uncertaintyMillis,
InetSocketAddress.createUnresolved("time.set.for.tests", 123));
mNtpTrustedTime.setCachedTimeResult(timeResult);
}
}
/**
* Clears the network time for testing {@link SystemClock#currentNetworkTimeClock()}.
*
* <p>This operation takes place in the calling thread.
*/
void clearNetworkTimeForSystemClockForTests() {
enforceSuggestNetworkTimePermission();
final long token = Binder.clearCallingIdentity();
try {
// TODO(b/222295093): Remove this condition once we can be sure that all uses of
// NtpTrustedTime result in a suggestion being made to the time detector.
// mNtpTrustedTime can be removed once this happens.
if (TimeDetectorNetworkTimeHelper.isInUse()) {
// Clear the latest network suggestion. Done in all c
mTimeDetectorStrategy.clearLatestNetworkSuggestion();
} else {
mNtpTrustedTime.clearCachedTimeResult();
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override @Override
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
@Nullable String[] args) { @Nullable String[] args) {

View File

@@ -16,12 +16,14 @@
package com.android.server.timedetector; package com.android.server.timedetector;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_NETWORK_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CONFIRM_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_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_TIME_STATE; 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_IS_AUTO_DETECTION_ENABLED;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_TIME_STATE; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_TIME_STATE;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_EXTERNAL_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_EXTERNAL_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_GNSS_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_GNSS_TIME;
@@ -73,9 +75,9 @@ class TimeDetectorShellCommand extends ShellCommand {
case SHELL_COMMAND_SUGGEST_NETWORK_TIME: case SHELL_COMMAND_SUGGEST_NETWORK_TIME:
return runSuggestNetworkTime(); return runSuggestNetworkTime();
case SHELL_COMMAND_GET_NETWORK_TIME: case SHELL_COMMAND_GET_NETWORK_TIME:
return runGetNetworkTime(); return runGetLatestNetworkTime();
case SHELL_COMMAND_CLEAR_NETWORK_TIME: case SHELL_COMMAND_CLEAR_NETWORK_TIME:
return runClearNetworkTime(); return runClearLatestNetworkTime();
case SHELL_COMMAND_SUGGEST_GNSS_TIME: case SHELL_COMMAND_SUGGEST_GNSS_TIME:
return runSuggestGnssTime(); return runSuggestGnssTime();
case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME: case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME:
@@ -86,6 +88,10 @@ class TimeDetectorShellCommand extends ShellCommand {
return runSetTimeState(); return runSetTimeState();
case SHELL_COMMAND_CONFIRM_TIME: case SHELL_COMMAND_CONFIRM_TIME:
return runConfirmTime(); return runConfirmTime();
case SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME:
return runClearSystemClockNetworkTime();
case SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME:
return runSetSystemClockNetworkTime();
default: { default: {
return handleDefaultCommands(cmd); return handleDefaultCommands(cmd);
} }
@@ -128,15 +134,15 @@ class TimeDetectorShellCommand extends ShellCommand {
mInterface::suggestNetworkTime); mInterface::suggestNetworkTime);
} }
private int runGetNetworkTime() { private int runGetLatestNetworkTime() {
NetworkTimeSuggestion networkTimeSuggestion = mInterface.getLatestNetworkSuggestion(); NetworkTimeSuggestion networkTimeSuggestion = mInterface.getLatestNetworkSuggestion();
final PrintWriter pw = getOutPrintWriter(); final PrintWriter pw = getOutPrintWriter();
pw.println(networkTimeSuggestion); pw.println(networkTimeSuggestion);
return 0; return 0;
} }
private int runClearNetworkTime() { private int runClearLatestNetworkTime() {
mInterface.clearNetworkTime(); mInterface.clearLatestNetworkTime();
return 0; return 0;
} }
@@ -187,6 +193,20 @@ class TimeDetectorShellCommand extends ShellCommand {
return 0; return 0;
} }
private int runClearSystemClockNetworkTime() {
mInterface.clearNetworkTimeForSystemClockForTests();
return 0;
}
private int runSetSystemClockNetworkTime() {
NetworkTimeSuggestion networkTimeSuggestion =
NetworkTimeSuggestion.parseCommandLineArg(this);
mInterface.setNetworkTimeForSystemClockForTests(
networkTimeSuggestion.getUnixEpochTime(),
networkTimeSuggestion.getUncertaintyMillis());
return 0;
}
@Override @Override
public void onHelp() { public void onHelp() {
final PrintWriter pw = getOutPrintWriter(); final PrintWriter pw = getOutPrintWriter();
@@ -218,6 +238,16 @@ class TimeDetectorShellCommand extends ShellCommand {
pw.printf(" Prints the network time information held by the detector.\n"); pw.printf(" Prints the network time information held by the detector.\n");
pw.printf(" %s\n", SHELL_COMMAND_CLEAR_NETWORK_TIME); pw.printf(" %s\n", SHELL_COMMAND_CLEAR_NETWORK_TIME);
pw.printf(" Clears the network time information held by the detector.\n"); pw.printf(" Clears the network time information held by the detector.\n");
// TODO(b/222295093) Remove these "system_clock" commands when
// SystemClock.currentNetworkTimeClock() is guaranteed to use the latest network
// suggestion. Then, commands above can be used instead.
pw.printf(" %s <network suggestion opts>\n",
SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME);
pw.printf(" Sets the network time information used for"
+ " SystemClock.currentNetworkTimeClock().\n");
pw.printf(" %s\n", SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME);
pw.printf(" Clears the network time information used for"
+ " SystemClock.currentNetworkTimeClock().\n");
pw.println(); pw.println();
ManualTimeSuggestion.printCommandLineOpts(pw); ManualTimeSuggestion.printCommandLineOpts(pw);
pw.println(); pw.println();

View File

@@ -386,70 +386,65 @@ public class TimeDetectorServiceTest {
.when(mMockContext).enforceCallingPermission(anyString(), any()); .when(mMockContext).enforceCallingPermission(anyString(), any());
assertThrows(SecurityException.class, assertThrows(SecurityException.class,
() -> mTimeDetectorService.clearNetworkTime()); () -> mTimeDetectorService.clearLatestNetworkTime());
verify(mMockContext).enforceCallingPermission( verify(mMockContext).enforceCallingPermission(
eq(android.Manifest.permission.SET_TIME), anyString()); eq(android.Manifest.permission.SET_TIME), anyString());
} }
@Test @Test
public void testClearNetworkTime() throws Exception { public void testClearLatestNetworkSuggestion() throws Exception {
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any()); doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
mTimeDetectorService.clearNetworkTime(); mTimeDetectorService.clearLatestNetworkTime();
verify(mMockContext).enforceCallingPermission( verify(mMockContext).enforceCallingPermission(
eq(android.Manifest.permission.SET_TIME), anyString()); eq(android.Manifest.permission.SET_TIME), anyString());
verify(mFakeTimeDetectorStrategySpy).clearLatestNetworkSuggestion(); verify(mFakeTimeDetectorStrategySpy).clearLatestNetworkSuggestion();
} }
@Test
public void testLatestNetworkTime() {
NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult(
1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123));
when(mMockNtpTrustedTime.getCachedTimeResult())
.thenReturn(latestNetworkTime);
UnixEpochTime expected = new UnixEpochTime(
latestNetworkTime.getElapsedRealtimeMillis(), latestNetworkTime.getTimeMillis());
assertEquals(expected, mTimeDetectorService.latestNetworkTime());
}
@Test
public void testLatestNetworkTime_noTimeAvailable() {
when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null);
assertThrows(ParcelableException.class, () -> mTimeDetectorService.latestNetworkTime());
}
@Test @Test
public void testGetLatestNetworkSuggestion() { public void testGetLatestNetworkSuggestion() {
if (TimeDetectorNetworkTimeHelper.isInUse()) { NetworkTimeSuggestion latestNetworkSuggestion = createNetworkTimeSuggestion();
NetworkTimeSuggestion latestNetworkTime = createNetworkTimeSuggestion(); mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkSuggestion);
mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkTime);
assertEquals(latestNetworkTime, mTimeDetectorService.getLatestNetworkSuggestion()); assertEquals(latestNetworkSuggestion, mTimeDetectorService.getLatestNetworkSuggestion());
}
@Test
public void testGetLatestNetworkSuggestion_noTimeAvailable() {
mFakeTimeDetectorStrategySpy.setLatestNetworkTime(null);
assertNull(mTimeDetectorService.getLatestNetworkSuggestion());
}
@Test
public void testLatestNetworkTime() {
if (TimeDetectorNetworkTimeHelper.isInUse()) {
NetworkTimeSuggestion latestNetworkSuggestion = createNetworkTimeSuggestion();
mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkSuggestion);
assertEquals(latestNetworkSuggestion.getUnixEpochTime(),
mTimeDetectorService.latestNetworkTime());
} else { } else {
NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult( NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult(
1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123)); 1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123));
when(mMockNtpTrustedTime.getCachedTimeResult()) when(mMockNtpTrustedTime.getCachedTimeResult())
.thenReturn(latestNetworkTime); .thenReturn(latestNetworkTime);
UnixEpochTime expectedUnixEpochTime = new UnixEpochTime( UnixEpochTime expected = new UnixEpochTime(
latestNetworkTime.getElapsedRealtimeMillis(), latestNetworkTime.getElapsedRealtimeMillis(),
latestNetworkTime.getTimeMillis()); latestNetworkTime.getTimeMillis());
NetworkTimeSuggestion expected = new NetworkTimeSuggestion( assertEquals(expected, mTimeDetectorService.latestNetworkTime());
expectedUnixEpochTime, latestNetworkTime.getUncertaintyMillis());
assertEquals(expected, mTimeDetectorService.getLatestNetworkSuggestion());
} }
} }
@Test @Test
public void testGetLatestNetworkSuggestion_noTimeAvailable() { public void testLatestNetworkTime_noTimeAvailable() {
if (TimeDetectorNetworkTimeHelper.isInUse()) { if (TimeDetectorNetworkTimeHelper.isInUse()) {
mFakeTimeDetectorStrategySpy.setLatestNetworkTime(null); mFakeTimeDetectorStrategySpy.setLatestNetworkTime(null);
assertNull(mTimeDetectorService.getLatestNetworkSuggestion());
} else { } else {
when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null); when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null);
assertNull(mTimeDetectorService.getLatestNetworkSuggestion());
} }
assertThrows(ParcelableException.class, () -> mTimeDetectorService.latestNetworkTime());
} }
@Test @Test