Merge "Introduce system clock time confidence"
This commit is contained in:
@@ -39,6 +39,7 @@ import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROU
|
||||
import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
|
||||
import static android.os.UserHandle.USER_SYSTEM;
|
||||
|
||||
import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
|
||||
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
|
||||
import static com.android.server.SystemTimeZone.getTimeZoneId;
|
||||
import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
|
||||
@@ -58,6 +59,8 @@ import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_R
|
||||
import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_UNDEFINED;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.Activity;
|
||||
@@ -87,7 +90,6 @@ import android.os.BatteryManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -101,7 +103,6 @@ import android.os.ServiceManager;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.ThreadLocalWorkSource;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
@@ -145,6 +146,8 @@ import com.android.server.DeviceIdleInternal;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.JobSchedulerBackgroundThread;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemClockTime;
|
||||
import com.android.server.SystemClockTime.TimeConfidence;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.SystemServiceManager;
|
||||
import com.android.server.SystemTimeZone;
|
||||
@@ -1417,7 +1420,7 @@ public class AlarmManagerService extends SystemService {
|
||||
|
||||
private long convertToElapsed(long when, int type) {
|
||||
if (isRtc(type)) {
|
||||
when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime();
|
||||
when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtimeMillis();
|
||||
}
|
||||
return when;
|
||||
}
|
||||
@@ -1577,7 +1580,7 @@ public class AlarmManagerService extends SystemService {
|
||||
alarmsToDeliver = alarmsForUid;
|
||||
mPendingBackgroundAlarms.remove(uid);
|
||||
}
|
||||
deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
|
||||
deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1594,7 +1597,8 @@ public class AlarmManagerService extends SystemService {
|
||||
mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
|
||||
|
||||
if (alarmsToDeliver.size() > 0) {
|
||||
deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
|
||||
deliverPendingBackgroundAlarmsLocked(
|
||||
alarmsToDeliver, mInjector.getElapsedRealtimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1908,17 +1912,8 @@ public class AlarmManagerService extends SystemService {
|
||||
mInjector.syncKernelTimeZoneOffset();
|
||||
}
|
||||
|
||||
// Ensure that we're booting with a halfway sensible current time. Use the
|
||||
// most recent of Build.TIME, the root file system's timestamp, and the
|
||||
// value of the ro.build.date.utc system property (which is in seconds).
|
||||
final long systemBuildTime = Long.max(
|
||||
1000L * SystemProperties.getLong("ro.build.date.utc", -1L),
|
||||
Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
|
||||
if (mInjector.getCurrentTimeMillis() < systemBuildTime) {
|
||||
Slog.i(TAG, "Current time only " + mInjector.getCurrentTimeMillis()
|
||||
+ ", advancing to build time " + systemBuildTime);
|
||||
mInjector.setKernelTime(systemBuildTime);
|
||||
}
|
||||
// Ensure that we're booting with a halfway sensible current time.
|
||||
mInjector.initializeTimeIfRequired();
|
||||
|
||||
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
|
||||
// Determine SysUI's uid
|
||||
@@ -2133,21 +2128,18 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
boolean setTimeImpl(long millis) {
|
||||
if (!mInjector.isAlarmDriverPresent()) {
|
||||
Slog.w(TAG, "Not setting time since no alarm driver is available.");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean setTimeImpl(
|
||||
@CurrentTimeMillisLong long newSystemClockTimeMillis, @TimeConfidence int confidence,
|
||||
@NonNull String logMsg) {
|
||||
synchronized (mLock) {
|
||||
final long currentTimeMillis = mInjector.getCurrentTimeMillis();
|
||||
mInjector.setKernelTime(millis);
|
||||
final long oldSystemClockTimeMillis = mInjector.getCurrentTimeMillis();
|
||||
mInjector.setCurrentTimeMillis(newSystemClockTimeMillis, confidence, logMsg);
|
||||
|
||||
if (KERNEL_TIME_ZONE_SYNC_ENABLED) {
|
||||
// Changing the time may cross a DST transition; sync the kernel offset if needed.
|
||||
final TimeZone timeZone = TimeZone.getTimeZone(SystemTimeZone.getTimeZoneId());
|
||||
final int currentTzOffset = timeZone.getOffset(currentTimeMillis);
|
||||
final int newTzOffset = timeZone.getOffset(millis);
|
||||
final int currentTzOffset = timeZone.getOffset(oldSystemClockTimeMillis);
|
||||
final int newTzOffset = timeZone.getOffset(newSystemClockTimeMillis);
|
||||
if (currentTzOffset != newTzOffset) {
|
||||
Slog.i(TAG, "Timezone offset has changed, updating kernel timezone");
|
||||
mInjector.setKernelTimeZoneOffset(newTzOffset);
|
||||
@@ -2260,7 +2252,7 @@ public class AlarmManagerService extends SystemService {
|
||||
triggerAtTime = 0;
|
||||
}
|
||||
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
final long nominalTrigger = convertToElapsed(triggerAtTime, type);
|
||||
// Try to prevent spamming by making sure apps aren't firing alarms in the immediate future
|
||||
final long minTrigger = nowElapsed
|
||||
@@ -2383,7 +2375,7 @@ public class AlarmManagerService extends SystemService {
|
||||
// No need to fuzz as this is already earlier than the coming wake-from-idle.
|
||||
return changedBeforeFuzz;
|
||||
}
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
final long futurity = upcomingWakeFromIdle - nowElapsed;
|
||||
|
||||
if (futurity <= mConstants.MIN_DEVICE_IDLE_FUZZ) {
|
||||
@@ -2405,7 +2397,7 @@ public class AlarmManagerService extends SystemService {
|
||||
* @return {@code true} if the alarm delivery time was updated.
|
||||
*/
|
||||
private boolean adjustDeliveryTimeBasedOnBatterySaver(Alarm alarm) {
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
if (isExemptFromBatterySaver(alarm)) {
|
||||
return false;
|
||||
}
|
||||
@@ -2472,7 +2464,7 @@ public class AlarmManagerService extends SystemService {
|
||||
* @return {@code true} if the alarm delivery time was updated.
|
||||
*/
|
||||
private boolean adjustDeliveryTimeBasedOnDeviceIdle(Alarm alarm) {
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
if (mPendingIdleUntil == null || mPendingIdleUntil == alarm) {
|
||||
return alarm.setPolicyElapsed(DEVICE_IDLE_POLICY_INDEX, nowElapsed);
|
||||
}
|
||||
@@ -2527,7 +2519,7 @@ public class AlarmManagerService extends SystemService {
|
||||
* adjustments made in this call.
|
||||
*/
|
||||
private boolean adjustDeliveryTimeBasedOnBucketLocked(Alarm alarm) {
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
if (mConstants.USE_TARE_POLICY || isExemptFromAppStandby(alarm) || mAppStandbyParole) {
|
||||
return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed);
|
||||
}
|
||||
@@ -2587,7 +2579,7 @@ public class AlarmManagerService extends SystemService {
|
||||
* adjustments made in this call.
|
||||
*/
|
||||
private boolean adjustDeliveryTimeBasedOnTareLocked(Alarm alarm) {
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
if (!mConstants.USE_TARE_POLICY
|
||||
|| isExemptFromTare(alarm) || hasEnoughWealthLocked(alarm)) {
|
||||
return alarm.setPolicyElapsed(TARE_POLICY_INDEX, nowElapsed);
|
||||
@@ -2643,7 +2635,7 @@ public class AlarmManagerService extends SystemService {
|
||||
ent.pkg = a.sourcePackage;
|
||||
ent.tag = a.statsTag;
|
||||
ent.op = "START IDLE";
|
||||
ent.elapsedRealtime = mInjector.getElapsedRealtime();
|
||||
ent.elapsedRealtime = mInjector.getElapsedRealtimeMillis();
|
||||
ent.argRealtime = a.getWhenElapsed();
|
||||
mAllowWhileIdleDispatches.add(ent);
|
||||
}
|
||||
@@ -2718,6 +2710,13 @@ public class AlarmManagerService extends SystemService {
|
||||
setTimeZoneImpl(tzId, confidence);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTime(
|
||||
@CurrentTimeMillisLong long unixEpochTimeMillis, int confidence,
|
||||
String logMsg) {
|
||||
setTimeImpl(unixEpochTimeMillis, confidence, logMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInFlightListener(InFlightListener callback) {
|
||||
synchronized (mLock) {
|
||||
@@ -2987,12 +2986,16 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setTime(long millis) {
|
||||
public boolean setTime(@CurrentTimeMillisLong long millis) {
|
||||
getContext().enforceCallingOrSelfPermission(
|
||||
"android.permission.SET_TIME",
|
||||
"setTime");
|
||||
|
||||
return setTimeImpl(millis);
|
||||
// The public API (and the shell command that also uses this method) have no concept
|
||||
// of confidence, but since the time should come either from apps working on behalf of
|
||||
// the user or a developer, confidence is assumed "high".
|
||||
final int timeConfidence = TIME_CONFIDENCE_HIGH;
|
||||
return setTimeImpl(millis, timeConfidence, "AlarmManager.setTime() called");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3142,7 +3145,7 @@ public class AlarmManagerService extends SystemService {
|
||||
pw.println();
|
||||
}
|
||||
|
||||
final long nowELAPSED = mInjector.getElapsedRealtime();
|
||||
final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
|
||||
final long nowUPTIME = SystemClock.uptimeMillis();
|
||||
final long nowRTC = mInjector.getCurrentTimeMillis();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
@@ -3618,7 +3621,7 @@ public class AlarmManagerService extends SystemService {
|
||||
|
||||
synchronized (mLock) {
|
||||
final long nowRTC = mInjector.getCurrentTimeMillis();
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC);
|
||||
proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed);
|
||||
proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME,
|
||||
@@ -3956,7 +3959,7 @@ public class AlarmManagerService extends SystemService {
|
||||
void rescheduleKernelAlarmsLocked() {
|
||||
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
|
||||
// prior to that which contains no wakeups, we schedule that as well.
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
long nextNonWakeup = 0;
|
||||
if (mAlarmStore.size() > 0) {
|
||||
final long firstWakeup = mAlarmStore.getNextWakeupDeliveryTime();
|
||||
@@ -4069,7 +4072,7 @@ public class AlarmManagerService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
private void removeAlarmsInternalLocked(Predicate<Alarm> whichAlarms, int reason) {
|
||||
final long nowRtc = mInjector.getCurrentTimeMillis();
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
final long nowElapsed = mInjector.getElapsedRealtimeMillis();
|
||||
|
||||
final ArrayList<Alarm> removedAlarms = mAlarmStore.remove(whichAlarms);
|
||||
final boolean removedFromStore = !removedAlarms.isEmpty();
|
||||
@@ -4208,7 +4211,7 @@ public class AlarmManagerService extends SystemService {
|
||||
void interactiveStateChangedLocked(boolean interactive) {
|
||||
if (mInteractive != interactive) {
|
||||
mInteractive = interactive;
|
||||
final long nowELAPSED = mInjector.getElapsedRealtime();
|
||||
final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
|
||||
if (interactive) {
|
||||
if (mPendingNonWakeupAlarms.size() > 0) {
|
||||
final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
|
||||
@@ -4310,7 +4313,6 @@ public class AlarmManagerService extends SystemService {
|
||||
private static native void close(long nativeData);
|
||||
private static native int set(long nativeData, int type, long seconds, long nanoseconds);
|
||||
private static native int waitForAlarm(long nativeData);
|
||||
private static native int setKernelTime(long nativeData, long millis);
|
||||
|
||||
/*
|
||||
* b/246256335: The @Keep ensures that the native definition is kept even when the optimizer can
|
||||
@@ -4357,7 +4359,7 @@ public class AlarmManagerService extends SystemService {
|
||||
ent.pkg = alarm.sourcePackage;
|
||||
ent.tag = alarm.statsTag;
|
||||
ent.op = "END IDLE";
|
||||
ent.elapsedRealtime = mInjector.getElapsedRealtime();
|
||||
ent.elapsedRealtime = mInjector.getElapsedRealtimeMillis();
|
||||
ent.argRealtime = alarm.getWhenElapsed();
|
||||
mAllowWhileIdleDispatches.add(ent);
|
||||
}
|
||||
@@ -4602,20 +4604,27 @@ public class AlarmManagerService extends SystemService {
|
||||
setKernelTimeZoneOffset(utcOffsetMillis);
|
||||
}
|
||||
|
||||
void setKernelTime(long millis) {
|
||||
if (mNativeData != 0) {
|
||||
AlarmManagerService.setKernelTime(mNativeData, millis);
|
||||
}
|
||||
void initializeTimeIfRequired() {
|
||||
SystemClockTime.initializeIfRequired();
|
||||
}
|
||||
|
||||
void setCurrentTimeMillis(
|
||||
@CurrentTimeMillisLong long unixEpochMillis,
|
||||
@TimeConfidence int confidence,
|
||||
@NonNull String logMsg) {
|
||||
SystemClockTime.setTimeAndConfidence(unixEpochMillis, confidence, logMsg);
|
||||
}
|
||||
|
||||
void close() {
|
||||
AlarmManagerService.close(mNativeData);
|
||||
}
|
||||
|
||||
long getElapsedRealtime() {
|
||||
@ElapsedRealtimeLong
|
||||
long getElapsedRealtimeMillis() {
|
||||
return SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
@CurrentTimeMillisLong
|
||||
long getCurrentTimeMillis() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
@@ -4665,7 +4674,7 @@ public class AlarmManagerService extends SystemService {
|
||||
while (true) {
|
||||
int result = mInjector.waitForAlarm();
|
||||
final long nowRTC = mInjector.getCurrentTimeMillis();
|
||||
final long nowELAPSED = mInjector.getElapsedRealtime();
|
||||
final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
|
||||
synchronized (mLock) {
|
||||
mLastWakeup = nowELAPSED;
|
||||
}
|
||||
@@ -4913,7 +4922,7 @@ public class AlarmManagerService extends SystemService {
|
||||
// this way, so WAKE_UP alarms will be delivered only when the device is awake.
|
||||
ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
|
||||
synchronized (mLock) {
|
||||
final long nowELAPSED = mInjector.getElapsedRealtime();
|
||||
final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
|
||||
triggerAlarmsLocked(triggerList, nowELAPSED);
|
||||
updateNextAlarmClockLocked();
|
||||
}
|
||||
@@ -5090,7 +5099,7 @@ public class AlarmManagerService extends SystemService {
|
||||
flags |= mConstants.TIME_TICK_ALLOWED_WHILE_IDLE ? FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
|
||||
: 0;
|
||||
|
||||
setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0,
|
||||
setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtimeMillis() + tickEventDelay, 0,
|
||||
0, null, mTimeTickTrigger, TIME_TICK_TAG, flags, workSource, null,
|
||||
Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST);
|
||||
|
||||
@@ -5277,7 +5286,7 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mTemporaryQuotaReserve.replenishQuota(packageName, userId, quotaBump,
|
||||
mInjector.getElapsedRealtime());
|
||||
mInjector.getElapsedRealtimeMillis());
|
||||
}
|
||||
mHandler.obtainMessage(AlarmHandler.TEMPORARY_QUOTA_CHANGED, userId, -1,
|
||||
packageName).sendToTarget();
|
||||
@@ -5439,7 +5448,7 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private void updateStatsLocked(InFlight inflight) {
|
||||
final long nowELAPSED = mInjector.getElapsedRealtime();
|
||||
final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
|
||||
BroadcastStats bs = inflight.mBroadcastStats;
|
||||
bs.nesting--;
|
||||
if (bs.nesting <= 0) {
|
||||
|
||||
@@ -76,19 +76,17 @@ typedef std::array<int, N_ANDROID_TIMERFDS> TimerFds;
|
||||
class AlarmImpl
|
||||
{
|
||||
public:
|
||||
AlarmImpl(const TimerFds &fds, int epollfd, const std::string &rtc_dev)
|
||||
: fds{fds}, epollfd{epollfd}, rtc_dev{rtc_dev} {}
|
||||
AlarmImpl(const TimerFds &fds, int epollfd)
|
||||
: fds{fds}, epollfd{epollfd} {}
|
||||
~AlarmImpl();
|
||||
|
||||
int set(int type, struct timespec *ts);
|
||||
int setTime(struct timeval *tv);
|
||||
int waitForAlarm();
|
||||
int getTime(int type, struct itimerspec *spec);
|
||||
|
||||
private:
|
||||
const TimerFds fds;
|
||||
const int epollfd;
|
||||
std::string rtc_dev;
|
||||
};
|
||||
|
||||
AlarmImpl::~AlarmImpl()
|
||||
@@ -131,43 +129,6 @@ int AlarmImpl::getTime(int type, struct itimerspec *spec)
|
||||
return timerfd_gettime(fds[type], spec);
|
||||
}
|
||||
|
||||
int AlarmImpl::setTime(struct timeval *tv)
|
||||
{
|
||||
if (settimeofday(tv, NULL) == -1) {
|
||||
ALOGV("settimeofday() failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
android::base::unique_fd fd{open(rtc_dev.c_str(), O_RDWR)};
|
||||
if (!fd.ok()) {
|
||||
ALOGE("Unable to open %s: %s", rtc_dev.c_str(), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct tm tm;
|
||||
if (!gmtime_r(&tv->tv_sec, &tm)) {
|
||||
ALOGV("gmtime_r() failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct rtc_time rtc = {};
|
||||
rtc.tm_sec = tm.tm_sec;
|
||||
rtc.tm_min = tm.tm_min;
|
||||
rtc.tm_hour = tm.tm_hour;
|
||||
rtc.tm_mday = tm.tm_mday;
|
||||
rtc.tm_mon = tm.tm_mon;
|
||||
rtc.tm_year = tm.tm_year;
|
||||
rtc.tm_wday = tm.tm_wday;
|
||||
rtc.tm_yday = tm.tm_yday;
|
||||
rtc.tm_isdst = tm.tm_isdst;
|
||||
if (ioctl(fd, RTC_SET_TIME, &rtc) == -1) {
|
||||
ALOGV("RTC_SET_TIME ioctl failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AlarmImpl::waitForAlarm()
|
||||
{
|
||||
epoll_event events[N_ANDROID_TIMERFDS];
|
||||
@@ -198,28 +159,6 @@ int AlarmImpl::waitForAlarm()
|
||||
return result;
|
||||
}
|
||||
|
||||
static jint android_server_alarm_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
|
||||
{
|
||||
AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
|
||||
|
||||
if (millis <= 0 || millis / 1000LL >= std::numeric_limits<time_t>::max()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = (millis / 1000LL);
|
||||
tv.tv_usec = ((millis % 1000LL) * 1000LL);
|
||||
|
||||
ALOGD("Setting time of day to sec=%ld", tv.tv_sec);
|
||||
|
||||
int ret = impl->setTime(&tv);
|
||||
if (ret < 0) {
|
||||
ALOGW("Unable to set rtc to %ld: %s", tv.tv_sec, strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jint android_server_alarm_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
|
||||
{
|
||||
struct timezone tz;
|
||||
@@ -287,19 +226,7 @@ static jlong android_server_alarm_AlarmManagerService_init(JNIEnv*, jobject)
|
||||
}
|
||||
}
|
||||
|
||||
// Find the wall clock RTC. We expect this always to be /dev/rtc0, but
|
||||
// check the /dev/rtc symlink first so that legacy devices that don't use
|
||||
// rtc0 can add a symlink rather than need to carry a local patch to this
|
||||
// code.
|
||||
//
|
||||
// TODO: if you're reading this in a world where all devices are using the
|
||||
// GKI, you can remove the readlink and just assume /dev/rtc0.
|
||||
std::string dev_rtc;
|
||||
if (!android::base::Readlink("/dev/rtc", &dev_rtc)) {
|
||||
dev_rtc = "/dev/rtc0";
|
||||
}
|
||||
|
||||
std::unique_ptr<AlarmImpl> alarm{new AlarmImpl(fds, epollfd, dev_rtc)};
|
||||
std::unique_ptr<AlarmImpl> alarm{new AlarmImpl(fds, epollfd)};
|
||||
|
||||
for (size_t i = 0; i < fds.size(); i++) {
|
||||
epoll_event event;
|
||||
@@ -392,7 +319,6 @@ static const JNINativeMethod sMethods[] = {
|
||||
{"close", "(J)V", (void*)android_server_alarm_AlarmManagerService_close},
|
||||
{"set", "(JIJJ)I", (void*)android_server_alarm_AlarmManagerService_set},
|
||||
{"waitForAlarm", "(J)I", (void*)android_server_alarm_AlarmManagerService_waitForAlarm},
|
||||
{"setKernelTime", "(JJ)I", (void*)android_server_alarm_AlarmManagerService_setKernelTime},
|
||||
{"setKernelTimezone", "(JI)I", (void*)android_server_alarm_AlarmManagerService_setKernelTimezone},
|
||||
{"getNextAlarm", "(JI)J", (void*)android_server_alarm_AlarmManagerService_getNextAlarm},
|
||||
};
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.app.PendingIntent;
|
||||
|
||||
import com.android.server.SystemClockTime.TimeConfidence;
|
||||
import com.android.server.SystemTimeZone.TimeZoneConfidence;
|
||||
|
||||
public interface AlarmManagerInternal {
|
||||
@@ -59,4 +61,15 @@ public interface AlarmManagerInternal {
|
||||
* for details
|
||||
*/
|
||||
void setTimeZone(String tzId, @TimeZoneConfidence int confidence);
|
||||
|
||||
/**
|
||||
* Sets the device's current time and time confidence.
|
||||
*
|
||||
* @param unixEpochTimeMillis the time
|
||||
* @param confidence the confidence that {@code unixEpochTimeMillis} is correct, see {@link
|
||||
* TimeConfidence} for details
|
||||
* @param logMsg the reason the time is being changed, for bug report logging
|
||||
*/
|
||||
void setTime(@CurrentTimeMillisLong long unixEpochTimeMillis, @TimeConfidence int confidence,
|
||||
String logMsg);
|
||||
}
|
||||
|
||||
174
services/core/java/com/android/server/SystemClockTime.java
Normal file
174
services/core/java/com/android/server/SystemClockTime.java
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2022 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 com.android.server;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.LocalLog;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* A set of static methods that encapsulate knowledge of how the system clock time and associated
|
||||
* metadata are stored on Android.
|
||||
*/
|
||||
public final class SystemClockTime {
|
||||
|
||||
private static final String TAG = "SystemClockTime";
|
||||
|
||||
/**
|
||||
* A log that records the decisions / decision metadata that affected the device's system clock
|
||||
* time. This is logged in bug reports to assist with debugging issues with time.
|
||||
*/
|
||||
@NonNull
|
||||
private static final LocalLog sTimeDebugLog =
|
||||
new LocalLog(30, false /* useLocalTimestamps */);
|
||||
|
||||
|
||||
/**
|
||||
* An annotation that indicates a "time confidence" value is expected.
|
||||
*
|
||||
* <p>The confidence indicates whether the time is expected to be correct. The confidence can be
|
||||
* upgraded or downgraded over time. It can be used to decide whether a user could / should be
|
||||
* asked to confirm the time. For example, during device set up low confidence would describe a
|
||||
* time that has been initialized by default. The user may then be asked to confirm the time,
|
||||
* moving it to a high confidence.
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target(TYPE_USE)
|
||||
@IntDef(prefix = "TIME_CONFIDENCE_",
|
||||
value = { TIME_CONFIDENCE_LOW, TIME_CONFIDENCE_HIGH })
|
||||
public @interface TimeConfidence {
|
||||
}
|
||||
|
||||
/** Used when confidence is low and would (ideally) be confirmed by a user. */
|
||||
public static final @TimeConfidence int TIME_CONFIDENCE_LOW = 0;
|
||||
|
||||
/**
|
||||
* Used when confidence in the time is high and does not need to be confirmed by a user.
|
||||
*/
|
||||
public static final @TimeConfidence int TIME_CONFIDENCE_HIGH = 100;
|
||||
|
||||
/**
|
||||
* The confidence in the current time. Android's time confidence is held in memory because RTC
|
||||
* hardware can forget / corrupt the time while the device is powered off. Therefore, on boot
|
||||
* we can't assume the time is good, and so default it to "low" confidence until it is confirmed
|
||||
* or explicitly set.
|
||||
*/
|
||||
private static @TimeConfidence int sTimeConfidence = TIME_CONFIDENCE_LOW;
|
||||
|
||||
private static final long sNativeData = init();
|
||||
|
||||
private SystemClockTime() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system clock time to a reasonable lower bound. Used during boot-up to ensure the
|
||||
* device has a time that is better than a default like 1970-01-01.
|
||||
*/
|
||||
public static void initializeIfRequired() {
|
||||
// Use the most recent of Build.TIME, the root file system's timestamp, and the
|
||||
// value of the ro.build.date.utc system property (which is in seconds).
|
||||
final long systemBuildTime = Long.max(
|
||||
1000L * SystemProperties.getLong("ro.build.date.utc", -1L),
|
||||
Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
|
||||
long currentTimeMillis = getCurrentTimeMillis();
|
||||
if (currentTimeMillis < systemBuildTime) {
|
||||
String logMsg = "Current time only " + currentTimeMillis
|
||||
+ ", advancing to build time " + systemBuildTime;
|
||||
Slog.i(TAG, logMsg);
|
||||
setTimeAndConfidence(systemBuildTime, TIME_CONFIDENCE_LOW, logMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system clock time and confidence. See also {@link #setConfidence(int, String)} for
|
||||
* an alternative that only sets the confidence.
|
||||
*
|
||||
* @param unixEpochMillis the time to set
|
||||
* @param confidence the confidence in {@code unixEpochMillis}. See {@link TimeConfidence} for
|
||||
* details.
|
||||
* @param logMsg a log message that can be included in bug reports that explains the update
|
||||
*/
|
||||
public static void setTimeAndConfidence(
|
||||
@CurrentTimeMillisLong long unixEpochMillis, int confidence, @NonNull String logMsg) {
|
||||
synchronized (SystemClockTime.class) {
|
||||
setTime(sNativeData, unixEpochMillis);
|
||||
sTimeConfidence = confidence;
|
||||
sTimeDebugLog.log(logMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system clock confidence. See also {@link #setTimeAndConfidence(long, int, String)}
|
||||
* for an alternative that sets the time and confidence.
|
||||
*
|
||||
* @param confidence the confidence in the system clock time. See {@link TimeConfidence} for
|
||||
* details.
|
||||
* @param logMsg a log message that can be included in bug reports that explains the update
|
||||
*/
|
||||
public static void setConfidence(@TimeConfidence int confidence, @NonNull String logMsg) {
|
||||
synchronized (SystemClockTime.class) {
|
||||
sTimeConfidence = confidence;
|
||||
sTimeDebugLog.log(logMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the system clock time. The same as {@link System#currentTimeMillis()}.
|
||||
*/
|
||||
private static @CurrentTimeMillisLong long getCurrentTimeMillis() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the system clock confidence. See {@link TimeConfidence} for details.
|
||||
*/
|
||||
public static @TimeConfidence int getTimeConfidence() {
|
||||
synchronized (SystemClockTime.class) {
|
||||
return sTimeConfidence;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry to the system time debug log that is included in bug reports. This method is
|
||||
* intended to be used to record event that may lead to a time change, e.g. config or mode
|
||||
* changes.
|
||||
*/
|
||||
public static void addDebugLogEntry(@NonNull String logMsg) {
|
||||
sTimeDebugLog.log(logMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps information about recent time / confidence changes to the supplied writer.
|
||||
*/
|
||||
public static void dump(PrintWriter writer) {
|
||||
sTimeDebugLog.dump(writer);
|
||||
}
|
||||
|
||||
private static native long init();
|
||||
private static native int setTime(long nativeData, @CurrentTimeMillisLong long millis);
|
||||
}
|
||||
@@ -46,6 +46,7 @@ public final class ConfigurationInternal {
|
||||
|
||||
private final boolean mAutoDetectionSupported;
|
||||
private final int mSystemClockUpdateThresholdMillis;
|
||||
private final int mSystemClockConfidenceUpgradeThresholdMillis;
|
||||
private final Instant mAutoSuggestionLowerBound;
|
||||
private final Instant mManualSuggestionLowerBound;
|
||||
private final Instant mSuggestionUpperBound;
|
||||
@@ -57,6 +58,8 @@ public final class ConfigurationInternal {
|
||||
private ConfigurationInternal(Builder builder) {
|
||||
mAutoDetectionSupported = builder.mAutoDetectionSupported;
|
||||
mSystemClockUpdateThresholdMillis = builder.mSystemClockUpdateThresholdMillis;
|
||||
mSystemClockConfidenceUpgradeThresholdMillis =
|
||||
builder.mSystemClockConfidenceUpgradeThresholdMillis;
|
||||
mAutoSuggestionLowerBound = Objects.requireNonNull(builder.mAutoSuggestionLowerBound);
|
||||
mManualSuggestionLowerBound = Objects.requireNonNull(builder.mManualSuggestionLowerBound);
|
||||
mSuggestionUpperBound = Objects.requireNonNull(builder.mSuggestionUpperBound);
|
||||
@@ -81,6 +84,17 @@ public final class ConfigurationInternal {
|
||||
return mSystemClockUpdateThresholdMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the absolute threshold at/below which the system clock confidence can be upgraded.
|
||||
* i.e. if the detector receives a high-confidence time and the current system clock is +/- this
|
||||
* value from that time and the confidence in the time is low, then the device's confidence in
|
||||
* the current system clock time can be upgraded. This needs to be an amount users would
|
||||
* consider "close enough".
|
||||
*/
|
||||
public int getSystemClockConfidenceUpgradeThresholdMillis() {
|
||||
return mSystemClockConfidenceUpgradeThresholdMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lower bound for valid automatic time suggestions. It is guaranteed to be in the
|
||||
* past, i.e. it is unrelated to the current system clock time.
|
||||
@@ -242,6 +256,8 @@ public final class ConfigurationInternal {
|
||||
return "ConfigurationInternal{"
|
||||
+ "mAutoDetectionSupported=" + mAutoDetectionSupported
|
||||
+ ", mSystemClockUpdateThresholdMillis=" + mSystemClockUpdateThresholdMillis
|
||||
+ ", mSystemClockConfidenceUpgradeThresholdMillis="
|
||||
+ mSystemClockConfidenceUpgradeThresholdMillis
|
||||
+ ", mAutoSuggestionLowerBound=" + mAutoSuggestionLowerBound
|
||||
+ "(" + mAutoSuggestionLowerBound.toEpochMilli() + ")"
|
||||
+ ", mManualSuggestionLowerBound=" + mManualSuggestionLowerBound
|
||||
@@ -258,6 +274,7 @@ public final class ConfigurationInternal {
|
||||
static final class Builder {
|
||||
private boolean mAutoDetectionSupported;
|
||||
private int mSystemClockUpdateThresholdMillis;
|
||||
private int mSystemClockConfidenceUpgradeThresholdMillis;
|
||||
@NonNull private Instant mAutoSuggestionLowerBound;
|
||||
@NonNull private Instant mManualSuggestionLowerBound;
|
||||
@NonNull private Instant mSuggestionUpperBound;
|
||||
@@ -286,68 +303,55 @@ public final class ConfigurationInternal {
|
||||
this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the user is allowed to configure time settings on this device.
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#isUserConfigAllowed()}. */
|
||||
Builder setUserConfigAllowed(boolean userConfigAllowed) {
|
||||
mUserConfigAllowed = userConfigAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether automatic time detection is supported on this device.
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#isAutoDetectionSupported()}. */
|
||||
public Builder setAutoDetectionSupported(boolean supported) {
|
||||
mAutoDetectionSupported = supported;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the absolute threshold below which the system clock need not be updated. i.e. if
|
||||
* setting the system clock would adjust it by less than this (either backwards or forwards)
|
||||
* then it need not be set.
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#getSystemClockUpdateThresholdMillis()}. */
|
||||
public Builder setSystemClockUpdateThresholdMillis(int systemClockUpdateThresholdMillis) {
|
||||
mSystemClockUpdateThresholdMillis = systemClockUpdateThresholdMillis;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lower bound for valid automatic time suggestions.
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#getSystemClockConfidenceUpgradeThresholdMillis()}. */
|
||||
public Builder setSystemClockConfidenceUpgradeThresholdMillis(int thresholdMillis) {
|
||||
mSystemClockConfidenceUpgradeThresholdMillis = thresholdMillis;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** See {@link ConfigurationInternal#getAutoSuggestionLowerBound()}. */
|
||||
public Builder setAutoSuggestionLowerBound(@NonNull Instant autoSuggestionLowerBound) {
|
||||
mAutoSuggestionLowerBound = Objects.requireNonNull(autoSuggestionLowerBound);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lower bound for valid manual time suggestions.
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#getManualSuggestionLowerBound()}. */
|
||||
public Builder setManualSuggestionLowerBound(@NonNull Instant manualSuggestionLowerBound) {
|
||||
mManualSuggestionLowerBound = Objects.requireNonNull(manualSuggestionLowerBound);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the upper bound for valid time suggestions (manual and automatic).
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#getSuggestionUpperBound()}. */
|
||||
public Builder setSuggestionUpperBound(@NonNull Instant suggestionUpperBound) {
|
||||
mSuggestionUpperBound = Objects.requireNonNull(suggestionUpperBound);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the order to look at time suggestions when automatically detecting time.
|
||||
* See {@code #ORIGIN_} constants
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#getAutoOriginPriorities()}. */
|
||||
public Builder setOriginPriorities(@NonNull @Origin int... originPriorities) {
|
||||
mOriginPriorities = Objects.requireNonNull(originPriorities);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the automatic time detection enabled setting for this device.
|
||||
*/
|
||||
/** See {@link ConfigurationInternal#getAutoDetectionEnabledSetting()}. */
|
||||
Builder setAutoDetectionEnabledSetting(boolean autoDetectionEnabledSetting) {
|
||||
mAutoDetectionEnabledSetting = autoDetectionEnabledSetting;
|
||||
return this;
|
||||
|
||||
@@ -16,16 +16,21 @@
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.AlarmManager;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.AlarmManagerInternal;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemClockTime;
|
||||
import com.android.server.SystemClockTime.TimeConfidence;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -38,7 +43,7 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
|
||||
@NonNull private final PowerManager.WakeLock mWakeLock;
|
||||
@NonNull private final AlarmManager mAlarmManager;
|
||||
@NonNull private final AlarmManagerInternal mAlarmManagerInternal;
|
||||
|
||||
EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
|
||||
@NonNull ServiceConfigAccessor serviceConfigAccessor) {
|
||||
@@ -49,7 +54,8 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
|
||||
mWakeLock = Objects.requireNonNull(
|
||||
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG));
|
||||
|
||||
mAlarmManager = Objects.requireNonNull(context.getSystemService(AlarmManager.class));
|
||||
mAlarmManagerInternal = Objects.requireNonNull(
|
||||
LocalServices.getService(AlarmManagerInternal.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,9 +90,22 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemClock(long newTimeMillis) {
|
||||
public @TimeConfidence int systemClockConfidence() {
|
||||
return SystemClockTime.getTimeConfidence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemClock(
|
||||
@CurrentTimeMillisLong long newTimeMillis, @TimeConfidence int confidence,
|
||||
@NonNull String logMsg) {
|
||||
checkWakeLockHeld();
|
||||
mAlarmManager.setTime(newTimeMillis);
|
||||
mAlarmManagerInternal.setTime(newTimeMillis, confidence, logMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemClockConfidence(@TimeConfidence int confidence, @NonNull String logMsg) {
|
||||
checkWakeLockHeld();
|
||||
SystemClockTime.setConfidence(confidence, logMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,4 +119,13 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
|
||||
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " not held");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugLogEntry(@NonNull String logMsg) {
|
||||
SystemClockTime.addDebugLogEntry(logMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpDebugLog(@NonNull PrintWriter printWriter) {
|
||||
SystemClockTime.dump(printWriter);
|
||||
}}
|
||||
|
||||
@@ -67,6 +67,15 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
|
||||
|
||||
private static final int SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT = 2 * 1000;
|
||||
|
||||
/**
|
||||
* An absolute threshold at/below which the system clock confidence can be upgraded. i.e. if the
|
||||
* detector receives a high-confidence time and the current system clock is +/- this value from
|
||||
* that time and the confidence in the time is low, then the device's confidence in the current
|
||||
* system clock time can be upgraded. This needs to be an amount users would consider
|
||||
* "close enough".
|
||||
*/
|
||||
private static final int SYSTEM_CLOCK_CONFIRMATION_THRESHOLD_MILLIS = 1000;
|
||||
|
||||
/**
|
||||
* By default telephony and network only suggestions are accepted and telephony takes
|
||||
* precedence over network.
|
||||
@@ -236,6 +245,8 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
|
||||
.setAutoDetectionSupported(isAutoDetectionSupported())
|
||||
.setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
|
||||
.setSystemClockUpdateThresholdMillis(getSystemClockUpdateThresholdMillis())
|
||||
.setSystemClockConfidenceUpgradeThresholdMillis(
|
||||
getSystemClockConfidenceUpgradeThresholdMillis())
|
||||
.setAutoSuggestionLowerBound(getAutoSuggestionLowerBound())
|
||||
.setManualSuggestionLowerBound(timeDetectorHelper.getManualSuggestionLowerBound())
|
||||
.setSuggestionUpperBound(timeDetectorHelper.getSuggestionUpperBound())
|
||||
@@ -285,6 +296,10 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
|
||||
return mSystemClockUpdateThresholdMillis;
|
||||
}
|
||||
|
||||
private int getSystemClockConfidenceUpgradeThresholdMillis() {
|
||||
return SYSTEM_CLOCK_CONFIRMATION_THRESHOLD_MILLIS;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Instant getAutoSuggestionLowerBound() {
|
||||
return mServerFlags.getOptionalInstant(KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.originToString;
|
||||
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
@@ -23,7 +24,6 @@ import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.app.timedetector.TelephonyTimeSuggestion;
|
||||
@@ -31,24 +31,24 @@ import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.TimestampedValue;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.LocalLog;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.SystemClockTime;
|
||||
import com.android.server.SystemClockTime.TimeConfidence;
|
||||
import com.android.server.timezonedetector.ArrayMapWithHistory;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
import com.android.server.timezonedetector.ReferenceWithHistory;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to
|
||||
* {@link AlarmManager}. When there are multiple telephony sources, the one with the lowest ID is
|
||||
* used unless the data becomes too stale.
|
||||
* The real implementation of {@link TimeDetectorStrategy}.
|
||||
*
|
||||
* <p>Most public methods are marked synchronized to ensure thread safety around internal state.
|
||||
*/
|
||||
@@ -84,13 +84,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
*/
|
||||
private static final int KEEP_SUGGESTION_HISTORY_SIZE = 10;
|
||||
|
||||
/**
|
||||
* A log that records the decisions / decision metadata that affected the device's system clock
|
||||
* time. This is logged in bug reports to assist with debugging issues with detection.
|
||||
*/
|
||||
@NonNull
|
||||
private final LocalLog mTimeChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
|
||||
|
||||
@NonNull
|
||||
private final Environment mEnvironment;
|
||||
|
||||
@@ -157,11 +150,30 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
@CurrentTimeMillisLong
|
||||
long systemClockMillis();
|
||||
|
||||
/** Sets the device system clock. The WakeLock must be held. */
|
||||
void setSystemClock(@CurrentTimeMillisLong long newTimeMillis);
|
||||
/** Returns the system clock confidence value. */
|
||||
@TimeConfidence int systemClockConfidence();
|
||||
|
||||
/** Sets the device system clock and confidence. The WakeLock must be held. */
|
||||
void setSystemClock(
|
||||
@CurrentTimeMillisLong long newTimeMillis, @TimeConfidence int confidence,
|
||||
@NonNull String logMsg);
|
||||
|
||||
/** Sets the device system clock confidence. The WakeLock must be held. */
|
||||
void setSystemClockConfidence(@TimeConfidence int confidence, @NonNull String logMsg);
|
||||
|
||||
/** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
|
||||
void releaseWakeLock();
|
||||
|
||||
|
||||
/**
|
||||
* Adds a standalone entry to the time debug log.
|
||||
*/
|
||||
void addDebugLogEntry(@NonNull String logMsg);
|
||||
|
||||
/**
|
||||
* Dumps the time debug log to the supplied {@link PrintWriter}.
|
||||
*/
|
||||
void dumpDebugLog(PrintWriter printWriter);
|
||||
}
|
||||
|
||||
static TimeDetectorStrategy create(
|
||||
@@ -250,7 +262,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
}
|
||||
|
||||
String cause = "Manual time suggestion received: suggestion=" + suggestion;
|
||||
return setSystemClockIfRequired(ORIGIN_MANUAL, newUnixEpochTime, cause);
|
||||
return setSystemClockAndConfidenceIfRequired(ORIGIN_MANUAL, newUnixEpochTime, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -318,7 +330,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
String logMsg = "handleConfigurationInternalChanged:"
|
||||
+ " oldConfiguration=" + mCurrentConfigurationInternal
|
||||
+ ", newConfiguration=" + currentUserConfig;
|
||||
logTimeDetectorChange(logMsg);
|
||||
addDebugLogEntry(logMsg);
|
||||
mCurrentConfigurationInternal = currentUserConfig;
|
||||
|
||||
boolean autoDetectionEnabled =
|
||||
@@ -335,11 +347,11 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
private void logTimeDetectorChange(@NonNull String logMsg) {
|
||||
private void addDebugLogEntry(@NonNull String logMsg) {
|
||||
if (DBG) {
|
||||
Slog.d(LOG_TAG, logMsg);
|
||||
}
|
||||
mTimeChangesLog.log(logMsg);
|
||||
mEnvironment.addDebugLogEntry(logMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -356,10 +368,11 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
long systemClockMillis = mEnvironment.systemClockMillis();
|
||||
ipw.printf("mEnvironment.systemClockMillis()=%s (%s)\n",
|
||||
Instant.ofEpochMilli(systemClockMillis), systemClockMillis);
|
||||
ipw.println("mEnvironment.systemClockConfidence()=" + mEnvironment.systemClockConfidence());
|
||||
|
||||
ipw.println("Time change log:");
|
||||
ipw.increaseIndent(); // level 2
|
||||
mTimeChangesLog.dump(ipw);
|
||||
SystemClockTime.dump(ipw);
|
||||
ipw.decreaseIndent(); // level 2
|
||||
|
||||
ipw.println("Telephony suggestion history:");
|
||||
@@ -494,11 +507,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
|
||||
@GuardedBy("this")
|
||||
private void doAutoTimeDetection(@NonNull String detectionReason) {
|
||||
if (!mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
|
||||
// Avoid doing unnecessary work with this (race-prone) check.
|
||||
return;
|
||||
}
|
||||
|
||||
// Try the different origins one at a time.
|
||||
int[] originPriorities = mCurrentConfigurationInternal.getAutoOriginPriorities();
|
||||
for (int origin : originPriorities) {
|
||||
@@ -544,7 +552,14 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
|
||||
// Update the system clock if a good suggestion has been found.
|
||||
if (newUnixEpochTime != null) {
|
||||
setSystemClockIfRequired(origin, newUnixEpochTime, cause);
|
||||
if (mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
|
||||
setSystemClockAndConfidenceIfRequired(origin, newUnixEpochTime, cause);
|
||||
} else {
|
||||
// An automatically detected time can be used to raise the confidence in the
|
||||
// current time even if the device is set to only allow user input for the time
|
||||
// itself.
|
||||
upgradeSystemClockConfidenceIfRequired(newUnixEpochTime, cause);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -718,14 +733,18 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
}
|
||||
|
||||
@GuardedBy("this")
|
||||
private boolean setSystemClockIfRequired(
|
||||
private boolean setSystemClockAndConfidenceIfRequired(
|
||||
@Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
|
||||
|
||||
// Any time set through this class is inherently high confidence. Either it came directly
|
||||
// from a user, or it was detected automatically.
|
||||
@TimeConfidence final int newTimeConfidence = TIME_CONFIDENCE_HIGH;
|
||||
boolean isOriginAutomatic = isOriginAutomatic(origin);
|
||||
if (isOriginAutomatic) {
|
||||
if (!mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
|
||||
if (DBG) {
|
||||
Slog.d(LOG_TAG, "Auto time detection is not enabled."
|
||||
Slog.d(LOG_TAG,
|
||||
"Auto time detection is not enabled / no confidence update is needed."
|
||||
+ " origin=" + originToString(origin)
|
||||
+ ", time=" + time
|
||||
+ ", cause=" + cause);
|
||||
@@ -746,7 +765,57 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
|
||||
mEnvironment.acquireWakeLock();
|
||||
try {
|
||||
return setSystemClockUnderWakeLock(origin, time, cause);
|
||||
return setSystemClockAndConfidenceUnderWakeLock(origin, time, newTimeConfidence, cause);
|
||||
} finally {
|
||||
mEnvironment.releaseWakeLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrades the system clock confidence if the current time matches the supplied auto-detected
|
||||
* time. The method never changes the system clock and it never lowers the confidence. It only
|
||||
* raises the confidence if the supplied time is within the configured threshold of the current
|
||||
* system clock time.
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
private void upgradeSystemClockConfidenceIfRequired(
|
||||
@NonNull TimestampedValue<Long> autoDetectedUnixEpochTime, @NonNull String cause) {
|
||||
@TimeConfidence int newTimeConfidence = TIME_CONFIDENCE_HIGH;
|
||||
@TimeConfidence int currentTimeConfidence = mEnvironment.systemClockConfidence();
|
||||
boolean timeNeedsConfirmation = currentTimeConfidence < newTimeConfidence;
|
||||
if (!timeNeedsConfirmation) {
|
||||
return;
|
||||
}
|
||||
|
||||
// All system clock calculation take place under a wake lock.
|
||||
mEnvironment.acquireWakeLock();
|
||||
try {
|
||||
// Check if the specified time matches the current system clock time (closely
|
||||
// enough) to raise the confidence.
|
||||
long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
|
||||
long actualSystemClockMillis = mEnvironment.systemClockMillis();
|
||||
long adjustedAutoDetectedUnixEpochMillis = TimeDetectorStrategy.getTimeAt(
|
||||
autoDetectedUnixEpochTime, elapsedRealtimeMillis);
|
||||
long absTimeDifferenceMillis =
|
||||
Math.abs(adjustedAutoDetectedUnixEpochMillis - actualSystemClockMillis);
|
||||
int confidenceUpgradeThresholdMillis =
|
||||
mCurrentConfigurationInternal.getSystemClockConfidenceUpgradeThresholdMillis();
|
||||
boolean updateConfidenceRequired =
|
||||
absTimeDifferenceMillis <= confidenceUpgradeThresholdMillis;
|
||||
if (updateConfidenceRequired) {
|
||||
String logMsg = "Upgrade system clock confidence."
|
||||
+ " autoDetectedUnixEpochTime=" + autoDetectedUnixEpochTime
|
||||
+ " newTimeConfidence=" + newTimeConfidence
|
||||
+ " cause=" + cause
|
||||
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
|
||||
+ " (old) actualSystemClockMillis=" + actualSystemClockMillis
|
||||
+ " currentTimeConfidence=" + currentTimeConfidence;
|
||||
if (DBG) {
|
||||
Slog.d(LOG_TAG, logMsg);
|
||||
}
|
||||
|
||||
mEnvironment.setSystemClockConfidence(newTimeConfidence, logMsg);
|
||||
}
|
||||
} finally {
|
||||
mEnvironment.releaseWakeLock();
|
||||
}
|
||||
@@ -757,8 +826,9 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
}
|
||||
|
||||
@GuardedBy("this")
|
||||
private boolean setSystemClockUnderWakeLock(
|
||||
@Origin int origin, @NonNull TimestampedValue<Long> newTime, @NonNull String cause) {
|
||||
private boolean setSystemClockAndConfidenceUnderWakeLock(
|
||||
@Origin int origin, @NonNull TimestampedValue<Long> newTime,
|
||||
@TimeConfidence int newTimeConfidence, @NonNull String cause) {
|
||||
|
||||
long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
|
||||
boolean isOriginAutomatic = isOriginAutomatic(origin);
|
||||
@@ -776,6 +846,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
"System clock has not tracked elapsed real time clock. A clock may"
|
||||
+ " be inaccurate or something unexpectedly set the system"
|
||||
+ " clock."
|
||||
+ " origin=" + originToString(origin)
|
||||
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
|
||||
+ " expectedTimeMillis=" + expectedTimeMillis
|
||||
+ " actualTimeMillis=" + actualSystemClockMillis
|
||||
@@ -784,44 +855,72 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
// If the new signal would make sufficient difference to the system clock or mean a change
|
||||
// in confidence then system state must be updated.
|
||||
|
||||
// Adjust for the time that has elapsed since the signal was received.
|
||||
long newSystemClockMillis = TimeDetectorStrategy.getTimeAt(newTime, elapsedRealtimeMillis);
|
||||
|
||||
// Check if the new signal would make sufficient difference to the system clock. If it's
|
||||
// below the threshold then ignore it.
|
||||
long absTimeDifference = Math.abs(newSystemClockMillis - actualSystemClockMillis);
|
||||
long systemClockUpdateThreshold =
|
||||
mCurrentConfigurationInternal.getSystemClockUpdateThresholdMillis();
|
||||
if (absTimeDifference < systemClockUpdateThreshold) {
|
||||
boolean updateSystemClockRequired = absTimeDifference >= systemClockUpdateThreshold;
|
||||
|
||||
@TimeConfidence int currentTimeConfidence = mEnvironment.systemClockConfidence();
|
||||
boolean updateConfidenceRequired = newTimeConfidence > currentTimeConfidence;
|
||||
|
||||
if (updateSystemClockRequired) {
|
||||
String logMsg = "Set system clock & confidence."
|
||||
+ " origin=" + originToString(origin)
|
||||
+ " newTime=" + newTime
|
||||
+ " newTimeConfidence=" + newTimeConfidence
|
||||
+ " cause=" + cause
|
||||
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
|
||||
+ " (old) actualSystemClockMillis=" + actualSystemClockMillis
|
||||
+ " newSystemClockMillis=" + newSystemClockMillis
|
||||
+ " currentTimeConfidence=" + currentTimeConfidence;
|
||||
mEnvironment.setSystemClock(newSystemClockMillis, newTimeConfidence, logMsg);
|
||||
if (DBG) {
|
||||
Slog.d(LOG_TAG, "Not setting system clock. New time and"
|
||||
+ " system clock are close enough."
|
||||
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
|
||||
+ " newTime=" + newTime
|
||||
+ " cause=" + cause
|
||||
+ " systemClockUpdateThreshold=" + systemClockUpdateThreshold
|
||||
+ " absTimeDifference=" + absTimeDifference);
|
||||
Slog.d(LOG_TAG, logMsg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mEnvironment.setSystemClock(newSystemClockMillis);
|
||||
String logMsg = "Set system clock using time=" + newTime
|
||||
+ " cause=" + cause
|
||||
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
|
||||
+ " (old) actualSystemClockMillis=" + actualSystemClockMillis
|
||||
+ " newSystemClockMillis=" + newSystemClockMillis;
|
||||
if (DBG) {
|
||||
Slog.d(LOG_TAG, logMsg);
|
||||
}
|
||||
mTimeChangesLog.log(logMsg);
|
||||
|
||||
// CLOCK_PARANOIA : Record the last time this class set the system clock due to an auto-time
|
||||
// signal, or clear the record it is being done manually.
|
||||
if (isOriginAutomatic(origin)) {
|
||||
mLastAutoSystemClockTimeSet = newTime;
|
||||
// CLOCK_PARANOIA : Record the last time this class set the system clock due to an
|
||||
// auto-time signal, or clear the record it is being done manually.
|
||||
if (isOriginAutomatic(origin)) {
|
||||
mLastAutoSystemClockTimeSet = newTime;
|
||||
} else {
|
||||
mLastAutoSystemClockTimeSet = null;
|
||||
}
|
||||
} else if (updateConfidenceRequired) {
|
||||
// Only the confidence needs updating. This path is separate from a system clock update
|
||||
// to deliberately avoid touching the system clock's value when it's not needed. Doing
|
||||
// so could introduce inaccuracies or cause unnecessary wear in RTC hardware or
|
||||
// associated storage.
|
||||
String logMsg = "Set system clock confidence."
|
||||
+ " origin=" + originToString(origin)
|
||||
+ " newTime=" + newTime
|
||||
+ " newTimeConfidence=" + newTimeConfidence
|
||||
+ " cause=" + cause
|
||||
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
|
||||
+ " (old) actualSystemClockMillis=" + actualSystemClockMillis
|
||||
+ " newSystemClockMillis=" + newSystemClockMillis
|
||||
+ " currentTimeConfidence=" + currentTimeConfidence;
|
||||
if (DBG) {
|
||||
Slog.d(LOG_TAG, logMsg);
|
||||
}
|
||||
mEnvironment.setSystemClockConfidence(newTimeConfidence, logMsg);
|
||||
} else {
|
||||
mLastAutoSystemClockTimeSet = null;
|
||||
// Neither clock nor confidence need updating.
|
||||
if (DBG) {
|
||||
Slog.d(LOG_TAG, "Not setting system clock or confidence."
|
||||
+ " origin=" + originToString(origin)
|
||||
+ " newTime=" + newTime
|
||||
+ " newTimeConfidence=" + newTimeConfidence
|
||||
+ " cause=" + cause
|
||||
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
|
||||
+ " systemClockUpdateThreshold=" + systemClockUpdateThreshold
|
||||
+ " absTimeDifference=" + absTimeDifference
|
||||
+ " currentTimeConfidence=" + currentTimeConfidence);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ cc_library_static {
|
||||
"com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp",
|
||||
"com_android_server_stats_pull_StatsPullAtomService.cpp",
|
||||
"com_android_server_storage_AppFuseBridge.cpp",
|
||||
"com_android_server_SystemClockTime.cpp",
|
||||
"com_android_server_SystemServer.cpp",
|
||||
"com_android_server_tv_TvUinputBridge.cpp",
|
||||
"com_android_server_tv_TvInputHal.cpp",
|
||||
|
||||
126
services/core/jni/com_android_server_SystemClockTime.cpp
Normal file
126
services/core/jni/com_android_server_SystemClockTime.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SystemClockTime"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
class SystemClockImpl {
|
||||
public:
|
||||
SystemClockImpl(const std::string &rtc_dev) : rtc_dev{rtc_dev} {}
|
||||
|
||||
int setTime(struct timeval *tv);
|
||||
|
||||
private:
|
||||
std::string rtc_dev;
|
||||
};
|
||||
|
||||
int SystemClockImpl::setTime(struct timeval *tv) {
|
||||
if (settimeofday(tv, NULL) == -1) {
|
||||
ALOGV("settimeofday() failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
android::base::unique_fd fd{open(rtc_dev.c_str(), O_RDWR)};
|
||||
if (!fd.ok()) {
|
||||
ALOGE("Unable to open %s: %s", rtc_dev.c_str(), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct tm tm;
|
||||
if (!gmtime_r(&tv->tv_sec, &tm)) {
|
||||
ALOGV("gmtime_r() failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct rtc_time rtc = {};
|
||||
rtc.tm_sec = tm.tm_sec;
|
||||
rtc.tm_min = tm.tm_min;
|
||||
rtc.tm_hour = tm.tm_hour;
|
||||
rtc.tm_mday = tm.tm_mday;
|
||||
rtc.tm_mon = tm.tm_mon;
|
||||
rtc.tm_year = tm.tm_year;
|
||||
rtc.tm_wday = tm.tm_wday;
|
||||
rtc.tm_yday = tm.tm_yday;
|
||||
rtc.tm_isdst = tm.tm_isdst;
|
||||
if (ioctl(fd, RTC_SET_TIME, &rtc) == -1) {
|
||||
ALOGV("RTC_SET_TIME ioctl failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static jlong com_android_server_SystemClockTime_init(JNIEnv *, jobject) {
|
||||
// Find the wall clock RTC. We expect this always to be /dev/rtc0, but
|
||||
// check the /dev/rtc symlink first so that legacy devices that don't use
|
||||
// rtc0 can add a symlink rather than need to carry a local patch to this
|
||||
// code.
|
||||
//
|
||||
// TODO: if you're reading this in a world where all devices are using the
|
||||
// GKI, you can remove the readlink and just assume /dev/rtc0.
|
||||
std::string dev_rtc;
|
||||
if (!android::base::Readlink("/dev/rtc", &dev_rtc)) {
|
||||
dev_rtc = "/dev/rtc0";
|
||||
}
|
||||
|
||||
std::unique_ptr<SystemClockImpl> system_clock{new SystemClockImpl(dev_rtc)};
|
||||
return reinterpret_cast<jlong>(system_clock.release());
|
||||
}
|
||||
|
||||
static jint com_android_server_SystemClockTime_setTime(JNIEnv *, jobject, jlong nativeData,
|
||||
jlong millis) {
|
||||
SystemClockImpl *impl = reinterpret_cast<SystemClockImpl *>(nativeData);
|
||||
|
||||
if (millis <= 0 || millis / 1000LL >= std::numeric_limits<time_t>::max()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = (millis / 1000LL);
|
||||
tv.tv_usec = ((millis % 1000LL) * 1000LL);
|
||||
|
||||
ALOGD("Setting time of day to sec=%ld", tv.tv_sec);
|
||||
|
||||
int ret = impl->setTime(&tv);
|
||||
if (ret < 0) {
|
||||
ALOGW("Unable to set rtc to %ld: %s", tv.tv_sec, strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const JNINativeMethod sMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{"init", "()J", (void *)com_android_server_SystemClockTime_init},
|
||||
{"setTime", "(JJ)I", (void *)com_android_server_SystemClockTime_setTime},
|
||||
};
|
||||
|
||||
int register_com_android_server_SystemClockTime(JNIEnv *env) {
|
||||
return jniRegisterNativeMethods(env, "com/android/server/SystemClockTime", sMethods,
|
||||
NELEM(sMethods));
|
||||
}
|
||||
|
||||
} /* namespace android */
|
||||
@@ -65,6 +65,7 @@ int register_android_server_companion_virtual_InputController(JNIEnv* env);
|
||||
int register_android_server_app_GameManagerService(JNIEnv* env);
|
||||
int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
|
||||
int register_com_android_server_display_DisplayControl(JNIEnv* env);
|
||||
int register_com_android_server_SystemClockTime(JNIEnv* env);
|
||||
};
|
||||
|
||||
using namespace android;
|
||||
@@ -122,5 +123,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
register_android_server_app_GameManagerService(env);
|
||||
register_com_android_server_wm_TaskFpsCallbackController(env);
|
||||
register_com_android_server_display_DisplayControl(env);
|
||||
register_com_android_server_SystemClockTime(env);
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
@@ -168,6 +168,7 @@ import com.android.server.AppStateTracker;
|
||||
import com.android.server.AppStateTrackerImpl;
|
||||
import com.android.server.DeviceIdleInternal;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemClockTime.TimeConfidence;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.pm.permission.PermissionManagerService;
|
||||
import com.android.server.pm.permission.PermissionManagerServiceInternal;
|
||||
@@ -345,10 +346,6 @@ public class AlarmManagerServiceTest {
|
||||
mTestTimer.set(type, millis);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setKernelTime(long millis) {
|
||||
}
|
||||
|
||||
@Override
|
||||
int getSystemUiUid(PackageManagerInternal unused) {
|
||||
return SYSTEM_UI_UID;
|
||||
@@ -361,7 +358,18 @@ public class AlarmManagerServiceTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
long getElapsedRealtime() {
|
||||
void initializeTimeIfRequired() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@Override
|
||||
void setCurrentTimeMillis(long unixEpochMillis,
|
||||
@TimeConfidence int confidence, String logMsg) {
|
||||
mNowRtcTest = unixEpochMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
long getElapsedRealtimeMillis() {
|
||||
return mNowElapsedTest;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
|
||||
import static com.android.server.SystemClockTime.TIME_CONFIDENCE_LOW;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_EXTERNAL;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_GNSS;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
|
||||
@@ -35,6 +37,7 @@ import android.os.TimestampedValue;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.SystemClockTime.TimeConfidence;
|
||||
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
|
||||
@@ -42,6 +45,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -86,6 +90,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setAutoDetectionSupported(true)
|
||||
.setSystemClockUpdateThresholdMillis(
|
||||
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
|
||||
.setSystemClockUpdateThresholdMillis(TIME_CONFIDENCE_HIGH)
|
||||
.setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
|
||||
.setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
|
||||
.setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
|
||||
@@ -99,6 +104,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setAutoDetectionSupported(true)
|
||||
.setSystemClockUpdateThresholdMillis(
|
||||
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
|
||||
.setSystemClockUpdateThresholdMillis(TIME_CONFIDENCE_HIGH)
|
||||
.setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
|
||||
.setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
|
||||
.setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
|
||||
@@ -112,12 +118,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
public void setUp() {
|
||||
mFakeEnvironment = new FakeEnvironment();
|
||||
mFakeEnvironment.initializeConfig(CONFIG_AUTO_DISABLED);
|
||||
mFakeEnvironment.initializeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO);
|
||||
mFakeEnvironment.initializeFakeClocks(
|
||||
ARBITRARY_CLOCK_INITIALIZATION_INFO, TIME_CONFIDENCE_LOW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestTelephonyTime_autoTimeEnabled() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
Instant testTime = ARBITRARY_TEST_TIME;
|
||||
@@ -129,18 +137,21 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
script.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
|
||||
script.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestTelephonyTime_emptySuggestionIgnored() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
script.generateTelephonyTimeSuggestion(slotIndex, null);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, null);
|
||||
}
|
||||
@@ -278,17 +289,115 @@ public class TimeDetectorStrategyImplTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If an auto suggested time matches the current system clock, the confidence in the current
|
||||
* system clock is raised even when auto time is disabled. The system clock itself must not be
|
||||
* changed.
|
||||
*/
|
||||
@Test
|
||||
public void testSuggestTelephonyTime_autoTimeDisabled() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
|
||||
public void testSuggestTelephonyTime_autoTimeDisabled_suggestionMatchesSystemClock() {
|
||||
TimestampedValue<Instant> initialClockTime = ARBITRARY_CLOCK_INITIALIZATION_INFO;
|
||||
final int confidenceUpgradeThresholdMillis = 1000;
|
||||
ConfigurationInternal configInternal =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setSystemClockConfidenceUpgradeThresholdMillis(
|
||||
confidenceUpgradeThresholdMillis)
|
||||
.build();
|
||||
Script script = new Script()
|
||||
.pokeFakeClocks(initialClockTime, TIME_CONFIDENCE_LOW)
|
||||
.simulateConfigurationInternalChange(configInternal);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
script.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
|
||||
script.simulateTimePassing()
|
||||
.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
|
||||
|
||||
script.simulateTimePassing();
|
||||
long timeElapsedMillis =
|
||||
script.peekElapsedRealtimeMillis() - initialClockTime.getReferenceTimeMillis();
|
||||
|
||||
// Create a suggestion time that approximately matches the current system clock.
|
||||
Instant suggestionInstant = initialClockTime.getValue()
|
||||
.plusMillis(timeElapsedMillis)
|
||||
.plusMillis(confidenceUpgradeThresholdMillis);
|
||||
TimestampedValue<Long> matchingClockTime = new TimestampedValue<>(
|
||||
script.peekElapsedRealtimeMillis(),
|
||||
suggestionInstant.toEpochMilli());
|
||||
TelephonyTimeSuggestion timeSuggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
|
||||
.setUnixEpochTime(matchingClockTime)
|
||||
.build();
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
/**
|
||||
* If an auto suggested time doesn't match the current system clock, the confidence in the
|
||||
* current system clock will stay where it is. The system clock itself must not be changed.
|
||||
*/
|
||||
@Test
|
||||
public void testSuggestTelephonyTime_autoTimeDisabled_suggestionMismatchesSystemClock() {
|
||||
TimestampedValue<Instant> initialClockTime = ARBITRARY_CLOCK_INITIALIZATION_INFO;
|
||||
final int confidenceUpgradeThresholdMillis = 1000;
|
||||
ConfigurationInternal configInternal =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setSystemClockConfidenceUpgradeThresholdMillis(
|
||||
confidenceUpgradeThresholdMillis)
|
||||
.build();
|
||||
Script script = new Script().pokeFakeClocks(initialClockTime, TIME_CONFIDENCE_LOW)
|
||||
.simulateConfigurationInternalChange(configInternal);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
|
||||
script.simulateTimePassing();
|
||||
long timeElapsedMillis =
|
||||
script.peekElapsedRealtimeMillis() - initialClockTime.getReferenceTimeMillis();
|
||||
|
||||
// Create a suggestion time that doesn't match the current system clock closely enough.
|
||||
Instant suggestionInstant = initialClockTime.getValue()
|
||||
.plusMillis(timeElapsedMillis)
|
||||
.plusMillis(confidenceUpgradeThresholdMillis + 1);
|
||||
TimestampedValue<Long> mismatchingClockTime = new TimestampedValue<>(
|
||||
script.peekElapsedRealtimeMillis(),
|
||||
suggestionInstant.toEpochMilli());
|
||||
TelephonyTimeSuggestion timeSuggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
|
||||
.setUnixEpochTime(mismatchingClockTime)
|
||||
.build();
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
/**
|
||||
* If a suggested time doesn't match the current system clock, the confidence in the current
|
||||
* system clock will not drop.
|
||||
*/
|
||||
@Test
|
||||
public void testSuggestTelephonyTime_autoTimeDisabled_suggestionMismatchesSystemClock2() {
|
||||
TimestampedValue<Instant> initialClockTime = ARBITRARY_CLOCK_INITIALIZATION_INFO;
|
||||
final int confidenceUpgradeThresholdMillis = 1000;
|
||||
ConfigurationInternal configInternal =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setSystemClockConfidenceUpgradeThresholdMillis(
|
||||
confidenceUpgradeThresholdMillis)
|
||||
.build();
|
||||
Script script = new Script().pokeFakeClocks(initialClockTime, TIME_CONFIDENCE_HIGH)
|
||||
.simulateConfigurationInternalChange(configInternal);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
|
||||
script.simulateTimePassing();
|
||||
long timeElapsedMillis =
|
||||
script.peekElapsedRealtimeMillis() - initialClockTime.getReferenceTimeMillis();
|
||||
|
||||
// Create a suggestion time that doesn't closely match the current system clock.
|
||||
Instant initialClockInstant = initialClockTime.getValue();
|
||||
TimestampedValue<Long> mismatchingClockTime = new TimestampedValue<>(
|
||||
script.peekElapsedRealtimeMillis(),
|
||||
initialClockInstant.plusMillis(timeElapsedMillis + 1_000_000).toEpochMilli());
|
||||
TelephonyTimeSuggestion timeSuggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
|
||||
.setUnixEpochTime(mismatchingClockTime)
|
||||
.build();
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -298,7 +407,8 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setSystemClockUpdateThresholdMillis(systemClockUpdateThresholdMillis)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant testTime = ARBITRARY_TEST_TIME;
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
@@ -311,6 +421,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
script.simulateTimePassing();
|
||||
long expectedSystemClockMillis1 = script.calculateTimeInMillisForNow(unixEpochTime1);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion1)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
|
||||
|
||||
@@ -327,6 +438,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
TelephonyTimeSuggestion timeSuggestion2 =
|
||||
createTelephonyTimeSuggestion(slotIndex, unixEpochTime2);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion2)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
|
||||
|
||||
@@ -339,6 +451,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
TelephonyTimeSuggestion timeSuggestion3 =
|
||||
createTelephonyTimeSuggestion(slotIndex, unixEpochTime3);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion3)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
|
||||
|
||||
@@ -350,6 +463,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
TelephonyTimeSuggestion timeSuggestion4 =
|
||||
createTelephonyTimeSuggestion(slotIndex, unixEpochTime4);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion4)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4)
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion4);
|
||||
}
|
||||
@@ -362,7 +476,8 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setSystemClockUpdateThresholdMillis(systemClockUpdateThresholdMillis)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
Instant testTime = ARBITRARY_TEST_TIME;
|
||||
@@ -376,6 +491,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
// Simulate the time signal being received. It should not be used because auto time
|
||||
// detection is off but it should be recorded.
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion1)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
|
||||
|
||||
@@ -386,11 +502,13 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
// Turn on auto time detection.
|
||||
script.simulateAutoTimeDetectionToggle()
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
|
||||
|
||||
// Turn off auto time detection.
|
||||
script.simulateAutoTimeDetectionToggle()
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
|
||||
|
||||
@@ -408,18 +526,21 @@ public class TimeDetectorStrategyImplTest {
|
||||
// The new time, though valid, should not be set in the system clock because auto time is
|
||||
// disabled.
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion2)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
|
||||
|
||||
// Turn on auto time detection.
|
||||
script.simulateAutoTimeDetectionToggle()
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2)
|
||||
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestTelephonyTime_maxSuggestionAge() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
Instant testTime = ARBITRARY_TEST_TIME;
|
||||
@@ -431,6 +552,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(telephonySuggestion.getUnixEpochTime());
|
||||
script.simulateTelephonyTimeSuggestion(telephonySuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(
|
||||
expectedSystemClockMillis /* expectedNetworkBroadcast */)
|
||||
.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
|
||||
@@ -442,7 +564,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS);
|
||||
|
||||
// Look inside and check what the strategy considers the current best telephony suggestion.
|
||||
// It should still be the, it's just no longer used.
|
||||
// It should still be there, it's just no longer used.
|
||||
assertNull(script.peekBestTelephonySuggestion());
|
||||
script.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
|
||||
}
|
||||
@@ -454,12 +576,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_TELEPHONY)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowLowerBound);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -470,12 +594,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_TELEPHONY)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveLowerBound);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -486,12 +612,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_TELEPHONY)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveUpperBound);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -502,18 +630,21 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_TELEPHONY)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
|
||||
TelephonyTimeSuggestion timeSuggestion =
|
||||
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowUpperBound);
|
||||
script.simulateTelephonyTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTime_autoTimeDisabled() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
ManualTimeSuggestion timeSuggestion =
|
||||
script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
@@ -524,12 +655,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTime_retainsAutoSignal() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
int slotIndex = ARBITRARY_SLOT_INDEX;
|
||||
|
||||
@@ -544,6 +677,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
long expectedAutoClockMillis =
|
||||
script.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
|
||||
script.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
|
||||
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
|
||||
|
||||
@@ -552,6 +686,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
// Switch to manual.
|
||||
script.simulateAutoTimeDetectionToggle()
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
|
||||
|
||||
@@ -568,6 +703,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
script.calculateTimeInMillisForNow(manualTimeSuggestion.getUnixEpochTime());
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, manualTimeSuggestion, true /* expectedResult */)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis)
|
||||
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
|
||||
|
||||
@@ -580,17 +716,20 @@ public class TimeDetectorStrategyImplTest {
|
||||
expectedAutoClockMillis =
|
||||
script.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
|
||||
script.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
|
||||
|
||||
// Switch back to manual - nothing should happen to the clock.
|
||||
script.simulateAutoTimeDetectionToggle()
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking()
|
||||
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTime_isIgnored_whenAutoTimeEnabled() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
ManualTimeSuggestion timeSuggestion =
|
||||
script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
@@ -598,6 +737,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
script.simulateTimePassing()
|
||||
.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -607,12 +747,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveUpperBound);
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -622,12 +764,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowUpperBound);
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -637,12 +781,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowLowerBound);
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -652,12 +798,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveLowerBound);
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -667,7 +815,8 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setOriginPriorities(ORIGIN_NETWORK)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
@@ -677,6 +826,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
|
||||
@@ -703,12 +853,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_NETWORK)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(belowLowerBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -719,12 +871,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_NETWORK)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(aboveLowerBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -735,12 +889,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_NETWORK)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(aboveUpperBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -751,12 +907,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_NETWORK)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
|
||||
NetworkTimeSuggestion timeSuggestion =
|
||||
script.generateNetworkTimeSuggestion(belowUpperBound);
|
||||
script.simulateNetworkTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -766,7 +924,8 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setOriginPriorities(ORIGIN_GNSS)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
GnssTimeSuggestion timeSuggestion =
|
||||
script.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
@@ -776,6 +935,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
script.simulateGnssTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
|
||||
@@ -802,12 +962,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_GNSS)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
|
||||
GnssTimeSuggestion timeSuggestion =
|
||||
script.generateGnssTimeSuggestion(belowLowerBound);
|
||||
script.simulateGnssTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -818,12 +980,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_GNSS)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
|
||||
GnssTimeSuggestion timeSuggestion =
|
||||
script.generateGnssTimeSuggestion(aboveLowerBound);
|
||||
script.simulateGnssTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -834,12 +998,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_GNSS)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
|
||||
GnssTimeSuggestion timeSuggestion =
|
||||
script.generateGnssTimeSuggestion(aboveUpperBound);
|
||||
script.simulateGnssTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -850,12 +1016,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_GNSS)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
|
||||
GnssTimeSuggestion timeSuggestion =
|
||||
script.generateGnssTimeSuggestion(belowUpperBound);
|
||||
script.simulateGnssTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -865,7 +1033,8 @@ public class TimeDetectorStrategyImplTest {
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
|
||||
.setOriginPriorities(ORIGIN_EXTERNAL)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
ExternalTimeSuggestion timeSuggestion =
|
||||
script.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
@@ -875,6 +1044,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
script.simulateExternalTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
|
||||
@@ -901,12 +1071,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_EXTERNAL)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
|
||||
ExternalTimeSuggestion timeSuggestion =
|
||||
script.generateExternalTimeSuggestion(belowLowerBound);
|
||||
script.simulateExternalTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -917,12 +1089,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_EXTERNAL)
|
||||
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
|
||||
ExternalTimeSuggestion timeSuggestion =
|
||||
script.generateExternalTimeSuggestion(aboveLowerBound);
|
||||
script.simulateExternalTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -933,12 +1107,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_EXTERNAL)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
|
||||
ExternalTimeSuggestion timeSuggestion =
|
||||
script.generateExternalTimeSuggestion(aboveUpperBound);
|
||||
script.simulateExternalTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
|
||||
@@ -949,12 +1125,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
.setOriginPriorities(ORIGIN_EXTERNAL)
|
||||
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal);
|
||||
Script script = new Script().simulateConfigurationInternalChange(configInternal)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
|
||||
ExternalTimeSuggestion timeSuggestion =
|
||||
script.generateExternalTimeSuggestion(belowUpperBound);
|
||||
script.simulateExternalTimeSuggestion(timeSuggestion)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -1472,6 +1650,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
private boolean mWakeLockAcquired;
|
||||
private long mElapsedRealtimeMillis;
|
||||
private long mSystemClockMillis;
|
||||
private int mSystemClockConfidence = TIME_CONFIDENCE_LOW;
|
||||
private ConfigurationChangeListener mConfigurationInternalChangeListener;
|
||||
|
||||
// Tracking operations.
|
||||
@@ -1481,9 +1660,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
mConfigurationInternal = configurationInternal;
|
||||
}
|
||||
|
||||
public void initializeFakeClocks(TimestampedValue<Instant> timeInfo) {
|
||||
public void initializeFakeClocks(
|
||||
TimestampedValue<Instant> timeInfo, @TimeConfidence int timeConfidence) {
|
||||
pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
|
||||
pokeSystemClockMillis(timeInfo.getValue().toEpochMilli());
|
||||
pokeSystemClockMillis(timeInfo.getValue().toEpochMilli(), timeConfidence);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1515,10 +1695,23 @@ public class TimeDetectorStrategyImplTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemClock(long newTimeMillis) {
|
||||
public @TimeConfidence int systemClockConfidence() {
|
||||
return mSystemClockConfidence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemClock(
|
||||
long newTimeMillis, @TimeConfidence int confidence, String logMsg) {
|
||||
assertWakeLockAcquired();
|
||||
mSystemClockWasSet = true;
|
||||
mSystemClockMillis = newTimeMillis;
|
||||
mSystemClockConfidence = confidence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemClockConfidence(@TimeConfidence int confidence, String logMsg) {
|
||||
assertWakeLockAcquired();
|
||||
mSystemClockConfidence = confidence;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1527,6 +1720,16 @@ public class TimeDetectorStrategyImplTest {
|
||||
mWakeLockAcquired = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugLogEntry(String logMsg) {
|
||||
// No-op for tests
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpDebugLog(PrintWriter printWriter) {
|
||||
// No-op for tests
|
||||
}
|
||||
|
||||
// Methods below are for managing the fake's behavior.
|
||||
|
||||
void simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
|
||||
@@ -1538,8 +1741,9 @@ public class TimeDetectorStrategyImplTest {
|
||||
mElapsedRealtimeMillis = elapsedRealtimeMillis;
|
||||
}
|
||||
|
||||
void pokeSystemClockMillis(long systemClockMillis) {
|
||||
void pokeSystemClockMillis(long systemClockMillis, @TimeConfidence int timeConfidence) {
|
||||
mSystemClockMillis = systemClockMillis;
|
||||
mSystemClockConfidence = timeConfidence;
|
||||
}
|
||||
|
||||
long peekElapsedRealtimeMillis() {
|
||||
@@ -1567,6 +1771,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
assertEquals(expectedSystemClockMillis, mSystemClockMillis);
|
||||
}
|
||||
|
||||
public void verifySystemClockConfidence(@TimeConfidence int expectedConfidence) {
|
||||
assertEquals(expectedConfidence, mSystemClockConfidence);
|
||||
}
|
||||
|
||||
void resetCallTracking() {
|
||||
mSystemClockWasSet = false;
|
||||
}
|
||||
@@ -1589,6 +1797,14 @@ public class TimeDetectorStrategyImplTest {
|
||||
mTimeDetectorStrategy = new TimeDetectorStrategyImpl(mFakeEnvironment);
|
||||
}
|
||||
|
||||
Script pokeFakeClocks(TimestampedValue<Instant> initialClockTime,
|
||||
@TimeConfidence int timeConfidence) {
|
||||
mFakeEnvironment.pokeElapsedRealtimeMillis(initialClockTime.getReferenceTimeMillis());
|
||||
mFakeEnvironment.pokeSystemClockMillis(
|
||||
initialClockTime.getValue().toEpochMilli(), timeConfidence);
|
||||
return this;
|
||||
}
|
||||
|
||||
long peekElapsedRealtimeMillis() {
|
||||
return mFakeEnvironment.peekElapsedRealtimeMillis();
|
||||
}
|
||||
@@ -1675,6 +1891,11 @@ public class TimeDetectorStrategyImplTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
Script verifySystemClockConfidence(@TimeConfidence int expectedConfidence) {
|
||||
mFakeEnvironment.verifySystemClockConfidence(expectedConfidence);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* White box test info: Asserts the latest suggestion for the slotIndex is as expected.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user