Android 系统时间自动更新机制
来源:互联网 发布:ubuntu var tmp 编辑:程序博客网 时间:2024/06/14 11:57
两种时间更新机制
NITZ
NITZ(Network Identity and Time Zone,网络标识和时区),是一种用于自动配置本地的时间和日期的机制,同时也通过无线网向移动设备提供运营商信息。NITZ是自从PHASE 2+ RELEASE 96 的GSM中的可选功能,经常被用来自动更新移动电话的系统时钟。NITZ需要运营商网络支持(通过CS网络),目前国内电信、移动都支持NITZ方式更新时间日期,而联通目前不支持。
参考: https://en.wikipedia.org/wiki/NITZ
NTP
NTP:NTP(Network Time Protocol)提供准确时间,首先要有准确的时间来源,这一时间应该是国际标准时间UTC。 NTP获得UTC的时间来源可以是原子钟、天文台、卫星,也可以从Internet上获取。这样就有了准确而可靠的时间源。时间按NTP服务器的等级传播。与NITZ不同的是,NTP需要从专门的NTP服务器来获取时间,只要手机连接上网络,都可以实现时间的更新。
参考: https://en.wikipedia.org/wiki/Network_Time_Protocol
Android如何更新系统时间
Android有一个专门的系统服务 NetworkTimeUpdateServcie
来负责更新系统时间,该服务在系统启动时在SystemServer.java
中被创建:
if (!disableNetwork && !disableNetworkTime) { try { Slog.i(TAG, "NetworkTimeUpdateService"); networkTimeUpdater = new NetworkTimeUpdateService(context); } catch (Throwable e) { reportWtf("starting NetworkTimeUpdate service", e); } } ... ... try { if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying NetworkTimeService running", e); }
源码:
/frameworks/base/services/core/java/com/android/server/NetworkTimeUpdateService.java
服务初始化
NetworkTimeUpdateService
初始时会:
- 注册RIL的ACTION_NETWORK_SET_TIME以及ACTION_NETWORK_SET_TIMEZONE事件,以接受来自Telephony FW的NITZ时间更新;
- 监听 ACTION_POLL事件(定时更新时间)以及手机网络连接状态;
- 发送消息同步NTP时间
- 监听 Settings中“自动更新时间”选项的变化
/** Initialize the receivers and initiate the first NTP request */ public void systemRunning() { registerForTelephonyIntents(); registerForAlarms(); registerForConnectivityIntents(); HandlerThread thread = new HandlerThread(TAG); thread.start(); mHandler = new MyHandler(thread.getLooper()); // Check the network time on the new thread mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget(); mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED); mSettingsObserver.observe(mContext); }
同步NTP时间
如果没有收到NITZ时间的更新并且NTP超过一定间隔没有更新时间,服务会主动去同步NTP时间:
// force refresh NTP cache when outdated if (mTime.getCacheAge() >= mPollingIntervalMs) { mTime.forceRefresh(); }
NTP从服务器获取时间:
@Override public boolean forceRefresh() { ... // We can't do this at initialization time: ConnectivityService might not be running yet. synchronized (this) { if (mCM == null) { mCM = (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE); } } ... 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; } }
源码: /frameworks/base/core/java/android/util/NtpTrustedTime.java
接收NITZ时间
Telephony Framework层在接收到最新的NITZ时间后,会主动发送广播请求更新系统时间,NetworkTimeUpateService接收到广播后,保存相应的NITZ时间,下一次poll请求时,就会将该事件更新为系统时间。
private BroadcastReceiver mNitzReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) { mNitzTimeSetTime = SystemClock.elapsedRealtime(); } else if (TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE.equals(action)) { mNitzZoneSetTime = SystemClock.elapsedRealtime(); } } };
监听Settings中 “自动确定时间和日期”的变化
在setting中勾选“自动确定时间和日期”、“自动确定时区”后对key值为AUTO_TIME和AUTO_TIME_ZONE的Preference进行了赋值.
源码路径:packages/apps/Settings/src/com/android/settings/DateTimeSettings.java
void observe(Context context) { ContentResolver resolver = context.getContentResolver(); resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME), false, this); } @Override public void onChange(boolean selfChange) { mHandler.obtainMessage(mMsg).sendToTarget(); }
NetworkTimeUpdateService
在检测到key值改变的时,就会发送一个消息EVENT_AUTO_TIME_CHANGED
;handler接到消息后进行消息处理调用onPollNetworkTime(msg.what)
:
public void handleMessage(Message msg) { switch (msg.what) { case EVENT_AUTO_TIME_CHANGED: case EVENT_POLL_NETWORK_TIME: case EVENT_NETWORK_CONNECTED: onPollNetworkTime(msg.what); break; } }
在onPollNetworkTime方法中先判断是否勾选“自动更新时间”,如果没勾选直接退出,如果勾选了再看。如果NITZ已经更新了(不为NOT_SET(-1)),且更新间隔小于mPollingIntervalMs(mPollingIntervalMs=24*60*60*1000),则直接用NITZ更新系统时间,否则用NTP同步时间。
// If NITZ time was received less than mPollingIntervalMs time ago, // no need to sync to NTP. if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) { resetAlarm(mPollingIntervalMs); return; } 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. if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs || mLastNtpFetchTime == NOT_SET) { // Set the system time ...... if (ntp / 1000 < Integer.MAX_VALUE) { SystemClock.setCurrentTimeMillis(ntp); }
当从NTP服务器上获取的时间和当前时间之差的绝对值大于一个阀值,则认为当前时间错误,需要更新时间。
总结:
- 时间自动同步选项未勾选,不主动更新时间,直接返回;
- NITZ已同步且上次NITZ同步未超过24小时,则设置定时器24小时后再触发同步,即广播NetworkTimeUpdateService.ACTION_POLL;
- NTP上次成功同步超过24小时或用户勾选自动同步选项,则进行下面的NTP同步,否则同上设置定时器24小时后再触发同步
参考文献
- http://www.2cto.com/kf/201409/334153.html
- http://blog.csdn.net/lindir/article/details/7973700
- https://en.wikipedia.org/wiki/NITZ
- https://en.wikipedia.org/wiki/Network_Time_Protocol
- Android 系统时间自动更新机制
- [android]时间自动更新机制
- android自动更新时间时区机制
- android 中自动更新时间机制
- Ubuntu 自动更新系统时间
- Android的自动更新时间
- Android中的时间自动更新
- Android中的时间自动更新
- android自动更新时间mark
- Android中的时间自动更新
- Android中的时间自动更新
- Android中的时间自动更新
- Android中的时间自动更新
- Android中的时间自动更新
- Android 系统时间更新机制
- Android系统时间同步机制
- Android系统时间更新机制
- 关闭android系统自动更新
- HDU2032杨辉三角
- 网络数据传输需要注意的两个问题
- 长连接 短连接
- 数据挖掘之降维
- HDU2033 时间加法
- Android 系统时间自动更新机制
- HDU2034
- OpenGL ES入门
- raspberry pi安装mentohust
- Android动画小结
- HDU2035 次方某位数字
- HDU2036多边形面积
- 什么是数据挖掘
- 套接字