Android 时间同步与更新

概述

Android的时间更新分成2种,一种是走运营商协议的NITZ,另一种是走网络时钟的SNTP。


分析

当我们进行操作:设置菜单----->日期和时间------->自动

1.UI显示 :见DateTimeSetting.java

 public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {

        …………..

        } else if (key.equals(KEY_AUTO_TIME)) {

            boolean autoEnabled = preferences.getBoolean(key, true);

            Settings.System.putInt(getContentResolver(),

                    Settings.System.AUTO_TIME,

                    autoEnabled ? 1 : 0);

            mTimePref.setEnabled(!autoEnabled);

            mDatePref.setEnabled(!autoEnabled);

            mTimeZone.setEnabled(!autoEnabled);

        }

    }

注释:这是一个监听,当点击自动checkbox后,会触发此监听事件,其中设置了Settings.System.AUTO_TIME的值,disable/enable了时间、日期、区域三个选择项

2.后台处理:见CdmaServiceStateTracker.java/GsmServiceStateTracker.java

cr.registerContentObserver(  

                Settings.System.getUriFor(Settings.System.AUTO_TIME), true,

                mAutoTimeObserver);

        setSignalStrengthDefaultValues();
注释:设置Settings.System.AUTO_TIME的监听
private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {

        @Override

        public void onChange(boolean selfChange) {

            Log.i("CdmaServiceStateTracker", "Auto time state called ...");

            revertToNitz();

        }
注释:Settings.System.AUTO_TIME的监听处理函数
 private void revertToNitz() {

        if (Settings.System.getInt(cr, Settings.System.AUTO_TIME, 0) == 0) {

            return;

        }

        Log.d(LOG_TAG, "Reverting to NITZ: tz='" + mSavedTimeZone

                + "' mSavedTime=" + mSavedTime

                + " mSavedAtTime=" + mSavedAtTime);

        if (mSavedTimeZone != null && mSavedTime != 0 && mSavedAtTime != 0) {

            setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);

            setAndBroadcastNetworkSetTime(mSavedTime

                    + (SystemClock.elapsedRealtime() - mSavedAtTime));

        }

    }
注释:Settings.System.AUTO_TIME真正的处理函数,其取得从gsm/cdma取得的时间参数,对系统时间已经区域进行更新,并发送广播消息。  如果想用到SNTP网络时间同步的话,可以再此函数里面增加相应的代码


系统分析

系统时间同步,是靠ril层(见Reference-ril.c)发消息RIL_UNSOL_NITZ_TIME_RECEIVED来进行驱动的

reference-ril/reference-ril.c处理主动上报消息

if (strStartsWith(s, "%CTZV:")) {  
        /* TI specific -- NITZ time */  
        char *response;  
  
        line = p = strdup(s);  
        at_tok_start(&p);  
  
        err = at_tok_nextstr(&p, &response);  
  
        free(line);  
        if (err != 0) {  
            LOGE("invalid NITZ line %s\n", s);  
        } else {  
            RIL_onUnsolicitedResponse (  
                RIL_UNSOL_NITZ_TIME_RECEIVED,  
                response, strlen(response));  
        }  
} 
这里是处理模组主动上报的消息,如果是时间和时区消息,则调用RIL_onUnsolicitedResponse。

RIL客户端处理RIL_UNSOL_NITZ_TIME_RECEIVED消息(telephony/java/com/android/internal/telephony/RIL.java)

    case RIL_UNSOL_NITZ_TIME_RECEIVED:  
                    if (RILJ_LOGD) unsljLogRet(response, ret);  
      
                    // has bonus long containing milliseconds since boot that the NITZ  
                    // time was received  
                    long nitzReceiveTime = p.readLong();  
      
                    Object[] result = new Object[2];  
      
                    result[0] = ret;  
                    result[1] = Long.valueOf(nitzReceiveTime);  
      
                    if (mNITZTimeRegistrant != null) {  
      
                        mNITZTimeRegistrant  
                            .notifyRegistrant(new AsyncResult (null, result, null));  
                    } else {  
                        // in case NITZ time registrant isnt registered yet  
                        mLastNITZTimeInfo = result;  
                    }  

当Ril.java 接收到RIL_UNSOL_NITZ_TIME_RECEIVED消息,会将消息转发为EVENT_NITZ_TIME,

是GsmServiceStateTracker向RIL注册的,所以事件会由GsmServiceStateTracker来处理。

  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;

           }
