android 9.x 开机自动同步时间较慢(2~3分钟)

问题描述

不插sim卡,连接wifi启动,系统时间在2~3分钟之后才会同步到最新时间。

NITZ和NTP机制

在解决这个问题之前,让我们来学习一下NITZ和NTP的相关知识
NITZ:Network Identity and Time Zone(网络标识和时区),是一种用于自动配置本地的时间和日期的机制,需要运营商支持,可从运营商获取时间和时区具体信息。NITZ是自从PHASE 2+ RELEASE 96 的GSM中的可选功能,经常被用来自动更新移动电话的系统时钟。NITZ需要运营商网络支持(通过CS网络),目前国内电信、移动都支持NITZ方式更新时间日期,而联通目前不支持。
NTP:Network Time Protocol(网络时间协议),用来同步网络中各个计算机的时间的协议。在手机中,NTP更新时间的方式是通过GPRS或wifi向特定服务器获取时间信息(不包含时区信息)。

关于NITZ和NTP更新时间流程,建议参考博客:https://blog.csdn.net/yin1031468524/article/details/65447849
大佬的流程写的非常详细,建议大家去学习学习。

解决问题

遇事不决先抓Log,先来看看过滤ntp字段后的日志

	Line 3819: 03-10 12:42:15.954   908  1079 W BestClock: java.time.DateTimeException: Missing NTP fix
	Line 3827: 03-10 12:42:15.958   908  1079 W BestClock: java.time.DateTimeException: Missing NTP fix
	Line 3829: 03-10 12:42:15.960   908  1073 W BestClock: java.time.DateTimeException: Missing NTP fix
	Line 3831: 03-10 12:42:15.967   908  1073 W BestClock: java.time.DateTimeException: Missing NTP fix
	Line 4857: 03-10 12:42:20.994   908  1224 D SntpClient: request time failed: java.net.SocketTimeoutException: Poll timed out
	Line 4858: 03-10 12:42:20.995   908  1224 D NtpTrustedTime: setServer:[time.android.com]
	Line 5510: 03-10 12:42:25.708   908  1072 W BestClock: java.time.DateTimeException: Missing NTP fix
	Line 5526: 03-10 12:42:25.729   908  1072 W BestClock: java.time.DateTimeException: Missing NTP fix
	Line 5527: 03-10 12:42:25.731   908  1073 W BestClock: java.time.DateTimeException: Missing NTP fix
	Line 7007: 03-10 12:43:21.408   908  1224 D NetworkTimeUpdateService: Stale NTP fix; forcing refresh
	Line 7008: 03-10 12:43:21.408   908  1224 D NetworkTimeUpdateService: mTryAgainCounter = 1;mNtpServers.size() = 2;index = 1;mNtpServers = asia.pool.ntp.org
	Line 7009: 03-10 12:43:21.408   908  1224 D NtpTrustedTime: setServer:[asia.pool.ntp.org]
	Line 7152: 03-10 12:43:21.636   908  1224 D SntpClient: round trip: 209ms, clock offset: 7919964ms

先来看看java.time.DateTimeException: Missing NTP fix这个异常,定位到代码位置
/frameworks/base/services/core/java/com/android/server/AlarmManagerService.java

        @Override
        public long currentNetworkTimeMillis() {
            final NtpTrustedTime time = NtpTrustedTime.getInstance(getContext());
            if (time.hasCache()) {
                return time.currentTimeMillis();
            } else {
                throw new ParcelableException(new DateTimeException("Missing NTP fix"));
            }
        }

接着看time.hasCache()方法
/frameworks/base/core/java/android/util/NtpTrustedTime.java

    @Override
    public boolean hasCache() {
        return mHasCache;
    }

    public boolean forceRefresh(Network network) {
		............
        if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
        final SntpClient client = new SntpClient();
        if (client.requestTime(mServer, (int) mTimeout, network)) {
            mHasCache = true;
            mCachedNtpTime = client.getNtpTime();
            mCachedNtpElapsedRealtime = client.getNtpTimeReference();
            mCachedNtpCertainty = client.getRoundTripTime() / 2;
            return true;
        } else {
            return false;
        }
    }

只有client.requestTime()获取时间成功,才会把mHasCache置为true,说明这些异常发生时,获取时间一直是失败的。

继续看日志:

NtpTrustedTime: setServer:[time.android.com]

设置ntp server为time.android.com之后,还是会出现Missing NTP fix的异常,获取时间失败。

