Android中的网络时间同步

摘要:
在Android的系统设置中,有自动同步网络时间的选项。因为BronchoA1移植到froyo版本之后,我们发现时间同步选项无效了。研究的结果让我感到惊讶,Android的网络时间同步居然与SNTP协议无关,甚至与TCP/IP协议也毫无关系。=0){LOGE;}else{RIL_onUnsolicitedResponse;}}这里是处理模组主动上报的消息,如果是时间和时区消息,则调用RIL_onUnsolicitedResponse。intmonth=Integer.parseInt-1;c.set;intdate=Integer.parseInt;c.set;inthour=Integer.parseInt;c.set;intminute=Integer.parseInt;c.set;如果在系统设置中,用户选择了自动同步网络时间,才会去设置系统时间。

在 Android的系统设置中,有自动同步网络时间的选项。因为Broncho A1移植到froyo版本之后,我们发现时间同步选项无效了。所以我花了一点时间去研究 Android的网络时间同步的流程。研究的结果让我感到惊讶,Android的网络时间同步居然与SNTP协议无关,甚至与TCP/IP协议也毫无关系。

从设置的应用程序中可以了解到,自动同步网络时间的选项只是修改了Settings.System.AUTO_TIME这个设置:

private void setAutoState(boolean isEnabled, boolean autotimeStatus) {
       if (isEnabled == false) {
           mAutoPref.setChecked(autotimeStatus);
           mAutoPref.setEnabled(isEnabled);
       }
       else {
           Settings.System.putInt(getContentResolver(),
              Settings.System.AUTO_TIME, autotimeStatus ? 1 : 0);
       }
       mTimePref.setEnabled(!autotimeStatus);
       mDatePref.setEnabled(!autotimeStatus);
       mTimeZone.setEnabled(!autotimeStatus);
    }

谁会用这个设置呢?然后从代码中查找Settings.System.AUTO_TIME,主要有下面两处:

telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java

GSM和CDMA的实现应该是类似的,这里只是看看GSM: 1. 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。

2.	RIL_onUnsolicitedResponse会把消息发送给RIL的客户端。
ret = sendResponse(p, client_id);
时间和时区信息的格式在RIL_UNSOL_NITZ_TIME_RECEIVED消息的定义处有说明: "data" is const char * pointing to NITZ time string in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt" 3. RIL客户端处理RIL_UNSOL_NITZ_TIME_RECEIVED消息(telephony/java/com/android/internal/telephony/RIL.java: processUnsolicited)
            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;
                }
是GsmServiceStateTracker向RIL注册的,所以事件会由GsmServiceStateTracker来处理。 4. GsmServiceStateTracker 处理EVENT_NITZ_TIME事件:
            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;
这里nitzString是时间字符串,由setTimeFromNITZString负责解析。
private void setTimeFromNITZString (String nitz, long nitzReceiveTime) {
            String[] nitzSubs = nitz.split("[/:,+-]");

            int year = 2000 + Integer.parseInt(nitzSubs[0]);
            c.set(Calendar.YEAR, year);

            // month is 0 based!
            int month = Integer.parseInt(nitzSubs[1]) - 1;
            c.set(Calendar.MONTH, month);

            int date = Integer.parseInt(nitzSubs[2]);
            c.set(Calendar.DATE, date);

            int hour = Integer.parseInt(nitzSubs[3]);
            c.set(Calendar.HOUR, hour);

            int minute = Integer.parseInt(nitzSubs[4]);
            c.set(Calendar.MINUTE, minute);
如果在系统设置中,用户选择了自动同步网络时间,才会去设置系统时间。
           if (getAutoTime()) {
               setAndBroadcastNetworkSetTimeZone(zone.getID());
           }
           if (getAutoTime()) {
setAndBroadcastNetworkSetTime(c.getTimeInMillis());
           }
关于NITZ在WIKI上有说明: NITZ, or Network Identity and Time Zone[1], is a mechanism for provisioning local time and date, as well as network provider identity information to mobile devices via a wireless network[2]. NITZ has been part of the official GSM standard since phase 2+ release 96[3]. NITZ is often used to automatically update the system clock of mobile phones. 由于NITZ的实现是可选的,如果运营商不支持它,Android手机就无法使用此功能了。此时用最好用SNTP来代替,否则用户会感到迷惑。但Android目前好像并没有这样做,我只找到两处地方调用SntpClient,但它们都没有去设置系统时间。

免责声明:文章转载自《Android中的网络时间同步》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇linux下性能测试工具netperf使用spark基础知识(1)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

win10家庭版VMware,禁用Device/Credential Guard不兼容问题

环境vmware15pro,Windows 10家庭版。...

OpenWrt上搭建纯L2TP服务器[ZT]

转移自:http://www.openwrt.pro/post-389.html纯L2TP(L2TP+ppp,无IPSec)首先安装xl2tpd软件包opkgupdateopkginstallxl2tpd edit/etc/xl2tpd/xl2tpd。conf,并配置l2tp服务器[global]port=1701authfile=/etc/xl2tpd/x...

.gitignore模板

Github/gitgnore·Github列出了一些有用的。gitnore模板。例如,这是针对visual studio的。将“FallbackLocation”留空,这样VS将生成sdf到临时文件夹。...

压倒程序员的最后一个面试题,iOS性能优化的面试题

以及如何进行性能优化?关于instruments网上有很多资料,作为一个合格iOS开发者,熟悉这个工具还是很有必要的。一个tableview维持一个队列的数据可重用的UITableViewCell对象。这一过程即为Blending。在运行中缩放图片是很耗费资源的,特别是UIImageView嵌套在UIScrollView中的情况下。...

EwoMail 开源邮件服务器安装教程

本教程示例中使用的主要域名是ewomail.cn。设置主机名EwoMail将在安装后默认使用带有域名前缀mail的主机名。例如,mail.ewomail。cn将系统主机名更改为mail.ewomail.cn。查看当前主机名hostname-f修改主机名,修改文件/etc/sysconfig/network修改文件/etc/hosts,添加mail.ewoma...

MySQL 字段类型占用空间

MySQL支持多种列类型:数值类型、日期/时间类型和字符串(字符)类型。)1或2个字节,取决于枚举值的个数SET(‘value1’,’value2’,…)1、2、3、4或者8个字节,取决于set成员的数目上表的M只是为了说明占用空间大小,在实际创建表中char、varchar,20指的是字符而不是字节;那么字符和字节的转换要看字符集,utf-8下,1字符=3...