注释:EVENT_NITZ_TIME消息处理,获取gsm/cdma发送过来的时间参数,并且调用setTimeFromNITZString进行处理
private

    void setTimeFromNITZString (String nitz, long nitzReceiveTime)

    {

                     ……   

                if (getAutoTime()) {  //M.jr.xu for auto up sys time

                    /**

                     * Update system time automatically

                     */

                    long gained = c.getTimeInMillis() - System.currentTimeMillis();

                    long timeSinceLastUpdate = SystemClock.elapsedRealtime() - mSavedAtTime;

                    int nitzUpdateSpacing = Settings.Secure.getInt(cr,

                            Settings.Secure.NITZ_UPDATE_SPACING, mNitzUpdateSpacing);

                    int nitzUpdateDiff = Settings.Secure.getInt(cr,

                            Settings.Secure.NITZ_UPDATE_DIFF, mNitzUpdateDiff);

 

                    if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing)

                            || (Math.abs(gained) > nitzUpdateDiff)) {

                        Log.i(LOG_TAG, "NITZ: Auto updating time of day to " + c.getTime()

                                + " NITZ receive delay=" + millisSinceNitzReceived

                                + "ms gained=" + gained + "ms from " + nitz);

 

                        setAndBroadcastNetworkSetTime(c.getTimeInMillis());

                    } else {

                        Log.i(LOG_TAG, "NITZ: ignore, a previous update was "

                                + timeSinceLastUpdate + "ms ago and gained=" + gained + "ms");

                        return;

                    }

                }
注释:setTimeFromNITZString时间更新处理函数,当自动选择框为true,当获取的时间值和系统的时间值大于一定时,调用setAndBroadcastNetworkSetTime(c.getTimeInMillis())对系统时间进行更新,并且发送广播消息TelephonyIntents.ACTION_NETWORK_SET_TIME,在2.3当中此广播消息不会被接收到,也就是说没有说明作用,但是在4.0版本里面,此广播消息被NetWorkTimeupdataService接收到,并且进行了相关的时间同步处理(网络时钟SNTP),这一部分在这里就不做介绍了,原理和NITZ更新时间差不多,感兴趣的自己去研究一下。

添加SNTP

添加SNTP同步功能需要修改的代码包括:

frameworks/base/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java

frameworks/base/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java

添加如下内容:

      importandroid.net.SntpClient;

private void revertToNitz() {
        if (Settings.System.getInt(phone.getContext().getContentResolver(),
                Settings.System.AUTO_TIME, 0) == 0) {
            return;
        }
        Log.d(LOG_TAG, "Reverting to NITZ: tz='" + mSavedTimeZone
                + "' mSavedTime=" + mSavedTime
                + " mSavedAtTime=" + mSavedAtTime);
        if (mSavedTimeZone != null && mSavedTime != 0 && mSavedAtTime != 0) {
            setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
            setAndBroadcastNetworkSetTime(mSavedTime
                    + (SystemClock.elapsedRealtime() - mSavedAtTime));
        }
    }
修改为
private void revertToNitz() {
        if (Settings.System.getInt(phone.getContext().getContentResolver(),
                Settings.System.AUTO_TIME, 0) == 0) {
            return;
        }
        Log.d(LOG_TAG, "Reverting to NITZ: tz='" + mSavedTimeZone
                + "' mSavedTime=" + mSavedTime
                + " mSavedAtTime=" + mSavedAtTime);
        if (mSavedTimeZone != null && mSavedTime != 0 && mSavedAtTime != 0) {
            setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
            setAndBroadcastNetworkSetTime(mSavedTime
                    + (SystemClock.elapsedRealtime() - mSavedAtTime));
            return;
        }
        int tryCount = 5;
        SntpClient client = new SntpClient();

        Log.i(LOG_TAG, "revertToNitz new sntpclient");

        for(int i = 0; i < tryCount; i++){
            if(client.requestTime("north-america.pool.ntp.org", 10000)) {
                long cachedNtp = client.getNtpTime();
                long cachedNtpTimestamp = SystemClock.elapsedRealtime();

                Log.i(LOG_TAG, "Sntp NtpTime = " + cachedNtp);

                setAndBroadcastNetworkSetTime(cachedNtp
                   + (SystemClock.elapsedRealtime() - client.getNtpTimeReference()));
                return;
            }
        }
    }
当不支持NITZ获取时间同步时就使用SNTP方式获取时间进行同步。不过使用SNTP方式进行时间同步时不能同步时区,需要自己先去掉自动同步并设置时区后再设置自动同步,这样才能进行网络时间的同步更新。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android时间同步是指Android设备与网络时间服务器步时间的过程。Android系统提供了自动时间同步功能,可以通过与网络时间服务器进行通信,获取当前的准确时间,并将其应用到设备上。 Android设备在连接到互联网时,会自动与预配置的网络时间服务器进行通信,获取当前的时间信息。这是通过使用网络协议NTP(Network Time Protocol)来实现的。NTP是一种用于同步计算机时钟的协议,它可以通过网络获取准确的时间信息。 Android系统会周期性地与网络时间服务器进行通信,以确保设备上的时间与网络时间保持同步。这样可以确保设备上的时间准确无误,对于一些需要依赖时间的应用程序和服务非常重要,比如日历、闹钟、定时任务等。 在Android系统中,时间同步可以通过以下方式进行设置和管理: 1. 自动时间:在系统设置中,可以选择开启自动时间选项,让系统自动与网络时间服务器同步时间。 2. 手动时间:也可以手动设置设备时间,关闭自动时间选项后,可以手动调整设备时间。 3. 时间服务器:可以选择不同的网络时间服务器进行同步,系统默认使用Google提供的网络时间服务器。 总结一下,Android时间同步是通过与网络时间服务器通信,获取准确的时间信息,并将其应用到设备上,以确保设备上的时间与网络时间保持同步。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值