一、背景说明
Android系统默认不允许系统时间设置早于系统固件编译时间,毕竟时间是始终向前的,通常不会设置某个过去的无效时间。但在项目测试环节提出了此问题:
当设置系统时间为早于编译时间的时刻时,设备重启时间复位为固件编译时间。
二、根因分析
先以Android10展开分析,从现象分析可知:
1.设置系统时间后是重启设备才复位,因此是开机过程某处重置了系统时间
2.时间被复位为固件编译时间
分析开机log可看到相关log:
AlarmManager Current time only xxx , advancing to build time xxx
从而可知开机时时间被复位成固件编译时间,响应log代码位于:
frameworks/base/services/core/java/com/android/server/AlarmManagerService.java
@Override
public void onStart() {
mInjector.init();
synchronized (mLock) {
...
// 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);
}
此外我们知道固件编译保存在ro.build.date.utc属性中,全局搜索代码,也较容易定位到上述代码。
由此可知,开机AlarmManager服务启动时,从ro.builddate.utc属性中固件编译时间,并于当前系统时间比较,若当前系统时间早于编译时间,则以固件编译时间为系统时间。
三、解决方案
Android10
frameworks/base/services/core/java/com/android/server/AlarmManagerService.java
@Override
public void onStart() {
mInjector.init();
synchronized (mLock) {
...
// 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).
//Patch Start
/*
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);
}
*/
//Patch End
Android15 流程有些变化,在initializeTimeIfRequired()初始化合适的系统时间
frameworks/base/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@Override
public void onStart() {
mInjector.init();
mHandler = new AlarmHandler();
...
synchronized (mLock) {
...
// Ensure that we're booting with a halfway sensible current time.
//Patch Start
//mInjector.initializeTimeIfRequired();
//Patch End
...
}
...
}
frameworks/base/services/core/java/com/android/server/SystemClockTime.java
/**
* 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);
}
}
1863

被折叠的 条评论
为什么被折叠?



