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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:解决Android O 错误Context.startForegroundService() did not then call Service.startForeground
下一篇:编译avdecc-lib 方法

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月06日 15时16分38秒