对时概述

Android的自动对时有好几种,基本的是通过ntp网络服务器对时和通过手机sim卡运营商网络对时,国内如果是电信cdma手机的话,按照运营商需求是强制通过第二种方式对时的,手机设置中不可选择取消自动对时。不过目前手机基本都是全网通了,所以这个限制好像取消了。mtk的还有通过gps对时的选项。

ntp介绍见百度百科:

NTP服务器【Network Time Protocol(NTP)】是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。时间按NTP服务器的等级传播。按照离外部UTC源的远近把所有服务器归入不同的Stratum(层)中。

ntp对时服务器可见http://www.ntp.org.cn/,Android源码默认服务器不是中国区的,android是通过SettingProvider设置对时服务器值的,设置中的大多数值其实都是SettingsProvider数据库某个值。

Android系统服务器的值是在NtpTrustedTime类中初始化的。

frameworks/base/core/java/android/util/NtpTrustedTime.java

   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;    }
可以修改Settings.Global.NTP_SERVER数据库值来设置ntp服务器地址。之前有过自动对时无效的问题,后来修改ntp服务器地址为中国区的就没有再出现过这个问题了。注意通过网络对时是需要连接网络的,数据连接或者wifi都是可以的,不联网肯定没用啊...


网络服务器对时流程

android系统在设置中可以选择自动对时,自动对时设置界面代码是DateTimeSettings,启用自动对时的起点就是控件的点击事件

packages/apps/Settings/src/com/android/settings/DateTimeSettings.java

                Settings.Global.putInt(getContentResolver(),                        Settings.Global.AUTO_TIME, 1);

控件点击事件中写入了Settings.Global.AUTO_TIME值,使用自动同步的时候值为1


对时服务创建于SystemServer的run()函数,SystemServer的启动流程网上有不少分析了,不赘述

/frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {    ...    startOtherServices();    ...}
调用startOtherServices

private void startOtherServices() {    ...    networkTimeUpdater = new NetworkTimeUpdateService(context);    ...    if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();    ...}

创建了NetworkTimeUpdateService对象并调用了systemRunning

public void systemRunning() {    ...    mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);    mSettingsObserver.observe(mContext);    ...}
创建了一个数据库监控Observer监控Settings.Global.AUTO_TIME值的变化,值有变化就发送到内部的handler类对象中进行处理,处理函数是:

private void onPollNetworkTime(int event)
该方法稍长,不过基本逻辑就是先获取ntp时间,然后设置时间。

该方法最终调用SystemClock类中方法设置系统时间

SystemClock.setCurrentTimeMillis(ntp);

sim卡网络对时

手机不用通过数据网络照样可以对时的,例如电信手机开机后应该可以看到系统会发送自动对时的notification。

以Cdma网络为例,代码在CdmaServiceStateTracker.java,该类中有两条路径设置时间,路径1同样是监听Settings.Global.AUTO_TIME值

   private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {        @Override        public void onChange(boolean selfChange) {            if (DBG) log("Auto time state changed");            revertToNitzTime();        }    };
监听到值有变化的时候调用revertToNitzTime

private void revertToNitzTime() {            ...            setAndBroadcastNetworkSetTime(mSavedTime                    + (SystemClock.elapsedRealtime() - mSavedAtTime));            ...    }
revertToNitzTime调用setAndBroadcastNetworkSetTime

 private void setAndBroadcastNetworkSetTime(long time) {        if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms");        SystemClock.setCurrentTimeMillis(time);        Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);        intent.putExtra("time", time);        mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);    }
setAndBroadcastNetworkSetTime设置时间并发送了一个广播。路径1的流程到此完毕


路径2是ril上报时间,从而导致更新。在CdmaServiceStateTracker构造函数中

     mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null);
向ril注册了监听时间,ril有对时消息上报的时候会通知CdmaServiceStateTracker,telephony framework中的xxTracker基本都是继承Handler类的,目的就是为了方便发送和接收消息

        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);
收到EVENT_NITZ_TIME消息后调用setTimeFromNITZString:

private void setTimeFromNITZString (String nitz, long nitzReceiveTime){           ...           Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));           ...           if (getAutoTime()) {               ...               setAndBroadcastNetworkSetTime(c.getTimeInMillis());               ...           }           ...}
调用路径1末尾同样的方法设置时间。gsm的代码和cdma类似。不过依据我的个人经验,国内好像只有电信才有这个功能。

更多相关文章

  1. 万字长文带你了解最常用的开源 Squid 代理服务器
  2. Nginx系列教程(一)| 手把手教你在Linux环境下搭建Nginx服务
  3. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  4. Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
  5. Android(安卓)端实现mqtt消息接收
  6. Android编程之客户端通过socket与服务器通信的方法
  7. Android(安卓)HttpClient Session保持
  8. 2020-12-24
  9. 解决 android 4.2 连接 leap wifi 网络

随机推荐

  1. Android的移动存储解决方案之SharedPrefe
  2. 在Android中使用Html5
  3. Android中广播注册与接收流程
  4. Android(安卓)framework 系统服务的启动
  5. Android(安卓)EditText属性总结
  6. android平台解析epub格式的书籍信息
  7. 【Android】_UI设计_登录页面(记住密码)
  8. IPC(Inner Process Comunication)机制基本
  9. Android(安卓)Sudio 如何获取开发版SHA1
  10. Android(安卓)Message机制及其应用