Android P系统时间更新分析
文中的代码都是Android 原生代码
Android P系统时间更新分析_第1张图片

代码位置

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

类的调用框图

Android P系统时间更新分析_第2张图片

代码分析

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;}

总结:
调用res = settimeofday(tv, NULL);函数来设置系统时间
调用res = ioctl(fd, RTC_SET_TIME, &rtc);将时钟设置到RTC设备节点
最终将时间写到/dev/rtc*文件。

参考资料

  • Android系统五层架构
  • Zygote启动及其作用
  • Android 系统时间自动更新机制
  • AlarmManager深入分析
  • linux rtc驱动

更多相关文章

  1. C语言函数以及函数的使用
  2. Android 图形系统及其应用
  3. android系统自带的主题与样式(theme and style)
  4. android之4.0的系统主题style修改android:Theme.Holo.Light
  5. android 电池(三):android电池系统
  6. Android入门学习:Android 系统框架及应用程序执行过程
  7. 数据显示Android“姜饼”系统用户数增多
  8. Ice Cream Sandwich系统将统一Android版本
  9. Android之系统自带的文字外观设置及实际显示效果图

随机推荐

  1. 如何实现Android(安卓)布局背景模糊化处
  2. Android的应用程序框架
  3. Android输入管理_InputManager服务启动
  4. Android模拟器访问Tomcat和IIS7
  5. Android(安卓)DownloadManager下载进度查
  6. android tips:从资源文件中读取文件流显
  7. Android消息推送
  8. 清单文件,测试,打电话和发短信应用
  9. android 判断sdcard是否存在,以及写入权限
  10. android之动画(一)通过AnimationDrawable控