diff options
| author | 2020-11-27 19:41:53 +0000 | |
|---|---|---|
| committer | 2020-11-27 19:41:53 +0000 | |
| commit | abab23f3f6f9dbdb49b033648c3fd1e629b4605c (patch) | |
| tree | b3a1ae16fa6564b972e34b06524ad8498ac8ddb0 | |
| parent | 7678ebed57a9834a69dcf16525cc93ff2320cf6f (diff) | |
| parent | 0f61a4acda4d4249a2bbdb655d4e3ecbd7f31456 (diff) | |
Merge "Prepare to make time detection more configurable" am: ebec38b952 am: 0f61a4acda
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1513289
Change-Id: Ic552ef12eeead2c32883c906c8d369d3690a9617
6 files changed, 223 insertions, 62 deletions
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java index c63f306ec84f..6dac6b1773c4 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java @@ -125,7 +125,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub { /** Internal method for handling the auto time setting being changed. */ @VisibleForTesting public void handleAutoTimeDetectionChanged() { - mHandler.post(mTimeDetectorStrategy::handleAutoTimeDetectionChanged); + mHandler.post(mTimeDetectorStrategy::handleAutoTimeConfigChanged); } @Override diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java index 13f0ab605b3a..abd4c8c63a07 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java @@ -16,6 +16,7 @@ package com.android.server.timedetector; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.timedetector.ManualTimeSuggestion; @@ -24,6 +25,8 @@ import android.app.timedetector.TelephonyTimeSuggestion; import android.os.TimestampedValue; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * The interface for the class that implements the time detection algorithm used by the @@ -37,22 +40,41 @@ import java.io.PrintWriter; */ public interface TimeDetectorStrategy { - /** Process the suggested time from telephony sources. */ + @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK }) + @Retention(RetentionPolicy.SOURCE) + @interface Origin {} + + /** Used when a time value originated from a telephony signal. */ + @Origin + int ORIGIN_TELEPHONY = 1; + + /** Used when a time value originated from a user / manual settings. */ + @Origin + int ORIGIN_MANUAL = 2; + + /** Used when a time value originated from a network signal. */ + @Origin + int ORIGIN_NETWORK = 3; + + /** Processes the suggested time from telephony sources. */ void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion); /** - * Process the suggested manually entered time. Returns {@code false} if the suggestion was + * Processes the suggested manually entered time. Returns {@code false} if the suggestion was * invalid, or the device configuration prevented the suggestion being used, {@code true} if the * suggestion was accepted. A suggestion that is valid but does not change the time because it * matches the current device time is considered accepted. */ boolean suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion); - /** Process the suggested time from network sources. */ + /** Processes the suggested time from network sources. */ void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion); - /** Handle the auto-time setting being toggled on or off. */ - void handleAutoTimeDetectionChanged(); + /** + * Handles the auto-time configuration changing For example, when the auto-time setting is + * toggled on or off. + */ + void handleAutoTimeConfigChanged(); /** Dump debug information. */ void dump(@NonNull PrintWriter pw, @Nullable String[] args); @@ -67,4 +89,38 @@ public interface TimeDetectorStrategy { return (referenceClockMillisNow - timeValue.getReferenceTimeMillis()) + timeValue.getValue(); } + + /** + * Converts one of the {@code ORIGIN_} constants to a human readable string suitable for config + * and debug usage. Throws an {@link IllegalArgumentException} if the value is unrecognized. + */ + static String originToString(@Origin int origin) { + switch (origin) { + case ORIGIN_MANUAL: + return "manual"; + case ORIGIN_NETWORK: + return "network"; + case ORIGIN_TELEPHONY: + return "telephony"; + default: + throw new IllegalArgumentException("origin=" + origin); + } + } + + /** + * Converts a human readable config string to one of the {@code ORIGIN_} constants. + * Throws an {@link IllegalArgumentException} if the value is unrecognized. + */ + static @Origin int stringToOrigin(String originString) { + switch (originString) { + case "manual": + return ORIGIN_MANUAL; + case "network": + return ORIGIN_NETWORK; + case "telephony": + return ORIGIN_TELEPHONY; + default: + throw new IllegalArgumentException("originString=" + originString); + } + } } diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java index 6bd107fffeaa..5b6de0518999 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java @@ -16,6 +16,8 @@ package com.android.server.timedetector; +import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin; + import android.annotation.NonNull; import android.app.AlarmManager; import android.content.ContentResolver; @@ -58,6 +60,7 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat @NonNull private final ContentResolver mContentResolver; @NonNull private final PowerManager.WakeLock mWakeLock; @NonNull private final AlarmManager mAlarmManager; + @NonNull private final int[] mOriginPriorities; public TimeDetectorStrategyCallbackImpl(@NonNull Context context) { mContext = Objects.requireNonNull(context); @@ -72,6 +75,15 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat mSystemClockUpdateThresholdMillis = SystemProperties.getInt("ro.sys.time_detector_update_diff", SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT); + + // TODO(b/172230856): Obtain these values from configuration. + String[] originStrings = { "telephony", "network" }; + int[] origins = new int[originStrings.length]; + for (int i = 0; i < originStrings.length; i++) { + int origin = stringToOrigin(originStrings[i]); + origins[i] = origin; + } + mOriginPriorities = origins; } @Override @@ -94,6 +106,11 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat } @Override + public int[] getAutoOriginPriorities() { + return mOriginPriorities; + } + + @Override public void acquireWakeLock() { if (mWakeLock.isHeld()) { Slog.wtf(TAG, "WakeLock " + mWakeLock + " already held"); diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java index a889bdfe17b6..36a3ddd73d89 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java @@ -16,7 +16,8 @@ package com.android.server.timedetector; -import android.annotation.IntDef; +import static com.android.server.timedetector.TimeDetectorStrategy.originToString; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AlarmManager; @@ -34,9 +35,8 @@ import com.android.server.timezonedetector.ArrayMapWithHistory; import com.android.server.timezonedetector.ReferenceWithHistory; import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.time.Instant; +import java.util.Arrays; /** * An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to @@ -64,22 +64,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { static final long MAX_UTC_TIME_AGE_MILLIS = TELEPHONY_BUCKET_COUNT * TELEPHONY_BUCKET_SIZE_MILLIS; - @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK }) - @Retention(RetentionPolicy.SOURCE) - public @interface Origin {} - - /** Used when a time value originated from a telephony signal. */ - @Origin - private static final int ORIGIN_TELEPHONY = 1; - - /** Used when a time value originated from a user / manual settings. */ - @Origin - private static final int ORIGIN_MANUAL = 2; - - /** Used when a time value originated from a network signal. */ - @Origin - private static final int ORIGIN_NETWORK = 3; - /** * CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the * actual system clock time before a warning is logged. Used to help identify situations where @@ -153,6 +137,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { @NonNull Instant autoTimeLowerBound(); + /** + * Returns the order to look at time suggestions when automatically detecting time. + * See {@code #ORIGIN_} constants + */ + @Origin int[] getAutoOriginPriorities(); + /** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */ void acquireWakeLock(); @@ -237,12 +227,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { } @Override - public synchronized void handleAutoTimeDetectionChanged() { + public synchronized void handleAutoTimeConfigChanged() { boolean enabled = mCallback.isAutoTimeDetectionEnabled(); // When automatic time detection is enabled we update the system clock instantly if we can. // Conversely, when automatic time detection is disabled we leave the clock as it is. if (enabled) { - String reason = "Auto time zone detection setting enabled."; + String reason = "Auto time zone detection config changed."; doAutoTimeDetection(reason); } else { // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what @@ -365,33 +355,44 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { return; } - // Android devices currently prioritize any telephony over network signals. There are - // carrier compliance tests that would need to be changed before we could ignore NITZ or - // prefer NTP generally. This check is cheap on devices without telephony hardware. - TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion(); - if (bestTelephonySuggestion != null) { - final TimestampedValue<Long> newUtcTime = bestTelephonySuggestion.getUtcTime(); - String cause = "Found good telephony suggestion." - + ", bestTelephonySuggestion=" + bestTelephonySuggestion - + ", detectionReason=" + detectionReason; - setSystemClockIfRequired(ORIGIN_TELEPHONY, newUtcTime, cause); - return; - } + // Try the different origins one at a time. + int[] originPriorities = mCallback.getAutoOriginPriorities(); + for (int origin : originPriorities) { + TimestampedValue<Long> newUtcTime = null; + String cause = null; + if (origin == ORIGIN_TELEPHONY) { + TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion(); + if (bestTelephonySuggestion != null) { + newUtcTime = bestTelephonySuggestion.getUtcTime(); + cause = "Found good telephony suggestion." + + ", bestTelephonySuggestion=" + bestTelephonySuggestion + + ", detectionReason=" + detectionReason; + } + } else if (origin == ORIGIN_NETWORK) { + NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion(); + if (networkSuggestion != null) { + newUtcTime = networkSuggestion.getUtcTime(); + cause = "Found good network suggestion." + + ", networkSuggestion=" + networkSuggestion + + ", detectionReason=" + detectionReason; + } + } else { + Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin + + " in " + Arrays.toString(originPriorities) + + ": Skipping"); + } - // There is no good telephony suggestion, try network. - NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion(); - if (networkSuggestion != null) { - final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime(); - String cause = "Found good network suggestion." - + ", networkSuggestion=" + networkSuggestion - + ", detectionReason=" + detectionReason; - setSystemClockIfRequired(ORIGIN_NETWORK, newUtcTime, cause); - return; + // Update the system clock if a good suggestion has been found. + if (newUtcTime != null) { + setSystemClockIfRequired(origin, newUtcTime, cause); + return; + } } if (DBG) { - Slog.d(LOG_TAG, "Could not determine time: No best telephony or network suggestion." - + " detectionReason=" + detectionReason); + Slog.d(LOG_TAG, "Could not determine time: No suggestion found in" + + " originPriorities=" + Arrays.toString(originPriorities) + + ", detectionReason=" + detectionReason); } } @@ -476,7 +477,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { // Validate first. TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime(); if (!validateSuggestionUtcTime(elapsedRealtimeMillis, utcTime)) { - Slog.w(LOG_TAG, "Existing suggestion found to be invalid " + Slog.w(LOG_TAG, "Existing suggestion found to be invalid" + " elapsedRealtimeMillis=" + elapsedRealtimeMillis + ", timeSuggestion=" + timeSuggestion); return TELEPHONY_INVALID_SCORE; @@ -525,7 +526,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { if (!mCallback.isAutoTimeDetectionEnabled()) { if (DBG) { Slog.d(LOG_TAG, "Auto time detection is not enabled." - + " origin=" + origin + + " origin=" + originToString(origin) + ", time=" + time + ", cause=" + cause); } @@ -535,7 +536,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { if (mCallback.isAutoTimeDetectionEnabled()) { if (DBG) { Slog.d(LOG_TAG, "Auto time detection is enabled." - + " origin=" + origin + + " origin=" + originToString(origin) + ", time=" + time + ", cause=" + cause); } @@ -557,7 +558,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { @GuardedBy("this") private boolean setSystemClockUnderWakeLock( - int origin, @NonNull TimestampedValue<Long> newTime, @NonNull Object cause) { + @Origin int origin, @NonNull TimestampedValue<Long> newTime, @NonNull String cause) { long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis(); boolean isOriginAutomatic = isOriginAutomatic(origin); diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java index 02031bc4f210..22addf948a53 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java @@ -242,7 +242,7 @@ public class TimeDetectorServiceTest { } @Override - public void handleAutoTimeDetectionChanged() { + public void handleAutoTimeConfigChanged() { mHandleAutoTimeDetectionChangedCalled = true; } diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java index 217de55fb400..c23fb8028224 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java @@ -16,6 +16,9 @@ package com.android.server.timedetector; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -29,6 +32,8 @@ import android.os.TimestampedValue; import androidx.test.runner.AndroidJUnit4; +import com.android.server.timedetector.TimeDetectorStrategy.Origin; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -48,6 +53,9 @@ public class TimeDetectorStrategyImplTest { 123456789L /* realtimeClockMillis */, createUtcTime(2010, 5, 23, 12, 0, 0)); + // This is the traditional ordering for time detection on Android. + private static final @Origin int [] PROVIDERS_PRIORITY = { ORIGIN_TELEPHONY, ORIGIN_NETWORK }; + /** * An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO} * time. Can be used as the basis for time suggestions. @@ -488,11 +496,8 @@ public class TimeDetectorStrategyImplTest { .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion); } - /** - * Manual suggestions should be ignored if auto time is enabled. - */ @Test - public void testSuggestManualTime_autoTimeEnabled() { + public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true); @@ -505,7 +510,7 @@ public class TimeDetectorStrategyImplTest { } @Test - public void suggestManualTime_ignoresTimeLowerBound() { + public void manualTimeSuggestion_ignoresTimeLowerBound() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(false); Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); @@ -658,6 +663,73 @@ public class TimeDetectorStrategyImplTest { .assertLatestNetworkSuggestion(null); } + @Test + public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + Instant networkTime = ARBITRARY_TEST_TIME; + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + TelephonyTimeSuggestion telephonyTimeSuggestion = + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); + + mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion) + .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) + .assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); + } + + @Test + public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + Instant networkTime = ARBITRARY_TEST_TIME; + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + TelephonyTimeSuggestion telephonyTimeSuggestion = + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); + + mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) + .simulateNetworkTimeSuggestion(networkTimeSuggestion) + .assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); + } + + @Test + public void whenHighestPrioritySuggestionIsNotAvailable_fallbacksToNext() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + NetworkTimeSuggestion timeSuggestion = + mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .assertLatestNetworkSuggestion(timeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli()); + } + + @Test + public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(new int[]{ORIGIN_TELEPHONY}); + + NetworkTimeSuggestion timeSuggestion = mScript.generateNetworkTimeSuggestion( + ARBITRARY_TEST_TIME); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .assertLatestNetworkSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + /** * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving * like the real thing should, it also asserts preconditions. @@ -668,6 +740,7 @@ public class TimeDetectorStrategyImplTest { private long mElapsedRealtimeMillis; private long mSystemClockMillis; private int mSystemClockUpdateThresholdMillis = 2000; + private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY; // Tracking operations. private boolean mSystemClockWasSet; @@ -688,6 +761,11 @@ public class TimeDetectorStrategyImplTest { } @Override + public int[] getAutoOriginPriorities() { + return mAutoOriginPriorities; + } + + @Override public void acquireWakeLock() { if (mWakeLockAcquired) { fail("Wake lock already acquired"); @@ -736,6 +814,10 @@ public class TimeDetectorStrategyImplTest { mAutoTimeDetectionEnabled = enabled; } + void pokeAutoOriginPriorities(@Origin int[] autoOriginPriorities) { + mAutoOriginPriorities = autoOriginPriorities; + } + long peekElapsedRealtimeMillis() { return mElapsedRealtimeMillis; } @@ -804,6 +886,11 @@ public class TimeDetectorStrategyImplTest { return this; } + Script pokeAutoOriginPriorities(@Origin int[] autoOriginPriorites) { + mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorites); + return this; + } + long peekElapsedRealtimeMillis() { return mFakeCallback.peekElapsedRealtimeMillis(); } @@ -836,7 +923,7 @@ public class TimeDetectorStrategyImplTest { Script simulateAutoTimeDetectionToggle() { mFakeCallback.simulateAutoTimeZoneDetectionToggle(); - mTimeDetectorStrategy.handleAutoTimeDetectionChanged(); + mTimeDetectorStrategy.handleAutoTimeConfigChanged(); return this; } @@ -870,7 +957,7 @@ public class TimeDetectorStrategyImplTest { Script assertLatestTelephonySuggestion(int slotIndex, TelephonyTimeSuggestion expected) { assertEquals( "Expected to see " + expected + " at slotIndex=" + slotIndex + ", but got " - + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex), + + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex), expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex)); return this; } |