[RK3288][Android6.0] WiFi之同步网络时间过程
来源:互联网 发布:什么看书软件免费 编辑:程序博客网 时间:2024/06/03 11:17
Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
Android从外部同步时间的方式有两种
1. 从运营商获取,也就是插SIM卡的方式获取,运营商提供时间和时区,用的是NITZ协议
2. 网络获取时间,也就是WIFI或GPS的方式获取,网络只能提供时间,用的是SNTP协议(NTP协议的精简版)
这里关注在连接Wifi的情况下,开启自动获取时间,这时会调用:
onSharedPreferenceChanged -> DateTimeSettings.java //在initUI()初始化监听
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (key.equals(KEY_AUTO_TIME)) { boolean autoEnabled = preferences.getBoolean(key, true); //设置AUTO_TIME为enable到ContentProvider中 Settings.Global.putInt(getContentResolver(), Settings.Global.AUTO_TIME, autoEnabled ? 1 : 0); mTimePref.setEnabled(!autoEnabled); mDatePref.setEnabled(!autoEnabled); } else if (key.equals(KEY_AUTO_TIME_ZONE)) { boolean autoZoneEnabled = preferences.getBoolean(key, true); Settings.Global.putInt( getContentResolver(), Settings.Global.AUTO_TIME_ZONE, autoZoneEnabled ? 1 : 0); mTimeZone.setEnabled(!autoZoneEnabled); }}
另一方面,SettingsObserver监听Settings.Global.AUTO_TIME的变化,使用的是observer机制,机制可查看后面参考
private static class SettingsObserver extends ContentObserver { void observe(Context context) { ContentResolver resolver = context.getContentResolver(); resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME), false, this); }}
当Settings.Global.AUTO_TIME变化时,SettingsObserver收到EVENT_AUTO_TIME_CHANGED事件被触发
private static class SettingsObserver extends ContentObserver { @Override public void onChange(boolean selfChange) { //发给handler处理 mHandler.obtainMessage(mMsg).sendToTarget(); }}
public void handleMessage(Message msg) { switch (msg.what) { case EVENT_AUTO_TIME_CHANGED: case EVENT_POLL_NETWORK_TIME: case EVENT_NETWORK_CHANGED: onPollNetworkTime(msg.what); break; }}
onPollNetworkTime -> onPollNetworkTimeUnderWakeLock
private void onPollNetworkTimeUnderWakeLock(int event){ //系统开机时间 final long refTime = SystemClock.elapsedRealtime(); // If NITZ time was received less than mPollingIntervalMs time ago, // no need to sync to NTP. //如果已经从运行商(有SIM卡的情况)那边获取时间而且是在mPollingIntervalMs时间内设置过,那么就不设置NTP了 //mPollingIntervalMs在framework/base/core/res/res/values/config.xml配置,为864000000,也就是10天 if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) { resetAlarm(mPollingIntervalMs); return; } final long currentTime = System.currentTimeMillis(); if (DBG) Log.d(TAG, "System time = " + currentTime); // Get the NTP time if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs || event == EVENT_AUTO_TIME_CHANGED) { if (DBG) Log.d(TAG, "Before Ntp fetch"); // force refresh NTP cache when outdated //如果缓存超过了10天,就重新获取,mTime即NtpTrustedTime类 if (mTime.getCacheAge() >= mPollingIntervalMs) { mTime.forceRefresh(); } // only update when NTP time is fresh //NTP时间刷新后更新本地时间, if (mTime.getCacheAge() < mPollingIntervalMs) { final long ntp = mTime.currentTimeMillis(); mTryAgainCounter = 0; // If the clock is more than N seconds off or this is the first time it's been // fetched since boot, set the current time. //当NTP与本地时间的差比mTimeErrorThresholdMs大时才能更新时间 if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs || mLastNtpFetchTime == NOT_SET) { // Set the system time if (DBG && mLastNtpFetchTime == NOT_SET && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) { Log.d(TAG, "For initial setup, rtc = " + currentTime); } if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp); // Make sure we don't overflow, since it's going to be converted to an int if (ntp / 1000 < Integer.MAX_VALUE) { //设置成本地时间 SystemClock.setCurrentTimeMillis(ntp); } } else { if (DBG) Log.d(TAG, "Ntp time is close enough = " + ntp); } mLastNtpFetchTime = SystemClock.elapsedRealtime(); } else { // Try again shortly mTryAgainCounter++; if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) { resetAlarm(mPollingIntervalShorterMs); } else { // Try much later mTryAgainCounter = 0; resetAlarm(mPollingIntervalMs); } return; } } resetAlarm(mPollingIntervalMs);}
NtpTrustedTime.java:
public boolean forceRefresh() { //sntp协议 final SntpClient client = new SntpClient(); //请求时间 if (client.requestTime(mServer, (int) mTimeout)) { mHasCache = true; mCachedNtpTime = client.getNtpTime(); //更新后会改变getCacheAge()的值,上面设置到本地时间会判断 mCachedNtpElapsedRealtime = client.getNtpTimeReference(); mCachedNtpCertainty = client.getRoundTripTime() / 2; return true; } else { return false; }}
mServer为 res.getString(com.android.internal.R.string.config_ntpServer)
对应的配置文件在./core/res/res/values/config.xml <!-- Remote server that can provide NTP responses. -->
<string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
也就是说时间是从这个远程的server获取的。
参考:
Android 时间同步原理分析
Android中内容观察者的使用—- ContentObserver类详解
Android 7.1.1时间更新NITZ和NTP详解
- [RK3288][Android6.0] WiFi之同步网络时间过程
- [RK3288][Android6.0] WiFi之网络时间定期同步更新
- [RK3288][Android6.0] WiFi之wpa_supplicant初始化过程
- [RK3288][Android6.0] WiFi之wpa_supplicant扫描过程
- [RK3288][Android6.0] WiFi之Framework扫描过程
- [RK3288][Android6.0] WiFi之Framework连接过程小结
- [RK3288][Android6.0] WiFi之开机自动连接过程
- [RK3288][Android6.0] WiFi之无线网络配置的保存过程
- [RK3288][Android6.0] WiFi之无线网络配置的断开过程
- [RK3288][Android6.0] WiFi之无线网络配置的关闭过程
- [RK3288][Android6.0] WiFi之WifiWatchdogStateMachine
- [RK3288][Android6.0] WiFi之通过wpa_cli分析WPAS的连接过程
- [RK3288][Android6.0] WiFi之无线网络配置的忘记(移除)过程
- [RK3288][Android6.0] WiFi在Setting中的开启过程小结
- [RK3288][Android6.0] WiFi的驱动初始化过程小结
- [RK3288][Android6.0] WiFi之wpa_supplicant服务启动
- [RK3288][Android6.0] WiFi之Framework的socket(客户端)
- [RK3288][Android6.0] WiFi之wpa_supplicant的socket(服务端)
- 自动化测试二--测试框架设计
- HTML弹窗加蒙层
- hibernate和jpa注意
- RecyclerView的使用和优化
- Monitor.TryEnter方法和lock语句的使用注意
- [RK3288][Android6.0] WiFi之同步网络时间过程
- windows下写的shell脚本在linux执行出错的解决办法
- Selenium2+python自动化-元素定位参数化(find_element)
- linux模块驱动简单的Makefile
- 获取当前控制器
- 接口模拟框架 MockApi
- Debian下安装Go开发环境
- 一秒钟教你理解什么是异步什么是同步!
- Tensorflow 官方文档 Feed章节有误