Loading src/java/com/android/internal/telephony/MccTable.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -357,11 +357,11 @@ public final class MccTable { * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA) * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA) */ */ private static void setTimezoneFromMccIfNeeded(Context context, int mcc) { private static void setTimezoneFromMccIfNeeded(Context context, int mcc) { if (!TimeServiceHelper.isTimeZoneSettingInitializedStatic()) { if (!TimeServiceHelperImpl.isTimeZoneSettingInitializedStatic()) { String zoneId = defaultTimeZoneForMcc(mcc); String zoneId = defaultTimeZoneForMcc(mcc); if (zoneId != null && zoneId.length() > 0) { if (zoneId != null && zoneId.length() > 0) { // Set time zone based on MCC // Set time zone based on MCC TimeServiceHelper.setDeviceTimeZoneStatic(context, zoneId); TimeServiceHelperImpl.setDeviceTimeZoneStatic(context, zoneId); Slog.d(LOG_TAG, "timezone set to " + zoneId); Slog.d(LOG_TAG, "timezone set to " + zoneId); } } } } Loading src/java/com/android/internal/telephony/NitzStateMachine.java +44 −19 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,9 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; /** /** * An interface for the Android component that handles NITZ and related signals for time and time * zone detection. * * {@hide} * {@hide} */ */ public interface NitzStateMachine { public interface NitzStateMachine { Loading Loading @@ -87,11 +90,42 @@ public interface NitzStateMachine { String getSavedTimeZoneId(); String getSavedTimeZoneId(); /** /** * A proxy over device state that allows things like system properties, system clock * A proxy over read-only device state that allows things like system properties, elapsed * to be faked for tests. * realtime clock to be faked for tests. */ interface DeviceState { /** * If time between NITZ updates is less than {@link #getNitzUpdateSpacingMillis()} the * update may be ignored. */ int getNitzUpdateSpacingMillis(); /** * If {@link #getNitzUpdateSpacingMillis()} hasn't been exceeded but update is > * {@link #getNitzUpdateDiffMillis()} do the update */ int getNitzUpdateDiffMillis(); /** * Returns true if the {@code gsm.ignore-nitz} system property is set to "yes". */ boolean getIgnoreNitz(); String getNetworkCountryIsoForPhone(); /** * Returns the same value as {@link SystemClock#elapsedRealtime()}. */ long elapsedRealtime(); } /** * The real implementation of {@link DeviceState}. * * {@hide} */ */ // Non-final to allow mocking. class DeviceStateImpl implements DeviceState { class DeviceState { private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; private final int mNitzUpdateSpacing; private final int mNitzUpdateSpacing; Loading @@ -102,7 +136,7 @@ public interface NitzStateMachine { private final TelephonyManager mTelephonyManager; private final TelephonyManager mTelephonyManager; private final ContentResolver mCr; private final ContentResolver mCr; public DeviceState(GsmCdmaPhone phone) { DeviceStateImpl(GsmCdmaPhone phone) { mPhone = phone; mPhone = phone; Context context = phone.getContext(); Context context = phone.getContext(); Loading @@ -115,38 +149,29 @@ public interface NitzStateMachine { SystemProperties.getInt("ro.nitz_update_diff", NITZ_UPDATE_DIFF_DEFAULT); SystemProperties.getInt("ro.nitz_update_diff", NITZ_UPDATE_DIFF_DEFAULT); } } /** @Override * If time between NITZ updates is less than {@link #getNitzUpdateSpacingMillis()} the * update may be ignored. */ public int getNitzUpdateSpacingMillis() { public int getNitzUpdateSpacingMillis() { return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_SPACING, return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_SPACING, mNitzUpdateSpacing); mNitzUpdateSpacing); } } /** @Override * If {@link #getNitzUpdateSpacingMillis()} hasn't been exceeded but update is > * {@link #getNitzUpdateDiffMillis()} do the update */ public int getNitzUpdateDiffMillis() { public int getNitzUpdateDiffMillis() { return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_DIFF, mNitzUpdateDiff); return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_DIFF, mNitzUpdateDiff); } } /** @Override * Returns true if the {@code gsm.ignore-nitz} system property is set to "yes". */ public boolean getIgnoreNitz() { public boolean getIgnoreNitz() { String ignoreNitz = SystemProperties.get("gsm.ignore-nitz"); String ignoreNitz = SystemProperties.get("gsm.ignore-nitz"); return ignoreNitz != null && ignoreNitz.equals("yes"); return ignoreNitz != null && ignoreNitz.equals("yes"); } } @Override public String getNetworkCountryIsoForPhone() { public String getNetworkCountryIsoForPhone() { return mTelephonyManager.getNetworkCountryIsoForPhone(mPhone.getPhoneId()); return mTelephonyManager.getNetworkCountryIsoForPhone(mPhone.getPhoneId()); } } /** @Override * Returns the same value as {@link SystemClock#elapsedRealtime()}. */ public long elapsedRealtime() { public long elapsedRealtime() { return SystemClock.elapsedRealtime(); return SystemClock.elapsedRealtime(); } } Loading src/java/com/android/internal/telephony/NitzStateMachineImpl.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -100,8 +100,8 @@ public final class NitzStateMachineImpl implements NitzStateMachine { public NitzStateMachineImpl(GsmCdmaPhone phone) { public NitzStateMachineImpl(GsmCdmaPhone phone) { this(phone, this(phone, new TimeServiceHelper(phone.getContext()), new TimeServiceHelperImpl(phone.getContext()), new DeviceState(phone), new DeviceStateImpl(phone), new TimeZoneLookupHelper()); new TimeZoneLookupHelper()); } } Loading src/java/com/android/internal/telephony/TimeServiceHelper.java +8 −97 Original line number Original line Diff line number Diff line Loading @@ -16,97 +16,45 @@ package com.android.internal.telephony; package com.android.internal.telephony; import android.app.AlarmManager; import android.app.timedetector.TimeDetector; import android.app.timedetector.TimeDetector; import android.app.timedetector.TimeSignal; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.util.TimestampedValue; import android.util.TimestampedValue; /** /** * An interface to various time / time zone detection behaviors that should be centralized into a * An interface to various time / time zone detection behaviors that should be centralized into a * new service. * new service. */ */ // Non-final to allow mocking. public interface TimeServiceHelper { public class TimeServiceHelper { /** /** * Callback interface for automatic detection enable/disable changes. * Callback interface for automatic detection enable/disable changes. */ */ public interface Listener { interface Listener { /** /** * Automatic time zone detection has been enabled or disabled. * Automatic time zone detection has been enabled or disabled. */ */ void onTimeZoneDetectionChange(boolean enabled); void onTimeZoneDetectionChange(boolean enabled); } } private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; private final Context mContext; private final ContentResolver mCr; private final TimeDetector mTimeDetector; private Listener mListener; /** Creates a TimeServiceHelper */ public TimeServiceHelper(Context context) { mContext = context; mCr = context.getContentResolver(); mTimeDetector = context.getSystemService(TimeDetector.class); } /** /** * Sets a listener that will be called when the automatic time / time zone detection setting * Sets a listener that will be called when the automatic time / time zone detection setting * changes. * changes. */ */ public void setListener(Listener listener) { 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_ZONE), true, new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { listener.onTimeZoneDetectionChange(isTimeZoneDetectionEnabled()); } }); } /** /** * Returns the same value as {@link System#currentTimeMillis()}. * Returns the same value as {@link System#currentTimeMillis()}. */ */ public long currentTimeMillis() { long currentTimeMillis(); return System.currentTimeMillis(); } /** /** * Returns true if the device has an explicit time zone set. * Returns true if the device has an explicit time zone set. */ */ public boolean isTimeZoneSettingInitialized() { boolean isTimeZoneSettingInitialized(); return isTimeZoneSettingInitializedStatic(); } /** /** * Returns true if automatic time zone detection is enabled in settings. * Returns true if automatic time zone detection is enabled in settings. */ */ public boolean isTimeZoneDetectionEnabled() { boolean isTimeZoneDetectionEnabled(); try { return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0; } catch (Settings.SettingNotFoundException snfe) { return true; } } /** /** * Set the device time zone and send out a sticky broadcast so the system can * Set the device time zone and send out a sticky broadcast so the system can Loading @@ -114,50 +62,13 @@ public class TimeServiceHelper { * * * @param zoneId timezone set by carrier * @param zoneId timezone set by carrier */ */ public void setDeviceTimeZone(String zoneId) { void setDeviceTimeZone(String zoneId); setDeviceTimeZoneStatic(mContext, zoneId); } /** /** * Suggest the time to the {@link TimeDetector}. * Suggest the time to the {@link TimeDetector}. * * * @param signalTimeMillis the signal time as received from the network * @param signalTimeMillis the signal time as received from the network */ */ public void suggestDeviceTime(TimestampedValue<Long> signalTimeMillis) { void suggestDeviceTime(TimestampedValue<Long> signalTimeMillis); TimeSignal timeSignal = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, signalTimeMillis); mTimeDetector.suggestTime(timeSignal); } /** * Static implementation of isTimeZoneSettingInitialized() for use from {@link MccTable}. This * is a hack to deflake TelephonyTests when running on a device with a real SIM: in that * situation real service events may come in while a TelephonyTest is running, leading to flakes * as the real / fake instance of TimeServiceHelper is swapped in and out from * {@link TelephonyComponentFactory}. */ static boolean isTimeZoneSettingInitializedStatic() { // timezone.equals("GMT") will be true and only true if the timezone was // set to a default value by the system server (when starting, system server // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by // any code that sets it explicitly (in case where something sets GMT explicitly, // "Etc/GMT" Olsen ID would be used). // TODO(b/64056758): Remove "timezone.equals("GMT")" hack when there's a // better way of telling if the value has been defaulted. String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY); return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT"); } /** * 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); } } } src/java/com/android/internal/telephony/TimeServiceHelperImpl.java 0 → 100644 +134 −0 Original line number Original line Diff line number Diff line /* * Copyright 2019 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 com.android.internal.telephony; import android.app.AlarmManager; import android.app.timedetector.TimeDetector; import android.app.timedetector.TimeSignal; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.util.TimestampedValue; /** * An interface to various time / time zone detection behaviors that should be centralized into a * new service. */ public final class TimeServiceHelperImpl implements TimeServiceHelper { private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; private final Context mContext; private final ContentResolver mCr; private final TimeDetector mTimeDetector; private Listener mListener; /** Creates a TimeServiceHelper */ public TimeServiceHelperImpl(Context context) { mContext = context; mCr = context.getContentResolver(); mTimeDetector = context.getSystemService(TimeDetector.class); } @Override 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_ZONE), true, new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { listener.onTimeZoneDetectionChange(isTimeZoneDetectionEnabled()); } }); } @Override public long currentTimeMillis() { return System.currentTimeMillis(); } @Override public boolean isTimeZoneSettingInitialized() { return isTimeZoneSettingInitializedStatic(); } @Override public boolean isTimeZoneDetectionEnabled() { try { return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0; } catch (Settings.SettingNotFoundException snfe) { return true; } } @Override public void setDeviceTimeZone(String zoneId) { setDeviceTimeZoneStatic(mContext, zoneId); } @Override public void suggestDeviceTime(TimestampedValue<Long> signalTimeMillis) { TimeSignal timeSignal = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, signalTimeMillis); mTimeDetector.suggestTime(timeSignal); } /** * Static implementation of isTimeZoneSettingInitialized() for use from {@link MccTable}. This * is a hack to deflake TelephonyTests when running on a device with a real SIM: in that * situation real service events may come in while a TelephonyTest is running, leading to flakes * as the real / fake instance of TimeServiceHelper is swapped in and out from * {@link TelephonyComponentFactory}. */ static boolean isTimeZoneSettingInitializedStatic() { // timezone.equals("GMT") will be true and only true if the timezone was // set to a default value by the system server (when starting, system server // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by // any code that sets it explicitly (in case where something sets GMT explicitly, // "Etc/GMT" Olsen ID would be used). // TODO(b/64056758): Remove "timezone.equals("GMT")" hack when there's a // better way of telling if the value has been defaulted. String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY); return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT"); } /** * 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); } } Loading
src/java/com/android/internal/telephony/MccTable.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -357,11 +357,11 @@ public final class MccTable { * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA) * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA) */ */ private static void setTimezoneFromMccIfNeeded(Context context, int mcc) { private static void setTimezoneFromMccIfNeeded(Context context, int mcc) { if (!TimeServiceHelper.isTimeZoneSettingInitializedStatic()) { if (!TimeServiceHelperImpl.isTimeZoneSettingInitializedStatic()) { String zoneId = defaultTimeZoneForMcc(mcc); String zoneId = defaultTimeZoneForMcc(mcc); if (zoneId != null && zoneId.length() > 0) { if (zoneId != null && zoneId.length() > 0) { // Set time zone based on MCC // Set time zone based on MCC TimeServiceHelper.setDeviceTimeZoneStatic(context, zoneId); TimeServiceHelperImpl.setDeviceTimeZoneStatic(context, zoneId); Slog.d(LOG_TAG, "timezone set to " + zoneId); Slog.d(LOG_TAG, "timezone set to " + zoneId); } } } } Loading
src/java/com/android/internal/telephony/NitzStateMachine.java +44 −19 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,9 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; /** /** * An interface for the Android component that handles NITZ and related signals for time and time * zone detection. * * {@hide} * {@hide} */ */ public interface NitzStateMachine { public interface NitzStateMachine { Loading Loading @@ -87,11 +90,42 @@ public interface NitzStateMachine { String getSavedTimeZoneId(); String getSavedTimeZoneId(); /** /** * A proxy over device state that allows things like system properties, system clock * A proxy over read-only device state that allows things like system properties, elapsed * to be faked for tests. * realtime clock to be faked for tests. */ interface DeviceState { /** * If time between NITZ updates is less than {@link #getNitzUpdateSpacingMillis()} the * update may be ignored. */ int getNitzUpdateSpacingMillis(); /** * If {@link #getNitzUpdateSpacingMillis()} hasn't been exceeded but update is > * {@link #getNitzUpdateDiffMillis()} do the update */ int getNitzUpdateDiffMillis(); /** * Returns true if the {@code gsm.ignore-nitz} system property is set to "yes". */ boolean getIgnoreNitz(); String getNetworkCountryIsoForPhone(); /** * Returns the same value as {@link SystemClock#elapsedRealtime()}. */ long elapsedRealtime(); } /** * The real implementation of {@link DeviceState}. * * {@hide} */ */ // Non-final to allow mocking. class DeviceStateImpl implements DeviceState { class DeviceState { private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; private final int mNitzUpdateSpacing; private final int mNitzUpdateSpacing; Loading @@ -102,7 +136,7 @@ public interface NitzStateMachine { private final TelephonyManager mTelephonyManager; private final TelephonyManager mTelephonyManager; private final ContentResolver mCr; private final ContentResolver mCr; public DeviceState(GsmCdmaPhone phone) { DeviceStateImpl(GsmCdmaPhone phone) { mPhone = phone; mPhone = phone; Context context = phone.getContext(); Context context = phone.getContext(); Loading @@ -115,38 +149,29 @@ public interface NitzStateMachine { SystemProperties.getInt("ro.nitz_update_diff", NITZ_UPDATE_DIFF_DEFAULT); SystemProperties.getInt("ro.nitz_update_diff", NITZ_UPDATE_DIFF_DEFAULT); } } /** @Override * If time between NITZ updates is less than {@link #getNitzUpdateSpacingMillis()} the * update may be ignored. */ public int getNitzUpdateSpacingMillis() { public int getNitzUpdateSpacingMillis() { return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_SPACING, return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_SPACING, mNitzUpdateSpacing); mNitzUpdateSpacing); } } /** @Override * If {@link #getNitzUpdateSpacingMillis()} hasn't been exceeded but update is > * {@link #getNitzUpdateDiffMillis()} do the update */ public int getNitzUpdateDiffMillis() { public int getNitzUpdateDiffMillis() { return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_DIFF, mNitzUpdateDiff); return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_DIFF, mNitzUpdateDiff); } } /** @Override * Returns true if the {@code gsm.ignore-nitz} system property is set to "yes". */ public boolean getIgnoreNitz() { public boolean getIgnoreNitz() { String ignoreNitz = SystemProperties.get("gsm.ignore-nitz"); String ignoreNitz = SystemProperties.get("gsm.ignore-nitz"); return ignoreNitz != null && ignoreNitz.equals("yes"); return ignoreNitz != null && ignoreNitz.equals("yes"); } } @Override public String getNetworkCountryIsoForPhone() { public String getNetworkCountryIsoForPhone() { return mTelephonyManager.getNetworkCountryIsoForPhone(mPhone.getPhoneId()); return mTelephonyManager.getNetworkCountryIsoForPhone(mPhone.getPhoneId()); } } /** @Override * Returns the same value as {@link SystemClock#elapsedRealtime()}. */ public long elapsedRealtime() { public long elapsedRealtime() { return SystemClock.elapsedRealtime(); return SystemClock.elapsedRealtime(); } } Loading
src/java/com/android/internal/telephony/NitzStateMachineImpl.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -100,8 +100,8 @@ public final class NitzStateMachineImpl implements NitzStateMachine { public NitzStateMachineImpl(GsmCdmaPhone phone) { public NitzStateMachineImpl(GsmCdmaPhone phone) { this(phone, this(phone, new TimeServiceHelper(phone.getContext()), new TimeServiceHelperImpl(phone.getContext()), new DeviceState(phone), new DeviceStateImpl(phone), new TimeZoneLookupHelper()); new TimeZoneLookupHelper()); } } Loading
src/java/com/android/internal/telephony/TimeServiceHelper.java +8 −97 Original line number Original line Diff line number Diff line Loading @@ -16,97 +16,45 @@ package com.android.internal.telephony; package com.android.internal.telephony; import android.app.AlarmManager; import android.app.timedetector.TimeDetector; import android.app.timedetector.TimeDetector; import android.app.timedetector.TimeSignal; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.util.TimestampedValue; import android.util.TimestampedValue; /** /** * An interface to various time / time zone detection behaviors that should be centralized into a * An interface to various time / time zone detection behaviors that should be centralized into a * new service. * new service. */ */ // Non-final to allow mocking. public interface TimeServiceHelper { public class TimeServiceHelper { /** /** * Callback interface for automatic detection enable/disable changes. * Callback interface for automatic detection enable/disable changes. */ */ public interface Listener { interface Listener { /** /** * Automatic time zone detection has been enabled or disabled. * Automatic time zone detection has been enabled or disabled. */ */ void onTimeZoneDetectionChange(boolean enabled); void onTimeZoneDetectionChange(boolean enabled); } } private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; private final Context mContext; private final ContentResolver mCr; private final TimeDetector mTimeDetector; private Listener mListener; /** Creates a TimeServiceHelper */ public TimeServiceHelper(Context context) { mContext = context; mCr = context.getContentResolver(); mTimeDetector = context.getSystemService(TimeDetector.class); } /** /** * Sets a listener that will be called when the automatic time / time zone detection setting * Sets a listener that will be called when the automatic time / time zone detection setting * changes. * changes. */ */ public void setListener(Listener listener) { 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_ZONE), true, new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { listener.onTimeZoneDetectionChange(isTimeZoneDetectionEnabled()); } }); } /** /** * Returns the same value as {@link System#currentTimeMillis()}. * Returns the same value as {@link System#currentTimeMillis()}. */ */ public long currentTimeMillis() { long currentTimeMillis(); return System.currentTimeMillis(); } /** /** * Returns true if the device has an explicit time zone set. * Returns true if the device has an explicit time zone set. */ */ public boolean isTimeZoneSettingInitialized() { boolean isTimeZoneSettingInitialized(); return isTimeZoneSettingInitializedStatic(); } /** /** * Returns true if automatic time zone detection is enabled in settings. * Returns true if automatic time zone detection is enabled in settings. */ */ public boolean isTimeZoneDetectionEnabled() { boolean isTimeZoneDetectionEnabled(); try { return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0; } catch (Settings.SettingNotFoundException snfe) { return true; } } /** /** * Set the device time zone and send out a sticky broadcast so the system can * Set the device time zone and send out a sticky broadcast so the system can Loading @@ -114,50 +62,13 @@ public class TimeServiceHelper { * * * @param zoneId timezone set by carrier * @param zoneId timezone set by carrier */ */ public void setDeviceTimeZone(String zoneId) { void setDeviceTimeZone(String zoneId); setDeviceTimeZoneStatic(mContext, zoneId); } /** /** * Suggest the time to the {@link TimeDetector}. * Suggest the time to the {@link TimeDetector}. * * * @param signalTimeMillis the signal time as received from the network * @param signalTimeMillis the signal time as received from the network */ */ public void suggestDeviceTime(TimestampedValue<Long> signalTimeMillis) { void suggestDeviceTime(TimestampedValue<Long> signalTimeMillis); TimeSignal timeSignal = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, signalTimeMillis); mTimeDetector.suggestTime(timeSignal); } /** * Static implementation of isTimeZoneSettingInitialized() for use from {@link MccTable}. This * is a hack to deflake TelephonyTests when running on a device with a real SIM: in that * situation real service events may come in while a TelephonyTest is running, leading to flakes * as the real / fake instance of TimeServiceHelper is swapped in and out from * {@link TelephonyComponentFactory}. */ static boolean isTimeZoneSettingInitializedStatic() { // timezone.equals("GMT") will be true and only true if the timezone was // set to a default value by the system server (when starting, system server // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by // any code that sets it explicitly (in case where something sets GMT explicitly, // "Etc/GMT" Olsen ID would be used). // TODO(b/64056758): Remove "timezone.equals("GMT")" hack when there's a // better way of telling if the value has been defaulted. String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY); return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT"); } /** * 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); } } }
src/java/com/android/internal/telephony/TimeServiceHelperImpl.java 0 → 100644 +134 −0 Original line number Original line Diff line number Diff line /* * Copyright 2019 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 com.android.internal.telephony; import android.app.AlarmManager; import android.app.timedetector.TimeDetector; import android.app.timedetector.TimeSignal; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.util.TimestampedValue; /** * An interface to various time / time zone detection behaviors that should be centralized into a * new service. */ public final class TimeServiceHelperImpl implements TimeServiceHelper { private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; private final Context mContext; private final ContentResolver mCr; private final TimeDetector mTimeDetector; private Listener mListener; /** Creates a TimeServiceHelper */ public TimeServiceHelperImpl(Context context) { mContext = context; mCr = context.getContentResolver(); mTimeDetector = context.getSystemService(TimeDetector.class); } @Override 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_ZONE), true, new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { listener.onTimeZoneDetectionChange(isTimeZoneDetectionEnabled()); } }); } @Override public long currentTimeMillis() { return System.currentTimeMillis(); } @Override public boolean isTimeZoneSettingInitialized() { return isTimeZoneSettingInitializedStatic(); } @Override public boolean isTimeZoneDetectionEnabled() { try { return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0; } catch (Settings.SettingNotFoundException snfe) { return true; } } @Override public void setDeviceTimeZone(String zoneId) { setDeviceTimeZoneStatic(mContext, zoneId); } @Override public void suggestDeviceTime(TimestampedValue<Long> signalTimeMillis) { TimeSignal timeSignal = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, signalTimeMillis); mTimeDetector.suggestTime(timeSignal); } /** * Static implementation of isTimeZoneSettingInitialized() for use from {@link MccTable}. This * is a hack to deflake TelephonyTests when running on a device with a real SIM: in that * situation real service events may come in while a TelephonyTest is running, leading to flakes * as the real / fake instance of TimeServiceHelper is swapped in and out from * {@link TelephonyComponentFactory}. */ static boolean isTimeZoneSettingInitializedStatic() { // timezone.equals("GMT") will be true and only true if the timezone was // set to a default value by the system server (when starting, system server // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by // any code that sets it explicitly (in case where something sets GMT explicitly, // "Etc/GMT" Olsen ID would be used). // TODO(b/64056758): Remove "timezone.equals("GMT")" hack when there's a // better way of telling if the value has been defaulted. String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY); return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT"); } /** * 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); } }