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);
        }
    }
相关推荐
Doro再努力1 天前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
Daniel李华1 天前
echarts使用案例
android·javascript·echarts
做人不要太理性1 天前
CANN Runtime 运行时组件深度解析:任务调度机制、存储管理策略与维测体系构建逻辑
android·运维·魔珐星云
我命由我123451 天前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
朗迹 - 张伟1 天前
Tauri2 导出 Android 详细教程
android
lpruoyu1 天前
【Android第一行代码学习笔记】Android架构_四大组件_权限_持久化_通知_异步_服务
android·笔记·学习
独自破碎E1 天前
【BISHI15】小红的夹吃棋
android·java·开发语言
李堇1 天前
android滚动列表VerticalRollingTextView
android·java
lxysbly2 天前
n64模拟器安卓版带金手指2026
android
游戏开发爱好者82 天前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview