1f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller/* 2f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Copyright 2017 The Android Open Source Project 3f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * 4f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 5f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * you may not use this file except in compliance with the License. 6f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * You may obtain a copy of the License at 7f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * 8f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * http://www.apache.org/licenses/LICENSE-2.0 9f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * 10f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Unless required by applicable law or agreed to in writing, software 11f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 12f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * See the License for the specific language governing permissions and 14f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * limitations under the License. 15f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 16f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 17f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerpackage com.android.internal.telephony; 18f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 19f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.app.AlarmManager; 20f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.content.ContentResolver; 21f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.content.Context; 22f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.content.Intent; 23f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.database.ContentObserver; 24f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.os.Handler; 25f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.os.SystemClock; 26f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.os.SystemProperties; 27f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.os.UserHandle; 28f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerimport android.provider.Settings; 29f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 30f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller/** 31f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * An interface to various time / time zone detection behaviors that should be centralized into a 32f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * new service. 33f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 34f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller// Non-final to allow mocking. 35f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fullerpublic class TimeServiceHelper { 36f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 37f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 38f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Callback interface for automatic detection enable/disable changes. 39f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 40f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public interface Listener { 41f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 42f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Automatic time detection has been enabled or disabled. 43f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 44f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller void onTimeDetectionChange(boolean enabled); 45f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 46f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 47f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Automatic time zone detection has been enabled or disabled. 48f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 49f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller void onTimeZoneDetectionChange(boolean enabled); 50f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 51f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 5292a32ccfd8f20d8cf3dee618e730fa73315331e4Neil Fuller private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; 53f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 54f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller private final Context mContext; 55f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller private final ContentResolver mCr; 56f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 57f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller private Listener mListener; 58f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 59f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** Creates a TimeServiceHelper */ 60f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public TimeServiceHelper(Context context) { 61f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller mContext = context; 62f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller mCr = context.getContentResolver(); 63f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 64f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 65f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 66f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Sets a listener that will be called when the automatic time / time zone detection setting 67f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * changes. 68f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 69f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public void setListener(Listener listener) { 70f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller if (listener == null) { 71f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller throw new NullPointerException("listener==null"); 72f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 73f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller if (mListener != null) { 74f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller throw new IllegalStateException("listener already set"); 75f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 76f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller this.mListener = listener; 77f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller mCr.registerContentObserver( 78f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true, 79f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller new ContentObserver(new Handler()) { 80f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public void onChange(boolean selfChange) { 81f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller listener.onTimeDetectionChange(isTimeDetectionEnabled()); 82f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 83f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller }); 84f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller mCr.registerContentObserver( 85f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true, 86f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller new ContentObserver(new Handler()) { 87f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public void onChange(boolean selfChange) { 88f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller listener.onTimeZoneDetectionChange(isTimeZoneDetectionEnabled()); 89f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 90f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller }); 91f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 92f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 93f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 947cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller * Returns the same value as {@link System#currentTimeMillis()}. 957cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller */ 967cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller public long currentTimeMillis() { 977cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller return System.currentTimeMillis(); 987cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller } 997cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller 1007cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller /** 1017cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller * Returns the same value as {@link SystemClock#elapsedRealtime()}. 1027cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller */ 1037cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller public long elapsedRealtime() { 1047cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller return SystemClock.elapsedRealtime(); 1057cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller } 1067cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller 1077cecf024c258ae234dcaf124cc32ed0e6d0d929eNeil Fuller /** 108f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Returns true if the device has an explicit time zone set. 109f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 110f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public boolean isTimeZoneSettingInitialized() { 111eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller return isTimeZoneSettingInitializedStatic(); 11292a32ccfd8f20d8cf3dee618e730fa73315331e4Neil Fuller 113f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 114f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 115f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 116f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Returns true if automatic time detection is enabled in settings. 117f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 118f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public boolean isTimeDetectionEnabled() { 119f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller try { 120f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME) > 0; 121f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } catch (Settings.SettingNotFoundException snfe) { 122f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller return true; 123f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 124f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 125f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 126f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 127f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Returns true if automatic time zone detection is enabled in settings. 128f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 129f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public boolean isTimeZoneDetectionEnabled() { 130f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller try { 131f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0; 132f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } catch (Settings.SettingNotFoundException snfe) { 133f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller return true; 134f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 135f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 136f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 137f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 138f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Set the device time zone and send out a sticky broadcast so the system can 139f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * determine if the timezone was set by the carrier. 140f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * 141f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * @param zoneId timezone set by carrier 142f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 143f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public void setDeviceTimeZone(String zoneId) { 144eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller setDeviceTimeZoneStatic(mContext, zoneId); 145f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 146f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller 147f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller /** 148f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * Set the time and Send out a sticky broadcast so the system can determine 149f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * if the time was set by the carrier. 150f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * 151f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller * @param time time set by network 152f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller */ 153f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller public void setDeviceTime(long time) { 154f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller SystemClock.setCurrentTimeMillis(time); 155f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME); 156f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 157f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller intent.putExtra("time", time); 158f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 159f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller } 160eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller 161eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller /** 162eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller * Static implementation of isTimeZoneSettingInitialized() for use from {@link MccTable}. This 163eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller * is a hack to deflake TelephonyTests when running on a device with a real SIM: in that 164eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller * situation real service events may come in while a TelephonyTest is running, leading to flakes 165eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller * as the real / fake instance of TimeServiceHelper is swapped in and out from 166eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller * {@link TelephonyComponentFactory}. 167eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller */ 168eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller static boolean isTimeZoneSettingInitializedStatic() { 169eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller // timezone.equals("GMT") will be true and only true if the timezone was 170eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller // set to a default value by the system server (when starting, system server 171eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by 172eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller // any code that sets it explicitly (in case where something sets GMT explicitly, 173eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller // "Etc/GMT" Olsen ID would be used). 174eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller // TODO(b/64056758): Remove "timezone.equals("GMT")" hack when there's a 175eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller // better way of telling if the value has been defaulted. 176eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller 177eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY); 178eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT"); 179eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller } 180eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller 181eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller /** 182eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller * Static method for use by MccTable. See {@link #isTimeZoneSettingInitializedStatic()} for 183eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller * explanation. 184eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller */ 185eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller static void setDeviceTimeZoneStatic(Context context, String zoneId) { 186eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 187eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller alarmManager.setTimeZone(zoneId); 188eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE); 189eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 190eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller intent.putExtra("time-zone", zoneId); 191eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller context.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 192eff964878d590a8a74837c48bbb0e4ff4ff8f28fNeil Fuller } 193f9e4314c7258d07ee1b995d625d20887d36c94daNeil Fuller} 194