[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详解

阅读全文
1 0
原创粉丝点击