Android T Wi-Fi 更新时间流程

首先我们要明白下概念:
NITZ(Network identifier Time Zone:网络标识和时区):用来配置本地日期和时间的机制,也通过无线网络向设备提供运营商信息。常用来更新设备的系统时钟,可校正时间和时区。需要运营商支持(如果不支持的话就需要采用SNTP更新时间了)
SNTP(Simple Network Time protocol:简单网络时间协议):用于使用Internet时间校正设备时间,只能校正时间,无法校正时区

代码位置:http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/
NetworkTimeUpdateService.java
在systemService里面初始化的 NetworkTimeUpdateService,看下初始化做了啥
在这里插入图片描述

 public NetworkTimeUpdateService(Context context) {
     mContext = context;
     mTime = NtpTrustedTime.getInstance(context);  ---> 拿到 NtpTrustedTime对象
     mAlarmManager = mContext.getSystemService(AlarmManager.class);
     mTimeDetector = mContext.getSystemService(TimeDetector.class);
     mCM = mContext.getSystemService(ConnectivityManager.class);

     Intent pollIntent = new Intent(ACTION_POLL, null);
     // Broadcast alarms sent by system are immutable
     mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, PendingIntent.FLAG_IMMUTABLE);
	// 注意这里的三个变量
	// mPollingIntervalMs 是64800000毫秒,就是18个小时
	// mPollingIntervalShorterMs 是60000毫秒,就是1分钟
     mPollingIntervalMs = mContext.getResources().getInteger(
     		com.android.internal.R.integer.config_ntpPollingInterval);
     mPollingIntervalShorterMs = mContext.getResources().getInteger(
             com.android.internal.R.integer.config_ntpPollingIntervalShorter);
     mTryAgainTimesMax = mContext.getResources().getInteger(
             com.android.internal.R.integer.config_ntpRetry);
             
     mWakeLock = context.getSystemService(PowerManager.class).newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, TAG);
 }
 
 <!-- Normal polling frequency in milliseconds -->
 <integer name="config_ntpPollingInterval">64800000</integer>
 <!-- Try-again polling interval in milliseconds, in case the network request failed -->
 <integer name="config_ntpPollingIntervalShorter">60000</integer>
 <!-- Number of times to try again with the shorter interval, before backing off until the normal polling interval. 
 							A value < 0 indicates infinite. -->
 <integer name="config_ntpRetry">3</integer>
 <!-- Timeout to wait for NTP server response in milliseconds. -->
 <integer name="config_ntpTimeout">5000</integer>


 /** Initialize the receivers and initiate the first NTP request */
 public void systemRunning() {
     registerForAlarms();  ---> 注册广播,看下面贴的代码

     HandlerThread thread = new HandlerThread(TAG);
     thread.start();
     mHandler = new MyHandler(thread.getLooper());
     mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();   ---> 网络变化的回调,看下面贴的代码
     mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);

     mAutoTimeSettingObserver = new AutoTimeSettingObserver(mContext, mHandler,
             EVENT_AUTO_TIME_ENABLED);
     mAutoTimeSettingObserver.observe();  ---> 注册内容观察者,看下面贴的代码
 }
 
private void registerForAlarms() {
    mContext.registerReceiver(
            new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();   ---> 发送这个消息:EVENT_POLL_NETWORK_TIME
                }
            }, new IntentFilter(ACTION_POLL));  ---> com.android.server.NetworkTimeUpdateService.action.POLL 
}

private class NetworkTimeUpdateCallback extends NetworkCallback {
    @Override
    public void onAvailable(Network network) {    
        Log.d(TAG, String.format("New default network %s; checking time.", network));
        mDefaultNetwork = network;   ---> 网络可用,注意下这个参数,下面能用到
        // Running on mHandler so invoke directly.
        onPollNetworkTime(EVENT_NETWORK_CHANGED);
    }

    @Override
    public void onLost(Network network) {
        if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
    }
}

private static class AutoTimeSettingObserver extends ContentObserver {
    private final Context mContext;
    private final int mMsg;
    private final Handler mHandler;

    AutoTimeSettingObserver(Context context, Handler handler, int msg) {
        super(handler);
        mContext = context;
        mHandler = handler;
        mMsg = msg;
    }
   // 需要监视的 AUTO_TIME 
    void observe() {
        ContentResolver resolver = mContext.getContentResolver();
        //Settings中的AUTO_TIME开关打开就会触发
        resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME), false, this);
    }

    @Override
    public void onChange(boolean selfChange) {
        if (isAutomaticTimeEnabled()) {
            mHandler.obtainMessage(mMsg).sendToTarget();
        }
    }

    /**
     * Checks if the user prefers to automatically set the time.
     */
    private boolean isAutomaticTimeEnabled() {
        ContentResolver resolver = mContext.getContentResolver();
        return Settings.Global.getInt(resolver, Settings.Global.AUTO_TIME, 0) != 0;
    }
}

