Android P系統時間更新分析

Android P系統時間更新分析
文中的代碼都是Android 原生代碼
在這裏插入圖片描述

代碼位置

frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/NetworkTimeUpdateService.java
frameworks/base/services/core/java/com/android/server/AlarmManagerService.java
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
frameworks/base/core/java/android/os/SystemClock.java
frameworks/base/core/java/android/app/IAlarmManager.aidl
frameworks/base/core/jni/android_os_SystemClock.cpp
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

代碼分析
在這裏插入圖片描述

SystemServer的啓動

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
在上面的文件中啓動systemserver, 詳情請參考下面代碼

public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
		// ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        final Runnable caller;
        try {
            // Report Zygote start time to tron unless it is a runtime restart
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            }

            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.enableDdms();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            zygoteServer.registerServerSocketFromEnv(socketName);
   // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false, 0);

            Zygote.nativeSecurityInit();

            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();

            ZygoteHooks.stopZygoteNoThreadCreation();

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }
            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

在frameworks/base/services/java/com/android/server/SystemServer.java中
調用main函數

	/**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }

順着調用關係找
在調用startOtherServices(); 創建NetworkTimeUpdateService類
frameworks/base/services/core/java/com/android/server/NetworkTimeUpdateService.java
在systemRunning()中, 註冊RIL的ACTION_NETWORK_SET_TIME以及ACTION_NETWORK_SET_TIMEZONE事件,以接受來自Telephony FW的NITZ時間更新;
監聽 ACTION_POLL事件(定時更新時間)以及手機網絡連接狀態;
發送消息同步NTP時間
監聽 Settings中“自動更新時間”選項的變化

/** Initialize the receivers and initiate the first NTP request */
   public void systemRunning() {
       registerForTelephonyIntents();
       registerForAlarms();

       HandlerThread thread = new HandlerThread(TAG);
       thread.start();
       mHandler = new MyHandler(thread.getLooper());
       mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
       mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);

       mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
       mSettingsObserver.observe(mContext);
   }

   private void registerForTelephonyIntents() {
       IntentFilter intentFilter = new IntentFilter();
       intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
       mContext.registerReceiver(mNitzReceiver, intentFilter);
   }

   private void registerForAlarms() {
       mContext.registerReceiver(
           new BroadcastReceiver() {
               @Override
               public void onReceive(Context context, Intent intent) {
                   mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
               }
           }, new IntentFilter(ACTION_POLL));
   }

同步NTP時間
如果沒有收到NITZ時間的更新並且NTP超過一定間隔沒有更新時間,服務會主動去同步NTP時間:
開啓事件循環,當EVENT_AUTO_TIME_CHANGED,EVENT_POLL_NETWORK_TIME、EVENT_NETWORK_CHANGED中一個發生時,onPollNetworkTime函數,最終調到onPollNetworkTimeUnderWakeLock(int event)函數

public void handleMessage(Message msg) {
            switch (msg.what) {
                case EVENT_AUTO_TIME_CHANGED:
                case EVENT_POLL_NETWORK_TIME:
                case EVENT_NETWORK_CHANGED:
                    onPollNetworkTime(msg.what);
                    break;
            }
        }

NtpTrustedTime調用public boolean forceRefresh(Network network)函數
New SntpClient()這個請求,通過ConnectivityManager 發出去。
通過這個函數更新時間

/**
     * Consider updating system clock based on current NTP fix, if requested by
     * user, significant enough delta, and we don't have a recent NITZ.
     */
    private void updateSystemClock(int event) {
        final boolean forceUpdate = (event == EVENT_AUTO_TIME_CHANGED);
        if (!forceUpdate) {
            if (getNitzAge() < mPollingIntervalMs) {
                if (DBG) Log.d(TAG, "Ignoring NTP update due to recent NITZ");
                return;
            }

            final long skew = Math.abs(mTime.currentTimeMillis() - System.currentTimeMillis());
            if (skew < mTimeErrorThresholdMs) {
                if (DBG) Log.d(TAG, "Ignoring NTP update due to low skew");
                return;
            }
        }

        SystemClock.setCurrentTimeMillis(mTime.currentTimeMillis());
    }

