Android 10&15 Framework 允许设置系统时间早于编译时间

文章目录

Android系统时间⌚相关文章
Android 10&15 Framework 允许设置系统时间早于编译时间
Android10设置未来时间后自动更新时间失败
Android10实现根据定位自动更新时区

一、背景说明

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);
        }
    }
相关推荐
墨天梦2 小时前
D03_Compose列表与稳定身份
android·gitee·kotlin
萌新杰少3 小时前
Kuikly股票查看软件开发体验——SaiRen
android·kotlin·客户端
vilya3 小时前
把 Python 塞进 APK:Chaquopy 打包实践
android·python
用户92817267390163 小时前
Android Compose版本的AI组件库来了。
android·kotlin
知昂七昂3 小时前
00-02:AOSP 源码阅读环境与检索方法论源码剖析(Android 16 / aosp-main)
android
知昂七昂3 小时前
00-01:AOSP 源码仓库结构与 repo 工作流源码剖析(Android 16 / aosp-main)
android·google
跨境数据猎手3 小时前
Android Native 层黑盒调用实战:unidbg 模拟执行 so 的原理
android
镜象科技4 小时前
中小学AI心理健康解决方案服务商怎么选?2026年选型参考
android·java·人工智能
脚踏实地,坚持不懈!4 小时前
从 AOSP 源码角度分析 Android 定位性能问题
android
悟道子HD5 小时前
网络安全基本功——MySQL基础
android·mysql·web安全