Android 時間 更新與同步


欠賬太多,做了好多年的驅動,做得多記錄的少,一直想找機會,把驅動部分的內容整理下,形成文字;現在倒好,工作內容網framework走了,本打算做一點記錄一點,可是現在回想一下,整個camera framework自己改動了一遍,花了好些時間,確沒留下點莫子記錄;突然又跑到wifi、wpa這邊解決問題來了,剛解決完,還有好些沒弄明白的地方,正想研究一下,寫個文檔;這倒好又切到用gps 時間來更新系統時間這個需求上面來了,這個比較簡單些,就寫了點東西,分享與記錄一下;要不馬上被催着去調ril了,又沒心情寫了。

一、概述

Android的時間更新分成2種,一種是走運營商協議的NITZ,另一種是走網絡時鍾的SNTP;

 

個人認為如果有GPS的話,可以使用GPS的時鍾信息對系統時間進行更新,當然這部分內容可能需要自己去實現,先初略的看了一下,大概需要用到一下一些方法:

SystemClock.setCurrentTimeMillis(time); // 設置系統時間

Android.location.location.getTime();//獲取Gps時間,可能會有一兩分鍾的延時,在收到星以后。

 

二、問題

目前所用fsl imx51 Android2.3系統時間無法更新,用的是華為的cdma模塊。需要查明並修正,已經看是否能夠將第三種系統時間更新方法加入其中。

 

三、分析

基於Android2.3做以下分析

  • 當選擇設置菜單----->日期和時間------->自動,系統如下處理
  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了時間、日期、區域三個選擇項

 

  1. 后台處理:見CdmaServiceStateTracker.java

 cr.registerContentObserver(   //M.jr.xu when System.AUTO_TIME changed,then callback mAutoTimeOberver

                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網絡時間同步的話,可以再此函數里面增加相應的代碼,這方面網絡資料很多,詳見http://blog.sina.com.cn/s/blog_3e4774e30100tq2p.html

  • 系統又是如何自動進行時間同步的呢,當選擇自動設置以后

        系統時間同步,是靠ril層(見Reference-ril.c)發消息RIL_UNSOL_NITZ_TIME_RECEIVED來進行驅動的,這里就不詳細介紹此消息是如何發生的了,其主要由gsm/cdma模塊來進行驅動的,想更深入的了了解,需要對RIL、MUX、AT、運營商協議 以及代碼進行綜合的分析,在這里就不做詳細介紹,如果以后有機會再次深入的介入這一部分內容,將會另外做詳細的分析。

        1)當Ril.java 接收到RIL_UNSOL_NITZ_TIME_RECEIVED消息,會將消息轉發為EVENT_NITZ_TIME,同時在CdmaServiceStateTracker中handleMessage會接收到EVENT_NITZ_TIME消息了,並進行相關處理,詳細代碼見下:

          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更新時間差不多,感興趣的自己去研究一下。

 

四、總結

     Android系統時間同步,從代碼上分析不是很復雜,但是目前Android2.3的同步只用到的Gsm/Cdma NITZ的同步機制,而未加入SNTP同步機制,更別說gsp時間同步機制了,依照其實現原理,實現他們應該都不是很難。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM