根据字符自动确定时区查找到Setting中对应的字符
1
2packages/apps/Settings/res/values-zh-rCN/strings.xml: <string name="zone_auto" msgid="334783869352026648">"自动确定时区"</string>
而后可以知道其对应的文件是:packages/apps/Settings/res/xml/date_time_prefs.xml,代码片段是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<PreferenceCategory android:key="time_zone_preference_category" android:layout="@layout/preference_category_no_label"> <com.android.settingslib.RestrictedSwitchPreference android:key="auto_zone" android:title="@string/zone_auto" android:summaryOn="@string/zone_auto_summaryOn" android:summaryOff="@string/zone_auto_summaryOff" settings:userRestriction="no_config_date_time" /> <com.android.settingslib.RestrictedPreference android:fragment="com.android.settings.datetime.ZonePicker" android:key="timezone" android:title="@string/date_time_set_timezone" android:summary="@string/summary_placeholder" settings:userRestriction="no_config_date_time" /> </PreferenceCategory>
根据以上的Key值auto_zone,可以知道所在的文件为:
packages/apps/Settings/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
获取到关键的控制参数是:Settings.Global.AUTO_TIME_ZONE
1
2
3
4
5
6
7
8
9@Override public boolean onPreferenceChange(Preference preference, Object newValue) { boolean autoZoneEnabled = (Boolean) newValue; Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTO_TIME_ZONE, autoZoneEnabled ? 1 : 0); mCallback.updateTimeAndDateDisplay(mContext); return true; }
在Service中有对Settings.Global.AUTO_TIME_ZONE的设置的反应,查找可以找到对应的Service是
frameworks/base/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
1
2
3
4
5
6
7
8
9
10
11
12
13@Override public boolean setTimeZone(ComponentName who, String timeZone) { Preconditions.checkNotNull(who, "ComponentName is null in setTimeZone"); getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); // Don't allow set timezone when auto timezone is on. if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) == 1) { return false; } mInjector.binderWithCleanCallingIdentity(() -> mInjector.getAlarmManager().setTimeZone(timeZone)); return true; }
对Settings.Global.AUTO_TIME_ZONE参数变化的监听是:frameworks/opt/telephony/src/java/com/android/internal/telephony/TimeServiceHelper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40public interface Listener { /** * Automatic time detection has been enabled or disabled. */ void onTimeDetectionChange(boolean enabled); /** * Automatic time zone detection has been enabled or disabled. */ void onTimeZoneDetectionChange(boolean enabled); } /** * Sets a listener that will be called when the automatic time / time zone detection setting * changes. */ public void setListener(Listener listener) { if (listener == null) { throw new NullPointerException("listener==null"); } if (mListener != null) { throw new IllegalStateException("listener already set"); } this.mListener = listener; mCr.registerContentObserver( Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true, new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { listener.onTimeDetectionChange(isTimeDetectionEnabled()); } }); mCr.registerContentObserver( Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true, new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { listener.onTimeZoneDetectionChange(isTimeZoneDetectionEnabled()); } }); }
当时区开关改变时候,会有监听函数:onTimeZoneDetectionChange响应;
继续跟踪可以找到实现该代码的位置:
frameworks/opt/telephony/src/java/com/android/internal/telephony/NitzStateMachine.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33mTimeServiceHelper.setListener(new TimeServiceHelper.Listener() { @Override public void onTimeDetectionChange(boolean enabled) { if (enabled) { handleAutoTimeEnabled(); } } @Override public void onTimeZoneDetectionChange(boolean enabled) { if (enabled) { handleAutoTimeZoneEnabled(); } } }); private void handleAutoTimeZoneEnabled() { String tmpLog = "handleAutoTimeZoneEnabled: Reverting to NITZ TimeZone:" + " mSavedTimeZoneId=" + mSavedTimeZoneId; if (DBG) { Rlog.d(LOG_TAG, tmpLog); } mTimeZoneLog.log(tmpLog); if (mSavedTimeZoneId != null) { setAndBroadcastNetworkSetTimeZone(mSavedTimeZoneId); } else { String iso = mDeviceState.getNetworkCountryIsoForPhone(); if (!TextUtils.isEmpty(iso)) { updateTimeZoneByNetworkCountryCode(iso); } } }
接收到网络更新的时区更新:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185/** * Handle a new NITZ signal being received. */ public void handleNitzReceived(TimeStampedValue<NitzData> nitzSignal) { handleTimeZoneFromNitz(nitzSignal); handleTimeFromNitz(nitzSignal); } private void handleTimeZoneFromNitz(TimeStampedValue<NitzData> nitzSignal) { try { NitzData newNitzData = nitzSignal.mValue; String iso = mDeviceState.getNetworkCountryIsoForPhone(); String zoneId; if (newNitzData.getEmulatorHostTimeZone() != null) { zoneId = newNitzData.getEmulatorHostTimeZone().getID(); } else { if (!mGotCountryCode) { zoneId = null; } else if (!TextUtils.isEmpty(iso)) { OffsetResult lookupResult = mTimeZoneLookupHelper.lookupByNitzCountry(newNitzData, iso); zoneId = lookupResult != null ? lookupResult.zoneId : null; } else { // We don't have a valid iso country code. This is // most likely because we're on a test network that's // using a bogus MCC (eg, "001"), so get a TimeZone // based only on the NITZ parameters. OffsetResult lookupResult = mTimeZoneLookupHelper.lookupByNitz(newNitzData); if (DBG) { Rlog.d(LOG_TAG, "handleTimeZoneFromNitz: guessZoneIdByNitz returned" + " lookupResult=" + lookupResult); } zoneId = lookupResult != null ? lookupResult.zoneId : null; } } if ((zoneId == null) || mLatestNitzSignal == null || offsetInfoDiffers(newNitzData, mLatestNitzSignal.mValue)) { // We got the time before the country, or the zone has changed // so we don't know how to identify the DST rules yet. Save // the information and hope to fix it up later. mNeedCountryCodeForNitz = true; mLatestNitzSignal = nitzSignal; } String tmpLog = "handleTimeZoneFromNitz: nitzSignal=" + nitzSignal + " zoneId=" + zoneId + " iso=" + iso + " mGotCountryCode=" + mGotCountryCode + " mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz + " isTimeZoneDetectionEnabled()=" + mTimeServiceHelper.isTimeZoneDetectionEnabled(); if (DBG) { Rlog.d(LOG_TAG, tmpLog); } mTimeZoneLog.log(tmpLog); if (zoneId != null) { if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) { setAndBroadcastNetworkSetTimeZone(zoneId); } mNitzTimeZoneDetectionSuccessful = true; mSavedTimeZoneId = zoneId; } } catch (RuntimeException ex) { Rlog.e(LOG_TAG, "handleTimeZoneFromNitz: Processing NITZ data" + " nitzSignal=" + nitzSignal + " ex=" + ex); } } private static boolean offsetInfoDiffers(NitzData one, NitzData two) { return one.getLocalOffsetMillis() != two.getLocalOffsetMillis() || one.isDst() != two.isDst(); } private void handleTimeFromNitz(TimeStampedValue<NitzData> nitzSignal) { try { boolean ignoreNitz = mDeviceState.getIgnoreNitz(); if (ignoreNitz) { Rlog.d(LOG_TAG, "handleTimeFromNitz: Not setting clock because gsm.ignore-nitz is set"); return; } try { // Acquire the wake lock as we are reading the elapsed realtime clock and system // clock. mWakeLock.acquire(); // Validate the nitzTimeSignal to reject obviously bogus elapsedRealtime values. long elapsedRealtime = mTimeServiceHelper.elapsedRealtime(); long millisSinceNitzReceived = elapsedRealtime - nitzSignal.mElapsedRealtime; if (millisSinceNitzReceived < 0 || millisSinceNitzReceived > Integer.MAX_VALUE) { if (DBG) { Rlog.d(LOG_TAG, "handleTimeFromNitz: not setting time, unexpected" + " elapsedRealtime=" + elapsedRealtime + " nitzSignal=" + nitzSignal); } return; } // Adjust the NITZ time by the delay since it was received to get the time now. long adjustedCurrentTimeMillis = nitzSignal.mValue.getCurrentTimeInMillis() + millisSinceNitzReceived; long gained = adjustedCurrentTimeMillis - mTimeServiceHelper.currentTimeMillis(); if (mTimeServiceHelper.isTimeDetectionEnabled()) { String logMsg = "handleTimeFromNitz:" + " nitzSignal=" + nitzSignal + " adjustedCurrentTimeMillis=" + adjustedCurrentTimeMillis + " millisSinceNitzReceived= " + millisSinceNitzReceived + " gained=" + gained; if (mSavedNitzTime == null) { logMsg += ": First update received."; setAndBroadcastNetworkSetTime(logMsg, adjustedCurrentTimeMillis); } else { long elapsedRealtimeSinceLastSaved = mTimeServiceHelper.elapsedRealtime() - mSavedNitzTime.mElapsedRealtime; int nitzUpdateSpacing = mDeviceState.getNitzUpdateSpacingMillis(); int nitzUpdateDiff = mDeviceState.getNitzUpdateDiffMillis(); if (elapsedRealtimeSinceLastSaved > nitzUpdateSpacing || Math.abs(gained) > nitzUpdateDiff) { // Either it has been a while since we received an update, or the gain // is sufficiently large that we want to act on it. logMsg += ": New update received."; setAndBroadcastNetworkSetTime(logMsg, adjustedCurrentTimeMillis); } else { if (DBG) { Rlog.d(LOG_TAG, logMsg + ": Update throttled."); } // Return early. This means that we don't reset the // mSavedNitzTime for next time and that we may act on more // NITZ time signals overall but should end up with a system clock that // tracks NITZ more closely than if we saved throttled values (which // would reset mSavedNitzTime.elapsedRealtime used to calculate time // since the last NITZ signal was received). return; } } } // Save the last NITZ time signal used so we can return to it later // if auto-time detection is toggled. mSavedNitzTime = new TimeStampedValue<>( adjustedCurrentTimeMillis, nitzSignal.mElapsedRealtime); } finally { mWakeLock.release(); } } catch (RuntimeException ex) { Rlog.e(LOG_TAG, "handleTimeFromNitz: Processing NITZ data" + " nitzSignal=" + nitzSignal + " ex=" + ex); } } private void setAndBroadcastNetworkSetTimeZone(String zoneId) { if (DBG) { Rlog.d(LOG_TAG, "setAndBroadcastNetworkSetTimeZone: zoneId=" + zoneId); } mTimeServiceHelper.setDeviceTimeZone(zoneId); if (DBG) { Rlog.d(LOG_TAG, "setAndBroadcastNetworkSetTimeZone: called setDeviceTimeZone()" + " zoneId=" + zoneId); } } private void setAndBroadcastNetworkSetTime(String msg, long time) { if (!mWakeLock.isHeld()) { Rlog.w(LOG_TAG, "setAndBroadcastNetworkSetTime: Wake lock not held while setting device" + " time (msg=" + msg + ")"); } msg = "setAndBroadcastNetworkSetTime: [Setting time to time=" + time + "]:" + msg; if (DBG) { Rlog.d(LOG_TAG, msg); } mTimeLog.log(msg); mTimeServiceHelper.setDeviceTime(time); TelephonyMetrics.getInstance().writeNITZEvent(mPhone.getPhoneId(), time); }
frameworks/opt/telephony/src/java/com/android/internal/telephony/ServiceStateTracker.java找到mNitzState.handleNitzReceived(nitzSignal)函数的调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24/** * nitzReceiveTime is time_t that the NITZ time was posted */ private void setTimeFromNITZString(String nitzString, long nitzReceiveTime) { long start = SystemClock.elapsedRealtime(); if (DBG) { Rlog.d(LOG_TAG, "NITZ: " + nitzString + "," + nitzReceiveTime + " start=" + start + " delay=" + (start - nitzReceiveTime)); } NitzData newNitzData = NitzData.parse(nitzString); if (newNitzData != null) { try { TimeStampedValue<NitzData> nitzSignal = new TimeStampedValue<>(newNitzData, nitzReceiveTime); mNitzState.handleNitzReceived(nitzSignal); } finally { if (DBG) { long end = SystemClock.elapsedRealtime(); Rlog.d(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start)); } } } }
ServiceStateTracker文件中对EVENT_NITZ_TIME事件的处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44@Override public void handleMessage(Message msg) { AsyncResult ar; int[] ints; Message message; if (VDBG) log("received event " + msg.what); switch (msg.what) { case EVENT_SET_RADIO_POWER_OFF: synchronized(this) { if (mPendingRadioPowerOffAfterDataOff && (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) { if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now."); hangupAndPowerOff(); mPendingRadioPowerOffAfterDataOffTag += 1; mPendingRadioPowerOffAfterDataOff = false; } else { log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 + "!= tag=" + mPendingRadioPowerOffAfterDataOffTag); } } break; //省略较多代码.. 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; case EVENT_SIGNAL_STRENGTH_UPDATE: // This is a notification from CommandsInterface.setOnSignalStrengthUpdate ar = (AsyncResult) msg.obj; // The radio is telling us about signal strength changes // we don't have to ask it mDontPollSignalStrength = true; onSignalStrengthResult(ar); break;
1
2
3
4
5
6
7
8
9
10public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) { mNitzState = TelephonyComponentFactory.getInstance().makeNitzStateMachine(phone); mPhone = phone; mCi = ci; //省略较多代码 mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null); mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null);
frameworks/opt/telephony/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40public static TelephonyComponentFactory getInstance() { if (sInstance == null) { String fullClsName = "com.qualcomm.qti.internal.telephony.QtiTelephonyComponentFactory"; String libPath = "/system/framework/qti-telephony-common.jar"; PathClassLoader classLoader = new PathClassLoader(libPath, ClassLoader.getSystemClassLoader()); Rlog.d(LOG_TAG, "classLoader = " + classLoader); if (fullClsName == null || fullClsName.length() == 0) { Rlog.d(LOG_TAG, "no customized TelephonyPlugin available, fallback to default"); fullClsName = "com.android.internal.telephony.TelephonyComponentFactory"; } Class<?> cls = null; try { cls = Class.forName(fullClsName, false, classLoader); Rlog.d(LOG_TAG, "cls = " + cls); Constructor custMethod = cls.getConstructor(); Rlog.d(LOG_TAG, "constructor method = " + custMethod); sInstance = (TelephonyComponentFactory) custMethod.newInstance(); } catch (NoClassDefFoundError e) { e.printStackTrace(); Rlog.e(LOG_TAG, "error loading TelephonyComponentFactory"); sInstance = new TelephonyComponentFactory(); } catch (Exception e) { e.printStackTrace(); Rlog.e(LOG_TAG, "Error loading TelephonyComponentFactory"); sInstance = new TelephonyComponentFactory(); } } return sInstance; } /** * Returns a new {@link NitzStateMachine} instance. */ public NitzStateMachine makeNitzStateMachine(GsmCdmaPhone phone) { return new NitzStateMachine(phone); }
frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioIndication.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public void nitzTimeReceived(int indicationType, String nitzTime, long receivedTime) { mRil.processIndication(indicationType); if (RIL.RILJ_LOGD) mRil.unsljLogRet(RIL_UNSOL_NITZ_TIME_RECEIVED, nitzTime); // todo: Clean this up with a parcelable class for better self-documentation Object[] result = new Object[2]; result[0] = nitzTime; result[1] = receivedTime; boolean ignoreNitz = SystemProperties.getBoolean( TelephonyProperties.PROPERTY_IGNORE_NITZ, false); if (ignoreNitz) { if (RIL.RILJ_LOGD) mRil.riljLog("ignoring UNSOL_NITZ_TIME_RECEIVED"); } else { if (mRil.mNITZTimeRegistrant != null) { mRil.mNITZTimeRegistrant.notifyRegistrant(new AsyncResult (null, result, null)); } // in case NITZ time registrant isn't registered yet, or a new registrant // registers later mRil.mLastNITZTimeInfo = result; } }
接着上述, 查看mTimeServiceHelper 的定义处:
frameworks/opt/telephony/src/java/com/android/internal/telephony/TimeServiceHelper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/** * Set the device time zone and send out a sticky broadcast so the system can * determine if the timezone was set by the carrier. * * @param zoneId timezone set by carrier */ public void setDeviceTimeZone(String zoneId) { setDeviceTimeZoneStatic(mContext, zoneId); } /** * Static method for use by MccTable. See {@link #isTimeZoneSettingInitializedStatic()} for * explanation. */ static void setDeviceTimeZoneStatic(Context context, String zoneId) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.setTimeZone(zoneId); Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra("time-zone", zoneId); context.sendStickyBroadcastAsUser(intent, UserHandle.ALL); }
根据广播TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE找到文件:
frameworks/base/telephony/java/com/android/internal/telephony/TelephonyIntents.java
1
2
最后
以上就是勤恳钢笔最近收集整理的关于Android P自动确定时区代码流程的全部内容,更多相关Android内容请搜索靠谱客的其他文章。
发表评论 取消回复