NITZ - Network Identity andTime Zone,网络标识和时区,是一种用于自动配置本地时间和日期的机制,同时也通过无线网向移动设备提供运营商信息。NITZ经常被用来自动更新移动电话的系统时钟,Android原有的更新机制就是采用NITZ方式,这是一种运营商的可选服务。其基本原理简单的来说,就是UI根据 Modem主动上报的时间信息,更新终端系统的时间及时区。
初始化:构造函数
ServiceStateTracker() {
…
mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null);
…
}
接收到EVENT_NITZ_TIME后,调用 setTimeFromNITZString去设置时间和时区
public void handleMessage(Message msg) { ... case EVENT_NITZ_TIME:
ar = (AsyncResult) msg.obj;
String nitzString = (String)((Object[])ar.result)[0]; long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue();
setTimeFromNITZString(nitzString, nitzReceiveTime); break; ... }
setTimeFromNITZString 负责解析传过来字符串(nitzString)并进行时间和时区的设置
private
void
setTimeFromNITZString
(String nitzString,
long
nitzReceiveTime) {
long
start = SystemClock.elapsedRealtime();
if
(DBG) {
Rlog.d(LOG_TAG, "NITZ: " + nitzString + "," + nitzReceiveTime + " start="+ start + " delay="+ (start - nitzReceiveTime));
} NitzData newNitzData = NitzData.parse(nitzString);
if
(newNitzData !=
null
) {
try
{
TimeStampedValue<NitzData> nitzSignal = new TimeStampedValue<>(newNitzData, nitzReceiveTime);
mNitzState.handleNitzReceived(nitzSignal); }
finally
{
} }
NitzStateMachine.java解析nitz时间
@NitzStateMachine.java /** * Handle a new NITZ signal being received. */ public void handleNitzReceived(TimeStampedValue<NitzData> nitzSignal) { handleTimeZoneFromNitz(nitzSignal); handleTimeFromNitz(nitzSignal); } private void handleTimeZoneFromNitz(TimeStampedValue<NitzData> nitzSignal) {String zoneId; if (newNitzData.getEmulatorHostTimeZone() != null) { zoneId = newNitzData.getEmulatorHostTimeZone().getID(); } else { if (!mGotCountryCode) { zoneId = null; } else if (!TextUtils.isEmpty(iso)) { OffsetResult lookupResult = mTimeZoneLookupHelper.lookupByNitzCountry(newNitzData, iso); zoneId = lookupResult != null ? lookupResult.zoneId : null; } else { // We don't have a valid iso country code. This is // most likely because we're on a test network that's // using a bogus MCC (eg, "001"), so get a TimeZone // based only on the NITZ parameters. OffsetResult lookupResult = mTimeZoneLookupHelper.lookupByNitz(newNitzData); if (DBG) { Rlog.d(LOG_TAG, "handleTimeZoneFromNitz: guessZoneIdByNitz returned" + " lookupResult=" + lookupResult); } zoneId = lookupResult != null ? lookupResult.zoneId : null; } } ... if (zoneId != null) { if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) { setAndBroadcastNetworkSetTimeZone(zoneId); } mNitzTimeZoneDetectionSuccessful = true; mSavedTimeZoneId = zoneId; } ... }
private void handleTimeFromNitz(TimeStampedValue<NitzData> nitzSignal) { ... if (mTimeServiceHelper.isTimeDetectionEnabled()) { ... setAndBroadcastNetworkSetTime(logMsg, adjustedCurrentTimeMillis); } ... }
/**
* Returns true if automatic time detection is enabled in settings.
*/
public boolean isTimeDetectionEnabled() {
try {
return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME) > 0;
} catch (Settings.SettingNotFoundException snfe) {
return true;
}
}
/**
* Returns true if automatic time zone detection is enabled in settings.
*/
public boolean isTimeZoneDetectionEnabled() {
try {
return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0;
} catch (Settings.SettingNotFoundException snfe) {
return true;
}
}
从代码中可以看出只有在数据库对自动同步网络时间/时区为勾选状态时,才会调用setAndBroadcastNetworkSetTime和 setAndBroadcastNetworkSetTimeZone设置当前NITZ解析的时间及时区,并发送广播进行最终的系统时间/时区维护。这里相关数据库的勾选状态获取方法如下,主要判断Settings.Global.AUTO_TIME 及Settings.Global.AUTO_TIME_ZONE 存储值
另外。RIL中mLastNITZTimeInfo值的设定在RadioIndication.java中
public void nitzTimeReceived(int indicationType, String nitzTime, long receivedTime) { mRil.processIndication(indicationType);
if (RIL.RILJ_LOGD) mRil.unsljLogRet(RIL_UNSOL_NITZ_TIME_RECEIVED, nitzTime);
// todo: Clean this up with a parcelable class for better self-documentation Object[] result = new Object[2]; result[0] = nitzTime; result[1] = receivedTime;
boolean ignoreNitz = SystemProperties.getBoolean( TelephonyProperties.PROPERTY_IGNORE_NITZ, false);
if (ignoreNitz) { if (RIL.RILJ_LOGD) mRil.riljLog("ignoring UNSOL_NITZ_TIME_RECEIVED"); } else { if (mRil.mNITZTimeRegistrant != null) { mRil.mNITZTimeRegistrant.notifyRegistrant(new AsyncResult (null, result, null)); } // in case NITZ time registrant isn't registered yet, or a new registrant // registers later mRil.mLastNITZTimeInfo = result; } }
该方法是HAL层,获取nitz
|