一,现象:
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.xmlindex 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.javaindex 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 backing off 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.javaindex 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.javaold mode 100644new mode 100755index 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;+ @NonNull private 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 //关闭网络同步时间开关