[RK3288][Android6.0] WiFi之同步网络时间过程

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

2.android.pool.ntp.org

也就是说时间是从这个远程的server获取的。

参考:
Android 时间同步原理分析
Android中内容观察者的使用—- ContentObserver类详解
Android 7.1.1时间更新NITZ和NTP详解

你可能感兴趣的:(子类__WiFi)