再往下看日志:

NetworkTimeUpdateService: mTryAgainCounter = 1;mNtpServers.size() = 2;index = 1;mNtpServers = asia.pool.ntp.org
NtpTrustedTime: setServer:[asia.pool.ntp.org]
SntpClient: round trip: 209ms, clock offset: 7919964ms

对应到代码,在这个位置:
/frameworks/base/services/core/java/com/android/server/NetworkTimeUpdateService.java

    private void onPollNetworkTimeUnderWakeLock(int event) {
        // Force an NTP fix when outdated
        if (mTime.getCacheAge() >= mPollingIntervalMs) {
            if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
            //M: For multiple NTP server retry
            //mTime.forceRefresh();
            int index = mTryAgainCounter % mNtpServers.size();
            if (DBG) Log.d(TAG, "mTryAgainCounter = " + mTryAgainCounter
                + ";mNtpServers.size() = " + mNtpServers.size()
                + ";index = " + index + ";mNtpServers = " + mNtpServers.get(index));
            //轮询ntp server
            if (mTime instanceof NtpTrustedTime){
                ((NtpTrustedTime) mTime).setServer(mNtpServers.get(index));
                mTime.forceRefresh();
                ((NtpTrustedTime) mTime).setServer(mDefaultServer);
            }
            else{
                mTime.forceRefresh();
            }
        }
        if (mTime.getCacheAge() < mPollingIntervalMs) {
            // Obtained fresh fix; schedule next normal update
            resetAlarm(mPollingIntervalMs);
            if (isAutomaticTimeRequested()) {
                updateSystemClock(event);
            }
        } else {
            // No fresh fix; schedule retry
            mTryAgainCounter++;
            if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
                resetAlarm(mPollingIntervalShorterMs);
            } else {
                // Try much later
                mTryAgainCounter = 0;
                resetAlarm(mPollingIntervalMs);
            }
        }
    }

onPollNetworkTimeUnderWakeLock()方法里面轮询访问ntp server获取时间。
adb shell进去设备,分别ping服务器time.android.com和asia.pool.ntp.org,前者Ping不同,后者可以ping通。

继续看代码resetAlarm()方法,发现轮训的时间间隔是60秒,和这个问题的现象对上了。


    private void resetAlarm(long interval) {
        mAlarmManager.cancel(mPendingPollIntent);
        long now = SystemClock.elapsedRealtime();
        long next = now + interval;
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
    }
        ...........
        mPollingIntervalShorterMs = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_ntpPollingIntervalShorter);


     <!-- Remote server that can provide NTP responses. -->
    <string translatable="false" name="config_ntpServer">time.android.com</string>
    <!-- Try-again polling interval in milliseconds, in case the network request failed -->
    <integer name="config_ntpPollingIntervalShorter">60000</integer>

修改config_ntpServer的值为2.android.pool.ntp.org,提前验证好,可以ping通。
编译framework-res.apk,push之后开机,时间更新及时,问题解决。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现开机自动打开 WiFi,你需要修改 Android 源代码中的系统设置应用程序(com.android.settings)。 首先,你需要下载 Android 源代码并进行编译。然后,在源代码中找到 com.android.settings 应用程序的代码。你需要修改的文件是 Settings.java。 在 Settings.java 文件中,你需要添加以下代码: ```java private static final String WIFI_ON_BOOT = "wifi_on_boot"; // 在 onCreate 方法中添加以下代码 Preference wifiOnBoot = findPreference(WIFI_ON_BOOT); wifiOnBoot.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { setWifiOnBoot(((CheckBoxPreference) preference).isChecked()); return true; } }); // 添加以下方法 private void setWifiOnBoot(boolean isChecked) { int flag = isChecked ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; ComponentName receiver = new ComponentName(this, WifiOnBootReceiver.class); PackageManager pm = getPackageManager(); pm.setComponentEnabledSetting(receiver, flag, PackageManager.DONT_KILL_APP); } // 添加以下类 public static class WifiOnBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); wifiManager.setWifiEnabled(true); } } ``` 这段代码会在系统设置应用程序的界面上添加一个“开机自动打开 WiFi”的开关。当用户打开开关时,系统会注册一个广播接收器(WifiOnBootReceiver),在系统启动时自动打开 WiFi。 最后,你需要重新编译 Android 系统并将其刷入你的设备。这样,你的设备就会在开机自动打开 WiFi。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值