Android NTP时间同步源码分析

Android NTP时间同步源码分析

  • Android系统设置自动时间后,如果连接了可用的网络。会同步网络时间。这个处理是 NetworkTimeUpdateService完成的。
  • 某些定制化的系统,需要禁止网络时间同步。比如仅仅使用GPS时间。基于Android9,分析一下 Android NTP时间的同步流程。

时序图:
在这里插入图片描述

  • 服务启动:NetworkTimeUpdateService在SystemServer的startOtherServices中启动(frameworks/base/services/java/com/android/server/SystemServer.java)
if (!isWatch) {
    
    
	traceBeginAndSlog("StartNetworkTimeUpdateService");
	try {
    
    
		networkTimeUpdater = new NetworkTimeUpdateService(context);
		ServiceManager.addService("network_time_update_service", networkTimeUpdater);
	} catch (Throwable e) {
    
    
		reportWtf("starting NetworkTimeUpdate service", e);
	}
	traceEnd();
}
// 省略
try {
    
    
	if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
} catch (Throwable e) {
    
    
	reportWtf("Notifying NetworkTimeService running", e);
}
  • NetworkTimeUpdateService启动过程中,会调用NTP、Conectivity服务,注册监听NITZ、监听自动时间设定项(frameworks/base/services/core/java/com/android/server/NetworkTimeUpdateService.java)
public NetworkTimeUpdateService(Context context) {
    
    
	mContext = context;
	mTime = NtpTrustedTime.getInstance(context);
	mAlarmManager = mContext.getSystemService(AlarmManager.class);
	mCM = mContext.getSystemService(ConnectivityManager.class);

	Intent pollIntent = new Intent(ACTION_POLL, null);
	mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);

	mPollingIntervalMs = mContext.getResources().getInteger(
			com.android.internal.R.integer.config_ntpPollingInterval);
	mPollingIntervalShorterMs = mContext.getResources().getInteger(
			com.android.internal.R.integer.config_ntpPollingIntervalShorter);
	mTryAgainTimesMax = mContext.getResources().getInteger(
			com.android.internal.R.integer.config_ntpRetry);
	mTimeErrorThresholdMs = mContext.getResources().getInteger(
			com.android.internal.R.integer.config_ntpThreshold);

	mWakeLock = context.getSystemService(PowerManager.class).newWakeLock(
			PowerManager.PARTIAL_WAKE_LOCK, TAG);
}

/** Initialize the receivers and initiate the first NTP request */
public void systemRunning() {
    
    
	registerForTelephonyIntents();
	registerForAlarms();

	HandlerThread thread = new HandlerThread(TAG);
	thread.start();
	mHandler = new MyHandler(thread.getLooper());
	mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
	mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);

	mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
	mSettingsObserver.observe(mContext);
}
  • 当自动时间设定变更、网络状态变更、更新周期达到时,会触发NetworkTimeUpdateService更新系统时间。通过获取NTP时间,以及进行各种判断(比如近期是否更新过NITZ时间),最终判断是否使用NTP时间更新(参考上面的时序图)
/** Handler to do the network accesses on */
private class MyHandler extends Handler {
    
    

	public MyHandler(Looper l) {
    
    
		super(l);
	}

	@Override
	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;
		}
	}
}

private void onPollNetworkTime(int event) {
    
    
	// If Automatic time is not set, don't bother. Similarly, if we don't
	// have any default network, don't bother.
	if (mDefaultNetwork == null) return;
	mWakeLock.acquire();
	try {
    
    
		onPollNetworkTimeUnderWakeLock(event);
	} finally {
    
    
		mWakeLock.release();
	}
}

private void onPollNetworkTimeUnderWakeLock(int event) {
    
    
	// Force an NTP fix when outdated
	if (mTime.getCacheAge() >= mPollingIntervalMs) {
    
    
		if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
		mTime.forceRefresh();
	}

	if (mTime.getCacheAge() < mPollingIntervalMs) {
    
    
		// Obtained fresh fix; schedule next normal update
		resetAlarm(mPollingIntervalMs);
		if (isAutomaticTimeRequested()) {
    
    
			updateSystemClock(event);
		}

	} else {
    
    
		// No fresh fix; schedule retry
		mTryAgainCounter++;
		if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
    
    
			resetAlarm(mPollingIntervalShorterMs);
		} else {
    
    
			// Try much later
			mTryAgainCounter = 0;
			resetAlarm(mPollingIntervalMs);
		}
	}
}

private void updateSystemClock(int event) {
    
    
	final boolean forceUpdate = (event == EVENT_AUTO_TIME_CHANGED);
	if (!forceUpdate) {
    
    
		if (getNitzAge() < mPollingIntervalMs) {
    
    
			if (DBG) Log.d(TAG, "Ignoring NTP update due to recent NITZ");
			return;
		}

		final long skew = Math.abs(mTime.currentTimeMillis() - System.currentTimeMillis());
		if (skew < mTimeErrorThresholdMs) {
    
    
			if (DBG) Log.d(TAG, "Ignoring NTP update due to low skew");
			return;
		}
	}

	SystemClock.setCurrentTimeMillis(mTime.currentTimeMillis());
}
  • 上面的代码,是基于Android9的。在Android12中引入了 TimeDetect服务,通过配置frameworks/base/core/res/res/values/config.xml中的 “config_autoTimeSourcesPriority”这个设定项,指定优先的时间源。所以在Android12中,NetworkTimeUpdateService会将时间更新请求发送给 TimeDetect服务,而不是直接使用SystemClock更新时间。关于Android12的NetworkTimeUpdateService详细流程,这里不进行分析。

猜你喜欢

转载自blog.csdn.net/zxc024000/article/details/131625729