通过上面这段代码我们知道两点

  1. 网络发生变化时候会发 EVENT_NETWORK_CHANGED 消息
  2. 用户设置AUTO_TIME变化时会发 EVENT_AUTO_TIME_ENABLED 消息
  3. 收到广播后发送 EVENT_POLL_NETWORK_TIME 消息

而这些消息都在Handle里面处理:

/** Handler to do the network accesses on */
private class MyHandler extends Handler {
    MyHandler(Looper l) {
        super(l);
    }
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_AUTO_TIME_ENABLED: 
            case EVENT_POLL_NETWORK_TIME:  
            case EVENT_NETWORK_CHANGED: 
                onPollNetworkTime(msg.what);  ---> 这三个消息都触发这个方法
                break;
        }
    }
}

private void onPollNetworkTime(int event) {
    if (mDefaultNetwork == null) return;   ---> 上面在网络回调中onAvailable方法里给这个赋值了,如果依然是Null,则返回
    mWakeLock.acquire();
    // 也就是如果没有网络变换,mDefaultNetwork永远是null,就算其它两个消息来了,也是得return,不会走到下面
    try {
        onPollNetworkTimeUnderWakeLock(event);
    } finally {
        mWakeLock.release();
    }
}

private void onPollNetworkTimeUnderWakeLock(int event) {
    long currentElapsedRealtimeMillis = SystemClock.elapsedRealtime();
    // Force an NTP fix when outdated
    NtpTrustedTime.TimeResult cachedNtpResult = mTime.getCachedTimeResult();
    // 这里就是涉及到我们一开始讲的参数了
    // mPollingIntervalMs 是64800000毫秒,就是18个小时
	// mPollingIntervalShorterMs 是60000毫秒,就是1分钟
    // 刚开始 cachedNtpResult 是 null,所以回去强制 forceRefresh()下
    if (cachedNtpResult == null || cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis) >= mPollingIntervalMs) {
        if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
    //位置:http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/core/java/android/util/NtpTrustedTime.java#forceRefresh()
        boolean isSuccessful = mTime.forceRefresh();  ---> 这里面就是去和NTP服务器交互的地方
        if (isSuccessful) {
            mTryAgainCounter = 0;
        } else {
            String logMsg = "forceRefresh() returned false: cachedNtpResult=" + cachedNtpResult
                    + ", currentElapsedRealtimeMillis=" + currentElapsedRealtimeMillis;

            if (DBG) {
                Log.d(TAG, logMsg);
            }
            mLocalLog.log(logMsg);
        }
        // 此时再获取一次,正常来说就不是null了,ntp 服务没问题的话
        cachedNtpResult = mTime.getCachedTimeResult();
    }
/*
* cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis) 是返回的时间差
* 当前时间减去服务器返回的参考时间
*/
if (cachedNtpResult != null && cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis) < mPollingIntervalMs) {
    // Obtained fresh fix; schedule next normal update
    resetAlarm(mPollingIntervalMs - cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis));
    // 将时间设置到系统中
    makeNetworkTimeSuggestion(cachedNtpResult, "Origin: NetworkTimeUpdateService. event=" + event);
} else {
    // No fresh fix; schedule retry
    // 从这个注释我们就知道如果没有正常更新,就要尝试mTryAgainTimesMax是3
    mTryAgainCounter++;   --->0累计
    if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
        resetAlarm(mPollingIntervalShorterMs);   ---> 1分钟
    } else {
        // Try much later
        String logMsg = "mTryAgainTimesMax exceeded, cachedNtpResult=" + cachedNtpResult;
        if (DBG) {
            Log.d(TAG, logMsg);
        }
        mLocalLog.log(logMsg);
        mTryAgainCounter = 0;
        resetAlarm(mPollingIntervalMs);
    }
}

// 设置闹钟,经过 interval 时间后 发一个 mPendingPollIntent
private void resetAlarm(long interval) {
    mAlarmManager.cancel(mPendingPollIntent);
    long now = SystemClock.elapsedRealtime();
    long next = now + interval;
    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
}

从开头我们知道 mPendingPollIntent 是这个,而 ACTION_POLL = “com.android.server.NetworkTimeUpdateService.action.POLL”;
在这里插入图片描述
接收广播的地方开头代码也贴出来了,这样就会发送 EVENT_POLL_NETWORK_TIME 消息,在重复调用Handle去处理,这样又回到之前的流程了,尝试3次。
在这里插入图片描述
Ok,到此我们就把整个Wi-Fi更新时间的流程给介绍完毕,说白了就是访问NTP的服务器去获取时间,和服务器交互的代码,有兴趣的可以去看看:http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/core/java/android/util/NtpTrustedTime.java#forceRefresh()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值