赞
踩
NTP:网络时间协议,英文名称:Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。NTP的目的是在无序的Internet环境中提供精确和健壮的时间服务。
Android系统使用NTP自动更新系统时间的触发机制有两种:
监听数据库字段AUTO_TIME,当这个字段发生变化的时候,会立即触发一次时间同步
网络连接发生变化,当网络接通,会触发一次时间检查和同步
定时更新机制,当预定的时间到了,会触发一次时间检查和同步
Android系统的使用NTP更新系统时间是在NetworkTimeUpdateService服务里面实现的,首先看一下服务的初始化过程。
mServer服务器名字,在初始化NtpTrustedTime时由config_ntpServer和NTP_SERVER共同制定
@frameworks/base/core/java/android/util/NtpTrustedTime.java private NtpTrustedTime(String server, long timeout) { if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server); mServer = server; mTimeout = timeout; } public static synchronized NtpTrustedTime getInstance(Context context) { if (sSingleton == null) { final Resources res = context.getResources(); final ContentResolver resolver = context.getContentResolver(); final String defaultServer = res.getString( com.android.internal.R.string.config_ntpServer); final long defaultTimeout = res.getInteger( com.android.internal.R.integer.config_ntpTimeout); final String secureServer = Settings.Global.getString( resolver, Settings.Global.NTP_SERVER); final long timeout = Settings.Global.getLong( resolver, Settings.Global.NTP_TIMEOUT, defaultTimeout); final String server = secureServer != null ? secureServer : defaultServer; sSingleton = new NtpTrustedTime(server, timeout); sContext = context; } return sSingleton; }
ntp服务地址: https://www.cnblogs.com/configure/p/13469039.html
<string translatable="false" name="config_ntpServer">time1.aliyun.com</string>
NtpService 调用forceRefresh获取时间,通过获取ConnectivityManager服务,SntpClient.requestTime来获取时间
@frameworks/base/core/java/android/util/NtpTrustedTime.java @Override public boolean forceRefresh() { // We can't do this at initialization time: ConnectivityService might not be running yet. synchronized (this) { if (mCM == null) { mCM = sContext.getSystemService(ConnectivityManager.class); } } final Network network = mCM == null ? null : mCM.getActiveNetwork(); return forceRefresh(network); } public boolean forceRefresh(Network network) { if (TextUtils.isEmpty(mServer)) { // missing server, so no trusted time available return false; } // We can't do this at initialization time: ConnectivityService might not be running yet. synchronized (this) { if (mCM == null) { mCM = sContext.getSystemService(ConnectivityManager.class); } } final NetworkInfo ni = mCM == null ? null : mCM.getNetworkInfo(network); if (ni == null || !ni.isConnected()) { if (LOGD) Log.d(TAG, "forceRefresh: no connectivity"); return false; } if (LOGD) Log.d(TAG, "forceRefresh() from cache miss"); final SntpClient client = new SntpClient(); if (client.requestTime(mServer, (int) mTimeout, network)) { mHasCache = true; mCachedNtpTime = client.getNtpTime(); mCachedNtpElapsedRealtime = client.getNtpTimeReference(); mCachedNtpCertainty = client.getRoundTripTime() / 2; return true; } else { return false; } }
NTpService得到时间
@frameworks/base/core/java/android/util/NtpTrustedTime.java
@Override
public long currentTimeMillis() {
if (!mHasCache) {
throw new IllegalStateException("Missing authoritative time source");
}
if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit");
// current time is age after the last ntp cache; callers who
// want fresh values will hit makeAuthoritative() first.
return mCachedNtpTime + getCacheAge();
}
大概就是mServer,通过socket访问,得到mNtpTime
@frameworks/base/core/java/android/net/SntpClient.java public boolean requestTime(InetAddress address, int port, int timeout, Network network) { DatagramSocket socket = null; final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP); try { socket = new DatagramSocket(); network.bindSocket(socket); socket.setSoTimeout(timeout); byte[] buffer = new byte[NTP_PACKET_SIZE]; DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, port); ... mNtpTime = responseTime + clockOffset; mNtpTimeReference = responseTicks; mRoundTripTime = roundTripTime; } catch (Exception e) { EventLogTags.writeNtpFailure(address.toString(), e.toString()); if (DBG) Log.d(TAG, "request time failed: " + e); return false; } finally { if (socket != null) { socket.close(); } TrafficStats.setThreadStatsTag(oldTag); } return true; }
服务是在startOtherServices启动,并添加到ServiceManager里面,调用systemRunning运行
@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); }
@frameworks/base/services/core/java/com/android/server/NetworkTimeUpdateService.java public NetworkTimeUpdateService(Context context) { mContext = context; // 创建NTP实例,这个就是使用NTP协议取得时间的类 mTime = NtpTrustedTime.getInstance(context); // 取得AlarmManager实例 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); // 从系统配置文件config.ini取得NTP时间参数 // 默认是86400000ms,即1天 mPollingIntervalMs = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpPollingInterval); // 由于网络原因,时间同步失败后,retry的时间间隔,默认是60000ms,即60s mPollingIntervalShorterMs = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpPollingIntervalShorter); // retry的次数,默认是3次 mTryAgainTimesMax = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpRetry); // 时间误差,默认是5000ms,当时间误差超过5s,会更新系统时间 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(); //注册MyHandler HandlerThread thread = new HandlerThread(TAG); thread.start(); mHandler = new MyHandler(thread.getLooper()); mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback(); mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler); //监听SettingProvider AUTO_TIME变化 mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED); mSettingsObserver.observe(mContext); }
private void registerForAlarms() {
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
}
}, new IntentFilter(ACTION_POLL));
}
AUTO_TIME变化就会发送Message更新
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();
}
private class NetworkTimeUpdateCallback extends NetworkCallback {
@Override
public void onAvailable(Network network) {
Log.d(TAG, String.format("New default network %s; checking time.", network));
mDefaultNetwork = network;
// Running on mHandler so invoke directly.
onPollNetworkTime(EVENT_NETWORK_CHANGED);
}
@Override
public void onLost(Network network) {
if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
}
}
变化msg受到都会触发onPollNetworkTime
/** 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 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(); //调用NtpTrustedTime获取时间,见上文 } 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); } } }
最后调用setCurrentTimeMillis设置时间,时间从NtpTrustedTime获取(mTime.currentTimeMillis())
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()); }
调用ALARM_SERVICE的setTime
@frameworks/base/core/java/android/os/SystemClock.java public static boolean setCurrentTimeMillis(long millis) { final IAlarmManager mgr = IAlarmManager.Stub .asInterface(ServiceManager.getService(Context.ALARM_SERVICE)); if (mgr == null) { return false; } try { return mgr.setTime(millis); } catch (RemoteException e) { Slog.e(TAG, "Unable to set RTC", e); } catch (SecurityException e) { Slog.e(TAG, "Unable to set RTC", e); } return false; }
AlarmManagerService添加ServiceManager ALARM_SERVICE
@frameworks/base/services/core/java/com/android/server/AlarmManagerService.java public void onStart() { mNativeData = init(); mNextWakeup = mNextNonWakeup = 0; ... try { ActivityManager.getService().registerUidObserver(new UidObserver(), ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE, ActivityManager.PROCESS_STATE_UNKNOWN, null); } catch (RemoteException e) { // ignored; both services live in system_server } publishBinderService(Context.ALARM_SERVICE, mService); }
注册AlarmManager
@frameworks/base/core/java/android/app/SystemServiceRegistry.java
registerService(Context.ALARM_SERVICE, AlarmManager.class,
new CachedServiceFetcher<AlarmManager>() {
@Override
public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);
IAlarmManager service = IAlarmManager.Stub.asInterface(b);
return new AlarmManager(service, ctx);
}});
IAlarmManager.aidl 提供设置时区时间等方法
@frameworks/base/core/java/android/app/IAlarmManager.aidl
interface IAlarmManager {
/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
void set(String callingPackage, int type, long triggerAtTime, long windowLength,
long interval, int flags, in PendingIntent operation, in IAlarmListener listener,
String listenerTag, in WorkSource workSource, in AlarmManager.AlarmClockInfo alarmClock);
boolean setTime(long millis);
void setTimeZone(String zone);
void remove(in PendingIntent operation, in IAlarmListener listener);
long getNextWakeFromIdleTime();
AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
long currentNetworkTimeMillis();
}
@@frameworks/base/services/core/java/com/android/server/AlarmManagerService.java @Override public boolean setTime(long millis) { getContext().enforceCallingOrSelfPermission( "android.permission.SET_TIME", "setTime"); return setTimeImpl(millis); } boolean setTimeImpl(long millis) { if (mNativeData == 0) { Slog.w(TAG, "Not setting time since no alarm driver is available."); return false; } synchronized (mLock) { return setKernelTime(mNativeData, millis) == 0; } } private native int setKernelTime(long nativeData, long millis);
@frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
{
AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
struct timeval tv;
...
ret = impl->setTime(&tv);
return ret;
}
打开dev/rtc节点,然后通过ioctl RTC_SET_TIME
int AlarmImpl::setTime(struct timeval *tv) { struct rtc_time rtc; struct tm tm, *gmtime_res; int fd; int res; res = settimeofday(tv, NULL); ... android::String8 rtc_dev = String8::format("/dev/rtc%d", rtc_id); fd = open(rtc_dev.string(), O_RDWR); gmtime_res = gmtime_r(&tv->tv_sec, &tm); if (!gmtime_res) { ALOGV("gmtime_r() failed: %s\n", strerror(errno)); res = -1; goto done; } memset(&rtc, 0, sizeof(rtc)); rtc.tm_sec = tm.tm_sec; rtc.tm_min = tm.tm_min; rtc.tm_hour = tm.tm_hour; rtc.tm_mday = tm.tm_mday; rtc.tm_mon = tm.tm_mon; rtc.tm_year = tm.tm_year; rtc.tm_wday = tm.tm_wday; rtc.tm_yday = tm.tm_yday; rtc.tm_isdst = tm.tm_isdst; res = ioctl(fd, RTC_SET_TIME, &rtc); if (res < 0) ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno)); done: close(fd); return res; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。