Android P系统时间更新分析
发布日期:2021-06-29 01:27:09
浏览次数:2
分类:技术文章
本文共 13652 字,大约阅读时间需要 45 分钟。
Android P系统时间更新分析
文中的代码都是Android 原生代码代码位置
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
类的调用框图
代码分析
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(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*文件。 参考资料
转载地址:https://blog.csdn.net/yt_42370304/article/details/105794664 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关注你微信了!
[***.104.42.241]2024年04月06日 15时16分38秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
一条数据的HBase之旅
2019-04-29
Hbase2.1.5集群环境搭建
2019-04-29
Hbase一些问题点
2019-04-29
关于服务器在处理性能上的对比以及达到的速度
2019-04-29
深度探索MySQL主从复制原理
2019-04-29
关于Mysql的存储引擎Innodb和Myisam
2019-04-29
部标JT808协议处理方案
2019-04-29
WebSocket实现与原理
2019-04-29
Docker概述与安装使用
2019-04-29
Java Serializable:明明就一个空的接口嘛
2019-04-29
Dockerfile 文件命令详解
2019-04-29
JAVA音视频解决方案----JTT1078-2016文档梳理与一些难点梳理
2019-04-29
RabbitMQ的工作流程
2019-04-29
RabbitMQ的消息安全机制
2019-04-29
Kafka的消息安全机制
2019-04-29
RabbitMq集群环境搭建
2019-04-29
系统设计规范化解决了什么问题
2019-04-29
java:快速排序算法与冒泡排序算法
2019-04-29
概要设计与详细设计
2019-04-29
Flying Saucer实现html转pdf(一些问题,持续更新)
2019-04-29