AndroidP 本地时间/时区自动更新 – NITZ

半城伤御伤魂 提交于 2020-02-26 14:57:58
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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!