概述
根据字符自动确定时区查找到Setting中对应的字符
packages/apps/Settings/res/values-zh-rCN/strings.xml: <string name="zone_auto" msgid="334783869352026648">"自动确定时区"</string>
而后可以知道其对应的文件是:packages/apps/Settings/res/xml/date_time_prefs.xml,代码片段是:
<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
@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
@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
public 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
mTimeServiceHelper.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);
}
}
}
接收到网络更新的时区更新:
/**
* 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)函数的调用:
/**
* 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事件的处理:
@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;
public 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
public 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
public 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
/**
* 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
最后
以上就是勤恳钢笔为你收集整理的Android P自动确定时区代码流程的全部内容,希望文章能够帮你解决Android P自动确定时区代码流程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复