1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server; 17 18 import static java.lang.annotation.ElementType.TYPE_USE; 19 import static java.lang.annotation.RetentionPolicy.SOURCE; 20 21 import android.annotation.CurrentTimeMillisLong; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.os.Build; 25 import android.os.Environment; 26 import android.os.SystemProperties; 27 import android.util.LocalLog; 28 import android.util.Slog; 29 30 import java.io.PrintWriter; 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.Target; 33 34 /** 35 * A set of static methods that encapsulate knowledge of how the system clock time and associated 36 * metadata are stored on Android. 37 */ 38 public final class SystemClockTime { 39 40 private static final String TAG = "SystemClockTime"; 41 42 /** 43 * A log that records the decisions / decision metadata that affected the device's system clock 44 * time. This is logged in bug reports to assist with debugging issues with time. 45 */ 46 @NonNull 47 private static final LocalLog sTimeDebugLog = 48 new LocalLog(30, false /* useLocalTimestamps */); 49 50 51 /** 52 * An annotation that indicates a "time confidence" value is expected. 53 * 54 * <p>The confidence indicates whether the time is expected to be correct. The confidence can be 55 * upgraded or downgraded over time. It can be used to decide whether a user could / should be 56 * asked to confirm the time. For example, during device set up low confidence would describe a 57 * time that has been initialized by default. The user may then be asked to confirm the time, 58 * moving it to a high confidence. 59 */ 60 @Retention(SOURCE) 61 @Target(TYPE_USE) 62 @IntDef(prefix = "TIME_CONFIDENCE_", 63 value = { TIME_CONFIDENCE_LOW, TIME_CONFIDENCE_HIGH }) 64 public @interface TimeConfidence { 65 } 66 67 /** Used when confidence is low and would (ideally) be confirmed by a user. */ 68 public static final @TimeConfidence int TIME_CONFIDENCE_LOW = 0; 69 70 /** 71 * Used when confidence in the time is high and does not need to be confirmed by a user. 72 */ 73 public static final @TimeConfidence int TIME_CONFIDENCE_HIGH = 100; 74 75 /** 76 * The confidence in the current time. Android's time confidence is held in memory because RTC 77 * hardware can forget / corrupt the time while the device is powered off. Therefore, on boot 78 * we can't assume the time is good, and so default it to "low" confidence until it is confirmed 79 * or explicitly set. 80 */ 81 private static @TimeConfidence int sTimeConfidence = TIME_CONFIDENCE_LOW; 82 83 private static final long sNativeData = init(); 84 SystemClockTime()85 private SystemClockTime() { 86 } 87 88 /** 89 * Sets the system clock time to a reasonable lower bound. Used during boot-up to ensure the 90 * device has a time that is better than a default like 1970-01-01. 91 */ initializeIfRequired()92 public static void initializeIfRequired() { 93 // Use the most recent of Build.TIME, the root file system's timestamp, and the 94 // value of the ro.build.date.utc system property (which is in seconds). 95 final long systemBuildTime = Long.max( 96 1000L * SystemProperties.getLong("ro.build.date.utc", -1L), 97 Long.max(Environment.getRootDirectory().lastModified(), Build.TIME)); 98 long currentTimeMillis = getCurrentTimeMillis(); 99 if (currentTimeMillis < systemBuildTime) { 100 String logMsg = "Current time only " + currentTimeMillis 101 + ", advancing to build time " + systemBuildTime; 102 Slog.i(TAG, logMsg); 103 setTimeAndConfidence(systemBuildTime, TIME_CONFIDENCE_LOW, logMsg); 104 } 105 } 106 107 /** 108 * Sets the system clock time and confidence. See also {@link #setConfidence(int, String)} for 109 * an alternative that only sets the confidence. 110 * 111 * @param unixEpochMillis the time to set 112 * @param confidence the confidence in {@code unixEpochMillis}. See {@link TimeConfidence} for 113 * details. 114 * @param logMsg a log message that can be included in bug reports that explains the update 115 */ setTimeAndConfidence( @urrentTimeMillisLong long unixEpochMillis, int confidence, @NonNull String logMsg)116 public static void setTimeAndConfidence( 117 @CurrentTimeMillisLong long unixEpochMillis, int confidence, @NonNull String logMsg) { 118 synchronized (SystemClockTime.class) { 119 setTime(sNativeData, unixEpochMillis); 120 sTimeConfidence = confidence; 121 sTimeDebugLog.log(logMsg); 122 } 123 } 124 125 /** 126 * Sets the system clock confidence. See also {@link #setTimeAndConfidence(long, int, String)} 127 * for an alternative that sets the time and confidence. 128 * 129 * @param confidence the confidence in the system clock time. See {@link TimeConfidence} for 130 * details. 131 * @param logMsg a log message that can be included in bug reports that explains the update 132 */ setConfidence(@imeConfidence int confidence, @NonNull String logMsg)133 public static void setConfidence(@TimeConfidence int confidence, @NonNull String logMsg) { 134 synchronized (SystemClockTime.class) { 135 sTimeConfidence = confidence; 136 sTimeDebugLog.log(logMsg); 137 } 138 } 139 140 /** 141 * Returns the system clock time. The same as {@link System#currentTimeMillis()}. 142 */ getCurrentTimeMillis()143 private static @CurrentTimeMillisLong long getCurrentTimeMillis() { 144 return System.currentTimeMillis(); 145 } 146 147 /** 148 * Returns the system clock confidence. See {@link TimeConfidence} for details. 149 */ getTimeConfidence()150 public static @TimeConfidence int getTimeConfidence() { 151 synchronized (SystemClockTime.class) { 152 return sTimeConfidence; 153 } 154 } 155 156 /** 157 * Adds an entry to the system time debug log that is included in bug reports. This method is 158 * intended to be used to record event that may lead to a time change, e.g. config or mode 159 * changes. 160 */ addDebugLogEntry(@onNull String logMsg)161 public static void addDebugLogEntry(@NonNull String logMsg) { 162 sTimeDebugLog.log(logMsg); 163 } 164 165 /** 166 * Dumps information about recent time / confidence changes to the supplied writer. 167 */ dump(PrintWriter writer)168 public static void dump(PrintWriter writer) { 169 sTimeDebugLog.dump(writer); 170 } 171 init()172 private static native long init(); setTime(long nativeData, @CurrentTimeMillisLong long millis)173 private static native int setTime(long nativeData, @CurrentTimeMillisLong long millis); 174 } 175