一,现象:
1. NTP介绍
NTP:网络时间协议,英文名称:Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。NTP的目的是在无序的Internet环境中提供精确和健壮的时间服务。
Android系统使用NTP自动更新系统时间的触发机制:
监听数据库字段AUTO_TIME,当这个字段发生变化的时候,会立即触发一次时间同步
网络连接发生变化,当网络接通,会触发一次时间检查和同步
定时更新机制,当预定的时间到了,会触发一次时间检查和同步
Android自动同步时间是通过NtpServer来同步时间的,但是默认的服务器使用的是Google的所以无法连接,会导致自动同步日期和时间无效。
2. NTP时间设置流程示意图:
二,解决方案:
以下修改都在源码frameworks/base/
下
1. 修改默认的Ntp服务器
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 129cee58078..8ffc237c7e1 100755
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -229,4 +229,6 @@<integer name="def_screenshot_button_show">1</integer><!-- the store location of screen capture by default--><string name="def_screenshot_location">internal_storage</string>
+
+ <string name="def_ntp_server" translatable="false">time.windows.com</string>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 0ba3a5289ed..29361ad19bc 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2733,6 +2733,9 @@ class DatabaseHelper extends SQLiteOpenHelper {loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED,ImsConfig.FeatureValueConstants.ON);+ loadStringSetting(stmt, Settings.Global.NTP_SERVER,
+ R.string.def_ntp_server);
+/** IMPORTANT: Do not add any more upgrade steps here as the global,* secure, and system settings are no longer stored in a database
2. 修改NTP基础配置
<!-- Remote server that can provide NTP responses. -->
<string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
<!-- Normal polling frequency in milliseconds -->
<integer name="config_ntpPollingInterval">86400000</integer>
<!-- Try-again polling interval in milliseconds, in case the network request failed -->
<integer name="config_ntpPollingIntervalShorter">30000</integer>
<!-- Number of times to try again with the shorter interval, before backingoff until the normal polling interval. A value < 0 indicates infinite. -->
<integer name="config_ntpRetry">5</integer>
<!-- Timeout to wait for NTP server response in milliseconds. -->
<integer name="config_ntpTimeout">10</integer>
2.android.pool.ntp.org:这个是NTP服务器地址
86400000:周期默认8640000ms,即1天,一般不改
30000:是由于网络原因,时间同步失败后,retry的时间间隔,默认是60000ms,即60s这里改成30s
5:retry的次数,默认是3次
10:时间误差,默认是5000ms,当时间误差超过5s,会更新系统时间,改成10ms.
wifi自动确定时间的问题时,NTP服务器可以自行更换为自己增加列表中的地址,例如:
<string translatable="false" name="config_ntpServer">ntp1.aliyun.com</string>
3. 增加NTP列表
添加多个Ntp服务器用于轮询,避免默认Ntp服务器失效;安卓10以后ntp的判定规则有所不同,所以代码有所差异。
1. Android10之前(Android7.1)修改
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index ed2d3c60fcd..60ad5d9f132 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -39,7 +39,7 @@ public class NtpTrustedTime implements TrustedTime {private static NtpTrustedTime sSingleton;private static Context sContext;- private final String mServer;
+ private String mServer;private final long mTimeout;private ConnectivityManager mCM;
@@ -49,6 +49,15 @@ public class NtpTrustedTime implements TrustedTime {private long mCachedNtpElapsedRealtime;private long mCachedNtpCertainty;+ String[] backupNtpServers = new String[]{
+ "tw.pool.ntp.org",
+ "time.nist.gov",
+ "time-a.nist.gov",
+ "ntp1.aliyun.com"
+ };
+ int index = -1;
+
+private NtpTrustedTime(String server, long timeout) {if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server);mServer = server;
@@ -101,15 +110,29 @@ public class NtpTrustedTime implements TrustedTime {if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");final SntpClient client = new SntpClient();
- if (client.requestTime(mServer, (int) mTimeout)) {
- mHasCache = true;
- mCachedNtpTime = client.getNtpTime();
- mCachedNtpElapsedRealtime = client.getNtpTimeReference();
- mCachedNtpCertainty = client.getRoundTripTime() / 2;
- return true;
- } else {
- return false;
+
+ boolean result = false;
+ while(!(result = client.requestTime(mServer, (int)mTimeout)) && index < (backupNtpServers.length-1)){
+ index++;
+ mServer = backupNtpServers[index];}
+ index = -1;
+ Resources res = sContext.getResources();
+ String defaultServer = res.getString(
+ com.android.internal.R.string.config_ntpServer);
+ String secureServer = Settings.Global.getString(
+ sContext.getContentResolver(), Settings.Global.NTP_SERVER);
+
+ mServer = secureServer != null ? secureServer : defaultServer;
+
+ if(result){
+ mHasCache = true;
+ mCachedNtpTime = client.getNtpTime();
+ mCachedNtpElapsedRealtime = client.getNtpTimeReference();
+ mCachedNtpCertainty = client.getRoundTripTime() / 2;
+ }
+
+ return result;}@Override
2. Android10之后(Android11.0)修改
diff --git a/frameworks/base/core/java/android/util/NtpTrustedTime.java b/frameworks/base/core/java/android/util/NtpTrustedTime.java
old mode 100644
new mode 100755
index 0892c94d5b..bb8f894cb3
--- a/frameworks/base/core/java/android/util/NtpTrustedTime.java
+++ b/frameworks/base/core/java/android/util/NtpTrustedTime.java
@@ -98,6 +98,27 @@ public class NtpTrustedTime implements TrustedTime {private static NtpTrustedTime sSingleton;
+ String[] backupNtpServers = new String[]{
+ "time.nist.gov",
+ "time-a.nist.gov",
+ "ntp1.aliyun.com",
+ "ntp2.aliyun.com",
+ "ntp3.aliyun.com",
+ "ntp-sz.chl.la",
+ "3.cn.pool.ntp.org",
+ "asia.pool.ntp.org",
+ "cn.pool.ntp.org",
+ "sg.pool.ntp.org",
+ "jp.pool.ntp.org",
+ "hk.pool.ntp.org",
+ "s2g.time.edu.cn",
+ "oceania.pool.ntp.org",
+ "south-america.pool.ntp.org",
+ "north-america.pool.ntp.org",
+ "tw.pool.ntp.org",
+ };
+ int index = -1;
+@NonNullprivate final Context mContext;
@@ -162,12 +183,18 @@ public class NtpTrustedTime implements TrustedTime {if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");final SntpClient client = new SntpClient();
- final String serverName = connectionInfo.getServer();
+ boolean result = false;
+ String serverName = connectionInfo.getServer();
+ if (LOGD) Log.d(TAG, "----------rockemd-add-20221027-serverName--1------"+serverName);final int timeoutMillis = connectionInfo.getTimeoutMillis();
- if (client.requestTime(serverName, timeoutMillis, network)) {
+ while (!(result = client.requestTime(serverName, timeoutMillis, network)) && index < (backupNtpServers.length-1) ) {
+ index++;
+ serverName = backupNtpServers[index];
+ if (LOGD) Log.d(TAG, "----------rockemd-add-20221027-serverName--------"+serverName);
+ }
+ if(result){long ntpCertainty = client.getRoundTripTime() / 2;
- mTimeResult = new TimeResult(
- client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
+ mTimeResult = new TimeResult(client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);return true;} else {return false;
三,调试:
1. 通过adb更改当前服务器地址
adb shell settings put global ntp_server ntp.ntsc.ac.cn //更改服务器地址
adb shell setprop persist.sys.timezone Asia/Shangha //更改时区
adb shell settings get global ntp_server //查看当前使用地址
adb shel1 settings put global auto_time 1 //打开网络同步时间开关
adb shel1 settings put global auto_time 0 //关闭网络同步时间开关