framework/base/core/java/android/os/SystemClock.java
SystemClock.setCurrentTimeMillis(mTime.currentTimeMillis());//更新系統時間
從NtpTrustedTime類中,public long currentTimeMillis()函數獲取當前時間毫秒。
,設置到SystemClock中。
SystemClock類setCurrentTimeMillis實現:

public static boolean setCurrentTimeMillis(long millis) {
        final IAlarmManager mgr = IAlarmManager.Stub
                .asInterface(ServiceManager.getService(Context.ALARM_SERVICE));
        if (mgr == null) {
            return false;
        }

        try {
            return mgr.setTime(millis);
        } catch (RemoteException e) {
            Slog.e(TAG, "Unable to set RTC", e);
        } catch (SecurityException e) {
            Slog.e(TAG, "Unable to set RTC", e);
        }

        return false;
}

frameworks/base/core/java/android/app/IAlarmManager.aidl

/* //device/java/android/android/app/IAlarmManager.aidl
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.app;

import android.app.AlarmManager;
import android.app.IAlarmListener;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.WorkSource;

/**
 * System private API for talking with the alarm manager service.
 *
 * {@hide}
 */
interface IAlarmManager {
        /** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
    void set(String callingPackage, int type, long triggerAtTime, long windowLength,
            long interval, int flags, in PendingIntent operation, in IAlarmListener listener,
            String listenerTag, in WorkSource workSource, in AlarmManager.AlarmClockInfo alarmClock);
    boolean setTime(long millis);
    void setTimeZone(String zone);
    void remove(in PendingIntent operation, in IAlarmListener listener);
    long getNextWakeFromIdleTime();
    AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
    long currentNetworkTimeMillis();
}

framework/base/services/core/java/com/android/server/AlarmManagerService.java

final IAlarmManager mgr = IAlarmManager.Stub
                .asInterface(ServiceManager.getService(Context.ALARM_SERVICE));
public boolean setTime(long millis) {
            getContext().enforceCallingOrSelfPermission(
                    "android.permission.SET_TIME",
                    "setTime");

            return setTimeImpl(millis);
        }
boolean setTimeImpl(long millis) {
        if (mNativeData == 0) {
            Slog.w(TAG, "Not setting time since no alarm driver is available.");
            return false;
        }

        synchronized (mLock) {
            return setKernelTime(mNativeData, millis) == 0;
        }
    }

getSystemService()返回的不再是IAlarmManager接口,而是AlarmManager對象。

Framework/base/services/core/jni/com_android_server_AlarmManagerService.cpp

static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
{
    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
    struct timeval tv;
    int ret;

    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
        return -1;
    }

    tv.tv_sec = (time_t) (millis / 1000LL);
    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);

    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);

    ret = impl->setTime(&tv);

    if(ret < 0) {
        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
        ret = -1;
    }
    return ret;
}

AlarmImpl::setTime函數實現

int AlarmImpl::setTime(struct timeval *tv)
{
    struct rtc_time rtc;
    struct tm tm, *gmtime_res;
    int fd;
    int res;

    res = settimeofday(tv, NULL);
    if (res < 0) {
        ALOGV("settimeofday() failed: %s\n", strerror(errno));
        return -1;
    }

    if (rtc_id < 0) {
        ALOGV("Not setting RTC because wall clock RTC was not found");
        errno = ENODEV;
        return -1;
    }

    android::String8 rtc_dev = String8::format("/dev/rtc%d", rtc_id);
    fd = open(rtc_dev.string(), O_RDWR);
    if (fd < 0) {
        ALOGV("Unable to open %s: %s\n", rtc_dev.string(), strerror(errno));
        return res;
    }

    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
    if (!gmtime_res) {
        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
        res = -1;
        goto done;
    }

    memset(&rtc, 0, sizeof(rtc));
    rtc.tm_sec = tm.tm_sec;
    rtc.tm_min = tm.tm_min;
    rtc.tm_hour = tm.tm_hour;
    rtc.tm_mday = tm.tm_mday;
    rtc.tm_mon = tm.tm_mon;
    rtc.tm_year = tm.tm_year;
    rtc.tm_wday = tm.tm_wday;
    rtc.tm_yday = tm.tm_yday;
    rtc.tm_isdst = tm.tm_isdst;
    res = ioctl(fd, RTC_SET_TIME, &rtc);
    if (res < 0)
        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
done:
    close(fd);
    return res;
}

最終將時間寫到/dev/rtc*文件。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章