Loading src/java/com/android/internal/telephony/NitzStateMachine.java +132 −115 Original line number Diff line number Diff line Loading @@ -131,13 +131,13 @@ public class NitzStateMachine { // Time Zone detection state. /** * Sometimes we get the NITZ time before we know what country we * are in. Keep the time zone information from the NITZ string in * mNitzData so we can fix the time zone once know the country. * Sometimes we get the NITZ time before we know what country we are in. We keep the time zone * information from the NITZ string in mLatestNitzSignal so we can fix the time zone once we * know the country. */ private boolean mNeedCountryCodeForNitz = false; private NitzData mNitzData; private TimeStampedValue<NitzData> mLatestNitzSignal; private boolean mGotCountryCode = false; private String mSavedTimeZoneId; Loading Loading @@ -225,65 +225,77 @@ public class NitzStateMachine { final boolean isTimeZoneSettingInitialized = mTimeServiceHelper.isTimeZoneSettingInitialized(); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone" Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet:" + " isTimeZoneSettingInitialized=" + isTimeZoneSettingInitialized + " mNitzData=" + mNitzData + " iso-cc='" + isoCountryCode + "' countryUsesUtc=" + mTimeZoneLookupHelper.countryUsesUtc(isoCountryCode)); + " mLatestNitzSignal=" + mLatestNitzSignal + " isoCountryCode=" + isoCountryCode); } String zoneId; if (TextUtils.isEmpty(isoCountryCode) && mNeedCountryCodeForNitz) { // Country code not found. This is likely a test network. // Get a TimeZone based only on the NITZ parameters (best guess). // mNeedCountryCodeForNitz is only set to true when mNitzData is set so there's no // need to check mNitzData == null. zoneId = mTimeZoneLookupHelper.guessZoneIdByNitz(mNitzData); // mNeedCountryCodeForNitz is only set to true when mLatestNitzSignal is set so // there's no need to check mLatestNitzSignal == null. zoneId = mTimeZoneLookupHelper.guessZoneIdByNitz(mLatestNitzSignal.mValue); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone(): guessNitzTimeZone returned " + zoneId); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: guessZoneIdByNitz() returned" + " zoneId=" + zoneId); } } else if ((mNitzData == null || nitzOffsetMightBeBogus(mNitzData)) } else if (mLatestNitzSignal == null) { zoneId = null; if (DBG) { Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: No cached NITZ data available," + " not setting zone"); } } else { // mLatestNitzSignal != null if (nitzOffsetMightBeBogus(mLatestNitzSignal.mValue) && isTimeZoneSettingInitialized && !mTimeZoneLookupHelper.countryUsesUtc(isoCountryCode)) { // This case means that (1) the device received no NITZ signal yet or received an // NITZ signal that looks bogus due to having a zero offset from UTC, (2) the device // has a time zone set explicitly, and (3) the iso tells us the country is NOT one // that uses a zero offset. This is interpreted as being NITZ incorrectly reporting // a local time and not a UTC time. The zone is left as the current device's zone // setting, and the time may be adjusted by assuming the current zone setting is // correct. && !countryUsesUtc(isoCountryCode, mLatestNitzSignal)) { // This case means that (1) the device received an NITZ signal that could be // bogus due to having a zero offset from UTC, (2) the device has a time zone // set explicitly and (3) the iso tells us the country is NOT one that uses a // zero offset. This is interpreted as being NITZ incorrectly reporting a local // time and not a UTC time. The zone is left as the current device's zone // setting, and the system clock may be adjusted by taking the NITZ time and // assuming the current zone setting is correct. TimeZone zone = TimeZone.getDefault(); zoneId = zone.getID(); // Note that mNeedCountryCodeForNitz => (implies) { mNitzData != null }. Therefore, // if mNitzData == null, mNeedCountryCodeForNitz cannot be true. The code in this // section therefore means that when mNitzData == null (and the country is one that // doesn't use a zero UTC offset) the device will retain the existing time zone // setting and not try to derive one from the isoCountryCode. if (mNeedCountryCodeForNitz) { NitzData nitzData = mLatestNitzSignal.mValue; try { // Acquire the wakelock as we're reading the system clock here. // Acquire the wakelock as we're reading the elapsed realtime clock // here. mWakeLock.acquire(); long ctm = mDeviceState.currentTimeMillis(); long tzOffset = zone.getOffset(ctm); // Use the time that came with the NITZ offset that we think is bogus: // we just interpret it as local time. long ctm = nitzData.getCurrentTimeInMillis(); long delayAdjustedCtm = ctm + (mDeviceState.elapsedRealtime() - mLatestNitzSignal.mElapsedRealtime); long tzOffset = zone.getOffset(delayAdjustedCtm); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: tzOffset=" + tzOffset + " ltod=" + TimeUtils.logTimeOfDay(ctm)); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet:" + " tzOffset=" + tzOffset + " delayAdjustedCtm=" + TimeUtils.logTimeOfDay(delayAdjustedCtm)); } if (mTimeServiceHelper.isTimeDetectionEnabled()) { long adj = ctm - tzOffset; String msg = "fixTimeZone: adj ltod=" + TimeUtils.logTimeOfDay(adj); setAndBroadcastNetworkSetTime(msg, adj); long timeZoneAdjustedCtm = delayAdjustedCtm - tzOffset; String msg = "handleNetworkCountryCodeSet: setting time" + " timeZoneAdjustedCtm=" + TimeUtils.logTimeOfDay(timeZoneAdjustedCtm); setAndBroadcastNetworkSetTime(msg, timeZoneAdjustedCtm); } else { // Adjust the saved NITZ time to account for tzOffset. mSavedNitzTime = new TimeStampedValue<>( mSavedNitzTime.mValue - tzOffset, mSavedNitzTime.mElapsedRealtime); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: adj mSavedTime=" + mSavedNitzTime); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet:" + "adjusting time mSavedNitzTime=" + mSavedNitzTime); } } } finally { Loading @@ -291,48 +303,53 @@ public class NitzStateMachine { } } if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: using default TimeZone"); } } else if (mNitzData == null) { // The use of 1/1/1970 UTC is unusual but consistent with historical behavior when // it wasn't possible to detect whether a previous NITZ signal had been saved. zoneId = mTimeZoneLookupHelper.guessZoneIdByInstantOffsetDstCountry( 0 /* when */, 0 /* offset */, false /* dst */, isoCountryCode); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: No cached NITZ data available, using only country" + " code. zoneId=" + zoneId); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: using default TimeZone"); } } else { zoneId = mTimeZoneLookupHelper.guessZoneIdByNitzCountry(mNitzData, isoCountryCode); NitzData nitzData = mLatestNitzSignal.mValue; zoneId = mTimeZoneLookupHelper.guessZoneIdByNitzCountry( nitzData, isoCountryCode); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: using getTimeZone(off, dst, time, iso)"); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: using" + " guessZoneIdByNitzCountry(nitzData, isoCountryCode)," + " nitzData=" + nitzData + " isoCountryCode=" + isoCountryCode); } } } final String tmpLog = "fixTimeZone:" final String tmpLog = "handleNetworkCountryCodeSet:" + " isTimeZoneSettingInitialized=" + isTimeZoneSettingInitialized + " mNitzData=" + mNitzData + " mLatestNitzSignal=" + mLatestNitzSignal + " iso-cc=" + isoCountryCode + " mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz + " zoneId=" + zoneId; mTimeZoneLog.log(tmpLog); if (zoneId != null) { Rlog.d(LOG_TAG, "fixTimeZone: zone != null zoneId=" + zoneId); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: zoneId != null, zoneId=" + zoneId); if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) { setAndBroadcastNetworkSetTimeZone(zoneId); } else { Rlog.d(LOG_TAG, "fixTimeZone: skip changing zone as getAutoTimeZone was false"); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: skip changing zone as" + " isTimeZoneDetectionEnabled() is false"); } if (mNeedCountryCodeForNitz) { saveNitzTimeZone(zoneId); } } else { Rlog.d(LOG_TAG, "fixTimeZone: zone == null, do nothing for zone"); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: zoneId == null, do nothing"); } mNeedCountryCodeForNitz = false; } } private boolean countryUsesUtc( String isoCountryCode, TimeStampedValue<NitzData> nitzSignal) { return mTimeZoneLookupHelper.countryUsesUtc( isoCountryCode, nitzSignal.mValue.getCurrentTimeInMillis()); } /** * Informs the {@link NitzStateMachine} that the network has become available. */ Loading Loading @@ -392,33 +409,23 @@ public class NitzStateMachine { // based only on the NITZ parameters. zoneId = mTimeZoneLookupHelper.guessZoneIdByNitz(newNitzData); if (DBG) { Rlog.d(LOG_TAG, "setTimeZoneFromNitz(): findByNitz returned " + zoneId); Rlog.d(LOG_TAG, "handleTimeZoneFromNitz: guessZoneIdByNitz returned" + " zoneId=" + zoneId); } } } int previousUtcOffset; boolean previousIsDst; if (mNitzData == null) { // No previously saved NITZ data. Use the same defaults as Android would have done // before it was possible to detect this case. previousUtcOffset = 0; previousIsDst = false; } else { previousUtcOffset = mNitzData.getLocalOffsetMillis(); previousIsDst = mNitzData.isDst(); } if ((zoneId == null) || (newNitzData.getLocalOffsetMillis() != previousUtcOffset) || (newNitzData.isDst() != previousIsDst)) { // We got the time before the country or the zone has changed || 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; mNitzData = newNitzData; mLatestNitzSignal = nitzSignal; } String tmpLog = "NITZ: nitzTimeSignal=" + nitzSignal String tmpLog = "handleTimeZoneFromNitz: nitzTimeSignal=" + nitzSignal + " zoneId=" + zoneId + " iso=" + iso + " mGotCountryCode=" + mGotCountryCode + " mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz Loading @@ -437,16 +444,23 @@ public class NitzStateMachine { saveNitzTimeZone(zoneId); } } catch (RuntimeException ex) { Rlog.e(LOG_TAG, "NITZ: Processing NITZ data " + nitzSignal + " ex=" + 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> nitzTimeSignal) { try { boolean ignoreNitz = mDeviceState.getIgnoreNitz(); if (ignoreNitz) { Rlog.d(LOG_TAG, "setTimeFromNitz: Not setting clock because gsm.ignore-nitz is set"); "handleTimeFromNitz: Not setting clock because gsm.ignore-nitz is set"); return; } Loading @@ -460,7 +474,7 @@ public class NitzStateMachine { long millisSinceNitzReceived = elapsedRealtime - nitzTimeSignal.mElapsedRealtime; if (millisSinceNitzReceived < 0 || millisSinceNitzReceived > Integer.MAX_VALUE) { if (DBG) { Rlog.d(LOG_TAG, "setTimeFromNitz: not setting time, unexpected" Rlog.d(LOG_TAG, "handleTimeFromNitz: not setting time, unexpected" + " elapsedRealtime=" + elapsedRealtime + " nitzTimeSignal=" + nitzTimeSignal); } Loading @@ -473,7 +487,7 @@ public class NitzStateMachine { long gained = adjustedCurrentTimeMillis - mDeviceState.currentTimeMillis(); if (mTimeServiceHelper.isTimeDetectionEnabled()) { String logMsg = "(setTimeFromNitz)" String logMsg = "handleTimeFromNitz:" + " nitzTimeSignal=" + nitzTimeSignal + " adjustedCurrentTimeMillis=" + adjustedCurrentTimeMillis + " millisSinceNitzReceived= " + millisSinceNitzReceived Loading Loading @@ -517,7 +531,8 @@ public class NitzStateMachine { mWakeLock.release(); } } catch (RuntimeException ex) { Rlog.e(LOG_TAG, "setTimeFromNitz: Processing NITZ data " + nitzTimeSignal Rlog.e(LOG_TAG, "handleTimeFromNitz: Processing NITZ data" + " nitzTimeSignal=" + nitzTimeSignal + " ex=" + ex); } } Loading @@ -533,17 +548,18 @@ public class NitzStateMachine { mTimeServiceHelper.setDeviceTimeZone(zoneId); if (DBG) { Rlog.d(LOG_TAG, "setAndBroadcastNetworkSetTimeZone: call alarm.setTimeZone and broadcast" "setAndBroadcastNetworkSetTimeZone: called setDeviceTimeZone()" + " zoneId=" + zoneId); } } private void setAndBroadcastNetworkSetTime(String msg, long time) { if (!mWakeLock.isHeld()) { Rlog.w(LOG_TAG, "Wake lock not held while setting device time (msg=" + msg + ")"); Rlog.w(LOG_TAG, "setAndBroadcastNetworkSetTime: Wake lock not held while setting device" + " time (msg=" + msg + ")"); } msg = "setAndBroadcastNetworkSetTime: [setting time to time=" + time + "]:" + msg; msg = "setAndBroadcastNetworkSetTime: [Setting time to time=" + time + "]:" + msg; if (DBG) { Rlog.d(LOG_TAG, msg); } Loading @@ -554,7 +570,8 @@ public class NitzStateMachine { private void handleAutoTimeEnabled() { if (DBG) { Rlog.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedNitzTime); Rlog.d(LOG_TAG, "handleAutoTimeEnabled: Reverting to NITZ Time:" + " mSavedNitzTime=" + mSavedNitzTime); } if (mSavedNitzTime != null) { try { Loading @@ -562,7 +579,8 @@ public class NitzStateMachine { mWakeLock.acquire(); long elapsedRealtime = mDeviceState.elapsedRealtime(); String msg = "Reverting to NITZ time, elapsedRealtime=" + elapsedRealtime String msg = "mSavedNitzTime: Reverting to NITZ time" + " elapsedRealtime=" + elapsedRealtime + " mSavedNitzTime=" + mSavedNitzTime; long adjustedCurrentTimeMillis = mSavedNitzTime.mValue + (elapsedRealtime - mSavedNitzTime.mElapsedRealtime); Loading @@ -574,7 +592,8 @@ public class NitzStateMachine { } private void handleAutoTimeZoneEnabled() { String tmpLog = "Reverting to NITZ TimeZone: tz=" + mSavedTimeZoneId; String tmpLog = "handleAutoTimeZoneEnabled: Reverting to NITZ TimeZone:" + " mSavedTimeZoneId=" + mSavedTimeZoneId; if (DBG) { Rlog.d(LOG_TAG, tmpLog); } Loading @@ -598,7 +617,7 @@ public class NitzStateMachine { // Time Zone Detection State pw.println(" mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz); pw.println(" mNitzData=" + mNitzData); pw.println(" mLatestNitzSignal=" + mLatestNitzSignal); pw.println(" mGotCountryCode=" + mGotCountryCode); pw.println(" mSavedTimeZone=" + mSavedTimeZoneId); pw.println(" mNitzTimeZoneDetectionSuccessful=" + mNitzTimeZoneDetectionSuccessful); Loading Loading @@ -633,19 +652,17 @@ public class NitzStateMachine { String zoneId = mTimeZoneLookupHelper.guessZoneIdByCountry( iso, mDeviceState.currentTimeMillis()); if (zoneId != null) { String logMsg = "updateTimeZoneByNetworkCountryCode: set time" + " zoneId=" + zoneId + " iso=" + iso; if (DBG) { Rlog.d(LOG_TAG, "updateTimeZoneByNetworkCountryCode: set time zone=" + zoneId + " iso=" + iso); Rlog.d(LOG_TAG, logMsg); } mTimeZoneLog.log("updateTimeZoneByNetworkCountryCode: set time zone=" + zoneId + " iso=" + iso); mTimeZoneLog.log(logMsg); setAndBroadcastNetworkSetTimeZone(zoneId); } else { if (DBG) { Rlog.d(LOG_TAG, "updateTimeZoneByNetworkCountryCode: no good zone for iso-cc='" + iso + "', do nothing"); Rlog.d(LOG_TAG, "updateTimeZoneByNetworkCountryCode: no good zone for iso=" + iso); } } } Loading @@ -661,7 +678,7 @@ public class NitzStateMachine { * Returns the last NITZ data that was cached. */ public NitzData getCachedNitzData() { return mNitzData; return mLatestNitzSignal != null ? mLatestNitzSignal.mValue : null; } /** Loading src/java/com/android/internal/telephony/TimeZoneLookupHelper.java +13 −33 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package com.android.internal.telephony; import android.text.TextUtils; import android.util.TimeUtils; import libcore.util.CountryTimeZones; import libcore.util.TimeZoneFinder; import java.util.Arrays; import java.util.Date; import java.util.TimeZone; Loading @@ -32,35 +32,6 @@ import java.util.TimeZone; public class TimeZoneLookupHelper { private static final int MS_PER_HOUR = 60 * 60 * 1000; /** * List of ISO codes for countries that can have an offset of * GMT+0 when not in daylight savings time. This ignores some * small places such as the Canary Islands (Spain) and * Danmarkshavn (Denmark). The list must be sorted by code. */ private static final String[] GMT_COUNTRY_CODES = { "bf", // Burkina Faso "ci", // Cote d'Ivoire "eh", // Western Sahara "fo", // Faroe Islands, Denmark "gb", // United Kingdom of Great Britain and Northern Ireland "gh", // Ghana "gm", // Gambia "gn", // Guinea "gw", // Guinea Bissau "ie", // Ireland "lr", // Liberia "is", // Iceland "ma", // Morocco "ml", // Mali "mr", // Mauritania "pt", // Portugal "sl", // Sierra Leone "sn", // Senegal "st", // Sao Tome and Principe "tg", // Togo }; public TimeZoneLookupHelper() {} /** Loading Loading @@ -165,9 +136,18 @@ public class TimeZoneLookupHelper { /** * Returns {@code true} if the supplied (lower-case) ISO country code is for a country known to * use a raw offset of zero from UTC. * use a raw offset of zero from UTC at the time specified. */ public boolean countryUsesUtc(String isoCountryCode) { return Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode) >= 0; public boolean countryUsesUtc(String isoCountryCode, long whenMillis) { if (TextUtils.isEmpty(isoCountryCode)) { return false; } CountryTimeZones countryTimeZones = TimeZoneFinder.getInstance().lookupCountryTimeZones(isoCountryCode); if (countryTimeZones == null) { return false; } return countryTimeZones.hasUtcZone(whenMillis); } } tests/telephonytests/src/com/android/internal/telephony/TimeZoneLookupHelperTest.java +15 −12 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
src/java/com/android/internal/telephony/NitzStateMachine.java +132 −115 Original line number Diff line number Diff line Loading @@ -131,13 +131,13 @@ public class NitzStateMachine { // Time Zone detection state. /** * Sometimes we get the NITZ time before we know what country we * are in. Keep the time zone information from the NITZ string in * mNitzData so we can fix the time zone once know the country. * Sometimes we get the NITZ time before we know what country we are in. We keep the time zone * information from the NITZ string in mLatestNitzSignal so we can fix the time zone once we * know the country. */ private boolean mNeedCountryCodeForNitz = false; private NitzData mNitzData; private TimeStampedValue<NitzData> mLatestNitzSignal; private boolean mGotCountryCode = false; private String mSavedTimeZoneId; Loading Loading @@ -225,65 +225,77 @@ public class NitzStateMachine { final boolean isTimeZoneSettingInitialized = mTimeServiceHelper.isTimeZoneSettingInitialized(); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone" Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet:" + " isTimeZoneSettingInitialized=" + isTimeZoneSettingInitialized + " mNitzData=" + mNitzData + " iso-cc='" + isoCountryCode + "' countryUsesUtc=" + mTimeZoneLookupHelper.countryUsesUtc(isoCountryCode)); + " mLatestNitzSignal=" + mLatestNitzSignal + " isoCountryCode=" + isoCountryCode); } String zoneId; if (TextUtils.isEmpty(isoCountryCode) && mNeedCountryCodeForNitz) { // Country code not found. This is likely a test network. // Get a TimeZone based only on the NITZ parameters (best guess). // mNeedCountryCodeForNitz is only set to true when mNitzData is set so there's no // need to check mNitzData == null. zoneId = mTimeZoneLookupHelper.guessZoneIdByNitz(mNitzData); // mNeedCountryCodeForNitz is only set to true when mLatestNitzSignal is set so // there's no need to check mLatestNitzSignal == null. zoneId = mTimeZoneLookupHelper.guessZoneIdByNitz(mLatestNitzSignal.mValue); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone(): guessNitzTimeZone returned " + zoneId); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: guessZoneIdByNitz() returned" + " zoneId=" + zoneId); } } else if ((mNitzData == null || nitzOffsetMightBeBogus(mNitzData)) } else if (mLatestNitzSignal == null) { zoneId = null; if (DBG) { Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: No cached NITZ data available," + " not setting zone"); } } else { // mLatestNitzSignal != null if (nitzOffsetMightBeBogus(mLatestNitzSignal.mValue) && isTimeZoneSettingInitialized && !mTimeZoneLookupHelper.countryUsesUtc(isoCountryCode)) { // This case means that (1) the device received no NITZ signal yet or received an // NITZ signal that looks bogus due to having a zero offset from UTC, (2) the device // has a time zone set explicitly, and (3) the iso tells us the country is NOT one // that uses a zero offset. This is interpreted as being NITZ incorrectly reporting // a local time and not a UTC time. The zone is left as the current device's zone // setting, and the time may be adjusted by assuming the current zone setting is // correct. && !countryUsesUtc(isoCountryCode, mLatestNitzSignal)) { // This case means that (1) the device received an NITZ signal that could be // bogus due to having a zero offset from UTC, (2) the device has a time zone // set explicitly and (3) the iso tells us the country is NOT one that uses a // zero offset. This is interpreted as being NITZ incorrectly reporting a local // time and not a UTC time. The zone is left as the current device's zone // setting, and the system clock may be adjusted by taking the NITZ time and // assuming the current zone setting is correct. TimeZone zone = TimeZone.getDefault(); zoneId = zone.getID(); // Note that mNeedCountryCodeForNitz => (implies) { mNitzData != null }. Therefore, // if mNitzData == null, mNeedCountryCodeForNitz cannot be true. The code in this // section therefore means that when mNitzData == null (and the country is one that // doesn't use a zero UTC offset) the device will retain the existing time zone // setting and not try to derive one from the isoCountryCode. if (mNeedCountryCodeForNitz) { NitzData nitzData = mLatestNitzSignal.mValue; try { // Acquire the wakelock as we're reading the system clock here. // Acquire the wakelock as we're reading the elapsed realtime clock // here. mWakeLock.acquire(); long ctm = mDeviceState.currentTimeMillis(); long tzOffset = zone.getOffset(ctm); // Use the time that came with the NITZ offset that we think is bogus: // we just interpret it as local time. long ctm = nitzData.getCurrentTimeInMillis(); long delayAdjustedCtm = ctm + (mDeviceState.elapsedRealtime() - mLatestNitzSignal.mElapsedRealtime); long tzOffset = zone.getOffset(delayAdjustedCtm); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: tzOffset=" + tzOffset + " ltod=" + TimeUtils.logTimeOfDay(ctm)); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet:" + " tzOffset=" + tzOffset + " delayAdjustedCtm=" + TimeUtils.logTimeOfDay(delayAdjustedCtm)); } if (mTimeServiceHelper.isTimeDetectionEnabled()) { long adj = ctm - tzOffset; String msg = "fixTimeZone: adj ltod=" + TimeUtils.logTimeOfDay(adj); setAndBroadcastNetworkSetTime(msg, adj); long timeZoneAdjustedCtm = delayAdjustedCtm - tzOffset; String msg = "handleNetworkCountryCodeSet: setting time" + " timeZoneAdjustedCtm=" + TimeUtils.logTimeOfDay(timeZoneAdjustedCtm); setAndBroadcastNetworkSetTime(msg, timeZoneAdjustedCtm); } else { // Adjust the saved NITZ time to account for tzOffset. mSavedNitzTime = new TimeStampedValue<>( mSavedNitzTime.mValue - tzOffset, mSavedNitzTime.mElapsedRealtime); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: adj mSavedTime=" + mSavedNitzTime); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet:" + "adjusting time mSavedNitzTime=" + mSavedNitzTime); } } } finally { Loading @@ -291,48 +303,53 @@ public class NitzStateMachine { } } if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: using default TimeZone"); } } else if (mNitzData == null) { // The use of 1/1/1970 UTC is unusual but consistent with historical behavior when // it wasn't possible to detect whether a previous NITZ signal had been saved. zoneId = mTimeZoneLookupHelper.guessZoneIdByInstantOffsetDstCountry( 0 /* when */, 0 /* offset */, false /* dst */, isoCountryCode); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: No cached NITZ data available, using only country" + " code. zoneId=" + zoneId); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: using default TimeZone"); } } else { zoneId = mTimeZoneLookupHelper.guessZoneIdByNitzCountry(mNitzData, isoCountryCode); NitzData nitzData = mLatestNitzSignal.mValue; zoneId = mTimeZoneLookupHelper.guessZoneIdByNitzCountry( nitzData, isoCountryCode); if (DBG) { Rlog.d(LOG_TAG, "fixTimeZone: using getTimeZone(off, dst, time, iso)"); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: using" + " guessZoneIdByNitzCountry(nitzData, isoCountryCode)," + " nitzData=" + nitzData + " isoCountryCode=" + isoCountryCode); } } } final String tmpLog = "fixTimeZone:" final String tmpLog = "handleNetworkCountryCodeSet:" + " isTimeZoneSettingInitialized=" + isTimeZoneSettingInitialized + " mNitzData=" + mNitzData + " mLatestNitzSignal=" + mLatestNitzSignal + " iso-cc=" + isoCountryCode + " mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz + " zoneId=" + zoneId; mTimeZoneLog.log(tmpLog); if (zoneId != null) { Rlog.d(LOG_TAG, "fixTimeZone: zone != null zoneId=" + zoneId); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: zoneId != null, zoneId=" + zoneId); if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) { setAndBroadcastNetworkSetTimeZone(zoneId); } else { Rlog.d(LOG_TAG, "fixTimeZone: skip changing zone as getAutoTimeZone was false"); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: skip changing zone as" + " isTimeZoneDetectionEnabled() is false"); } if (mNeedCountryCodeForNitz) { saveNitzTimeZone(zoneId); } } else { Rlog.d(LOG_TAG, "fixTimeZone: zone == null, do nothing for zone"); Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: zoneId == null, do nothing"); } mNeedCountryCodeForNitz = false; } } private boolean countryUsesUtc( String isoCountryCode, TimeStampedValue<NitzData> nitzSignal) { return mTimeZoneLookupHelper.countryUsesUtc( isoCountryCode, nitzSignal.mValue.getCurrentTimeInMillis()); } /** * Informs the {@link NitzStateMachine} that the network has become available. */ Loading Loading @@ -392,33 +409,23 @@ public class NitzStateMachine { // based only on the NITZ parameters. zoneId = mTimeZoneLookupHelper.guessZoneIdByNitz(newNitzData); if (DBG) { Rlog.d(LOG_TAG, "setTimeZoneFromNitz(): findByNitz returned " + zoneId); Rlog.d(LOG_TAG, "handleTimeZoneFromNitz: guessZoneIdByNitz returned" + " zoneId=" + zoneId); } } } int previousUtcOffset; boolean previousIsDst; if (mNitzData == null) { // No previously saved NITZ data. Use the same defaults as Android would have done // before it was possible to detect this case. previousUtcOffset = 0; previousIsDst = false; } else { previousUtcOffset = mNitzData.getLocalOffsetMillis(); previousIsDst = mNitzData.isDst(); } if ((zoneId == null) || (newNitzData.getLocalOffsetMillis() != previousUtcOffset) || (newNitzData.isDst() != previousIsDst)) { // We got the time before the country or the zone has changed || 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; mNitzData = newNitzData; mLatestNitzSignal = nitzSignal; } String tmpLog = "NITZ: nitzTimeSignal=" + nitzSignal String tmpLog = "handleTimeZoneFromNitz: nitzTimeSignal=" + nitzSignal + " zoneId=" + zoneId + " iso=" + iso + " mGotCountryCode=" + mGotCountryCode + " mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz Loading @@ -437,16 +444,23 @@ public class NitzStateMachine { saveNitzTimeZone(zoneId); } } catch (RuntimeException ex) { Rlog.e(LOG_TAG, "NITZ: Processing NITZ data " + nitzSignal + " ex=" + 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> nitzTimeSignal) { try { boolean ignoreNitz = mDeviceState.getIgnoreNitz(); if (ignoreNitz) { Rlog.d(LOG_TAG, "setTimeFromNitz: Not setting clock because gsm.ignore-nitz is set"); "handleTimeFromNitz: Not setting clock because gsm.ignore-nitz is set"); return; } Loading @@ -460,7 +474,7 @@ public class NitzStateMachine { long millisSinceNitzReceived = elapsedRealtime - nitzTimeSignal.mElapsedRealtime; if (millisSinceNitzReceived < 0 || millisSinceNitzReceived > Integer.MAX_VALUE) { if (DBG) { Rlog.d(LOG_TAG, "setTimeFromNitz: not setting time, unexpected" Rlog.d(LOG_TAG, "handleTimeFromNitz: not setting time, unexpected" + " elapsedRealtime=" + elapsedRealtime + " nitzTimeSignal=" + nitzTimeSignal); } Loading @@ -473,7 +487,7 @@ public class NitzStateMachine { long gained = adjustedCurrentTimeMillis - mDeviceState.currentTimeMillis(); if (mTimeServiceHelper.isTimeDetectionEnabled()) { String logMsg = "(setTimeFromNitz)" String logMsg = "handleTimeFromNitz:" + " nitzTimeSignal=" + nitzTimeSignal + " adjustedCurrentTimeMillis=" + adjustedCurrentTimeMillis + " millisSinceNitzReceived= " + millisSinceNitzReceived Loading Loading @@ -517,7 +531,8 @@ public class NitzStateMachine { mWakeLock.release(); } } catch (RuntimeException ex) { Rlog.e(LOG_TAG, "setTimeFromNitz: Processing NITZ data " + nitzTimeSignal Rlog.e(LOG_TAG, "handleTimeFromNitz: Processing NITZ data" + " nitzTimeSignal=" + nitzTimeSignal + " ex=" + ex); } } Loading @@ -533,17 +548,18 @@ public class NitzStateMachine { mTimeServiceHelper.setDeviceTimeZone(zoneId); if (DBG) { Rlog.d(LOG_TAG, "setAndBroadcastNetworkSetTimeZone: call alarm.setTimeZone and broadcast" "setAndBroadcastNetworkSetTimeZone: called setDeviceTimeZone()" + " zoneId=" + zoneId); } } private void setAndBroadcastNetworkSetTime(String msg, long time) { if (!mWakeLock.isHeld()) { Rlog.w(LOG_TAG, "Wake lock not held while setting device time (msg=" + msg + ")"); Rlog.w(LOG_TAG, "setAndBroadcastNetworkSetTime: Wake lock not held while setting device" + " time (msg=" + msg + ")"); } msg = "setAndBroadcastNetworkSetTime: [setting time to time=" + time + "]:" + msg; msg = "setAndBroadcastNetworkSetTime: [Setting time to time=" + time + "]:" + msg; if (DBG) { Rlog.d(LOG_TAG, msg); } Loading @@ -554,7 +570,8 @@ public class NitzStateMachine { private void handleAutoTimeEnabled() { if (DBG) { Rlog.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedNitzTime); Rlog.d(LOG_TAG, "handleAutoTimeEnabled: Reverting to NITZ Time:" + " mSavedNitzTime=" + mSavedNitzTime); } if (mSavedNitzTime != null) { try { Loading @@ -562,7 +579,8 @@ public class NitzStateMachine { mWakeLock.acquire(); long elapsedRealtime = mDeviceState.elapsedRealtime(); String msg = "Reverting to NITZ time, elapsedRealtime=" + elapsedRealtime String msg = "mSavedNitzTime: Reverting to NITZ time" + " elapsedRealtime=" + elapsedRealtime + " mSavedNitzTime=" + mSavedNitzTime; long adjustedCurrentTimeMillis = mSavedNitzTime.mValue + (elapsedRealtime - mSavedNitzTime.mElapsedRealtime); Loading @@ -574,7 +592,8 @@ public class NitzStateMachine { } private void handleAutoTimeZoneEnabled() { String tmpLog = "Reverting to NITZ TimeZone: tz=" + mSavedTimeZoneId; String tmpLog = "handleAutoTimeZoneEnabled: Reverting to NITZ TimeZone:" + " mSavedTimeZoneId=" + mSavedTimeZoneId; if (DBG) { Rlog.d(LOG_TAG, tmpLog); } Loading @@ -598,7 +617,7 @@ public class NitzStateMachine { // Time Zone Detection State pw.println(" mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz); pw.println(" mNitzData=" + mNitzData); pw.println(" mLatestNitzSignal=" + mLatestNitzSignal); pw.println(" mGotCountryCode=" + mGotCountryCode); pw.println(" mSavedTimeZone=" + mSavedTimeZoneId); pw.println(" mNitzTimeZoneDetectionSuccessful=" + mNitzTimeZoneDetectionSuccessful); Loading Loading @@ -633,19 +652,17 @@ public class NitzStateMachine { String zoneId = mTimeZoneLookupHelper.guessZoneIdByCountry( iso, mDeviceState.currentTimeMillis()); if (zoneId != null) { String logMsg = "updateTimeZoneByNetworkCountryCode: set time" + " zoneId=" + zoneId + " iso=" + iso; if (DBG) { Rlog.d(LOG_TAG, "updateTimeZoneByNetworkCountryCode: set time zone=" + zoneId + " iso=" + iso); Rlog.d(LOG_TAG, logMsg); } mTimeZoneLog.log("updateTimeZoneByNetworkCountryCode: set time zone=" + zoneId + " iso=" + iso); mTimeZoneLog.log(logMsg); setAndBroadcastNetworkSetTimeZone(zoneId); } else { if (DBG) { Rlog.d(LOG_TAG, "updateTimeZoneByNetworkCountryCode: no good zone for iso-cc='" + iso + "', do nothing"); Rlog.d(LOG_TAG, "updateTimeZoneByNetworkCountryCode: no good zone for iso=" + iso); } } } Loading @@ -661,7 +678,7 @@ public class NitzStateMachine { * Returns the last NITZ data that was cached. */ public NitzData getCachedNitzData() { return mNitzData; return mLatestNitzSignal != null ? mLatestNitzSignal.mValue : null; } /** Loading
src/java/com/android/internal/telephony/TimeZoneLookupHelper.java +13 −33 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package com.android.internal.telephony; import android.text.TextUtils; import android.util.TimeUtils; import libcore.util.CountryTimeZones; import libcore.util.TimeZoneFinder; import java.util.Arrays; import java.util.Date; import java.util.TimeZone; Loading @@ -32,35 +32,6 @@ import java.util.TimeZone; public class TimeZoneLookupHelper { private static final int MS_PER_HOUR = 60 * 60 * 1000; /** * List of ISO codes for countries that can have an offset of * GMT+0 when not in daylight savings time. This ignores some * small places such as the Canary Islands (Spain) and * Danmarkshavn (Denmark). The list must be sorted by code. */ private static final String[] GMT_COUNTRY_CODES = { "bf", // Burkina Faso "ci", // Cote d'Ivoire "eh", // Western Sahara "fo", // Faroe Islands, Denmark "gb", // United Kingdom of Great Britain and Northern Ireland "gh", // Ghana "gm", // Gambia "gn", // Guinea "gw", // Guinea Bissau "ie", // Ireland "lr", // Liberia "is", // Iceland "ma", // Morocco "ml", // Mali "mr", // Mauritania "pt", // Portugal "sl", // Sierra Leone "sn", // Senegal "st", // Sao Tome and Principe "tg", // Togo }; public TimeZoneLookupHelper() {} /** Loading Loading @@ -165,9 +136,18 @@ public class TimeZoneLookupHelper { /** * Returns {@code true} if the supplied (lower-case) ISO country code is for a country known to * use a raw offset of zero from UTC. * use a raw offset of zero from UTC at the time specified. */ public boolean countryUsesUtc(String isoCountryCode) { return Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode) >= 0; public boolean countryUsesUtc(String isoCountryCode, long whenMillis) { if (TextUtils.isEmpty(isoCountryCode)) { return false; } CountryTimeZones countryTimeZones = TimeZoneFinder.getInstance().lookupCountryTimeZones(isoCountryCode); if (countryTimeZones == null) { return false; } return countryTimeZones.hasUtcZone(whenMillis); } }
tests/telephonytests/src/com/android/internal/telephony/TimeZoneLookupHelperTest.java +15 −12 File changed.Preview size limit exceeded, changes collapsed. Show changes