1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.tv.settings.system;
18 
19 import static com.android.tv.settings.util.InstrumentationUtils.logEntrySelected;
20 import static com.android.tv.settings.util.InstrumentationUtils.logToggleInteracted;
21 
22 import android.app.Activity;
23 import android.app.tvsettings.TvSettingsEnums;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.os.Bundle;
29 import android.os.SystemProperties;
30 import android.os.UserManager;
31 import android.provider.Settings;
32 import android.text.TextUtils;
33 import android.text.format.DateFormat;
34 
35 import androidx.annotation.Keep;
36 import androidx.preference.ListPreference;
37 import androidx.preference.Preference;
38 import androidx.preference.SwitchPreference;
39 
40 import com.android.settingslib.datetime.ZoneGetter;
41 import com.android.tv.settings.R;
42 import com.android.tv.settings.RestrictedPreferenceAdapter;
43 import com.android.tv.settings.SettingsPreferenceFragment;
44 
45 import java.util.Calendar;
46 import java.util.Date;
47 
48 /**
49  * The date and time screen in TV settings.
50  */
51 @Keep
52 public class DateTimeFragment extends SettingsPreferenceFragment implements
53         Preference.OnPreferenceChangeListener {
54 
55     private static final String KEY_AUTO_DATE_TIME = "auto_date_time";
56     private static final String KEY_SET_DATE = "set_date";
57     private static final String KEY_SET_TIME = "set_time";
58     private static final String KEY_SET_TIME_ZONE = "set_time_zone";
59     private static final String KEY_USE_24_HOUR = "use_24_hour";
60 
61     private static final String AUTO_DATE_TIME_NTP = "network";
62     private static final String AUTO_DATE_TIME_TS = "transport_stream";
63     private static final String AUTO_DATE_TIME_OFF = "off";
64 
65     private static final String HOURS_12 = "12";
66     private static final String HOURS_24 = "24";
67 
68     //    private TvInputManager mTvInputManager;
69     private final Calendar mDummyDate = Calendar.getInstance();
70 
71     private RestrictedPreferenceAdapter<Preference> mDatePref;
72     private RestrictedPreferenceAdapter<Preference> mTimePref;
73     private RestrictedPreferenceAdapter<Preference> mTimeZone;
74     private Preference mTime24Pref;
75 
76     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
77         @Override
78         public void onReceive(Context context, Intent intent) {
79             final Activity activity = getActivity();
80             if (activity != null) {
81                 updateTimeAndDateDisplay(activity);
82             }
83         }
84     };
85 
newInstance()86     public static DateTimeFragment newInstance() {
87         return new DateTimeFragment();
88     }
89 
90     @Override
onCreate(Bundle savedInstanceState)91     public void onCreate(Bundle savedInstanceState) {
92 //        mTvInputManager =
93 //                (TvInputManager) getActivity().getSystemService(Context.TV_INPUT_SERVICE);
94         super.onCreate(savedInstanceState);
95     }
96 
97     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)98     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
99         setPreferencesFromResource(R.xml.date_time, null);
100 
101         final boolean isRestricted = SecurityFragment.isRestrictedProfileInEffect(getContext());
102 
103         Preference datePref = findPreference(KEY_SET_DATE);
104         datePref.setVisible(!isRestricted);
105 
106         Preference timePref = findPreference(KEY_SET_TIME);
107         timePref.setVisible(!isRestricted);
108 
109         final boolean tsTimeCapable = SystemProperties.getBoolean("ro.config.ts.date.time", false);
110         final ListPreference autoDateTimePref =
111                 (ListPreference) findPreference(KEY_AUTO_DATE_TIME);
112         autoDateTimePref.setValue(getAutoDateTimeState());
113         autoDateTimePref.setOnPreferenceChangeListener(this);
114         if (tsTimeCapable) {
115             autoDateTimePref.setEntries(R.array.auto_date_time_ts_entries);
116             autoDateTimePref.setEntryValues(R.array.auto_date_time_ts_entry_values);
117         }
118         autoDateTimePref.setVisible(!isRestricted);
119 
120         Preference timeZonePref = findPreference(KEY_SET_TIME_ZONE);
121         timeZonePref.setVisible(!isRestricted);
122 
123         mTime24Pref = findPreference(KEY_USE_24_HOUR);
124         mTime24Pref.setOnPreferenceChangeListener(this);
125 
126         final String userRestriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
127         mDatePref = RestrictedPreferenceAdapter.adapt(datePref, userRestriction);
128         mTimePref = RestrictedPreferenceAdapter.adapt(timePref, userRestriction);
129         mTimeZone = RestrictedPreferenceAdapter.adapt(timeZonePref, userRestriction);
130         RestrictedPreferenceAdapter.adapt(autoDateTimePref, userRestriction);
131     }
132 
133     @Override
onResume()134     public void onResume() {
135         super.onResume();
136 
137         ((SwitchPreference)mTime24Pref).setChecked(is24Hour());
138 
139         // Register for time ticks and other reasons for time change
140         IntentFilter filter = new IntentFilter();
141         filter.addAction(Intent.ACTION_TIME_TICK);
142         filter.addAction(Intent.ACTION_TIME_CHANGED);
143         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
144         getActivity().registerReceiver(mIntentReceiver, filter, null, null);
145 
146         updateTimeAndDateDisplay(getActivity());
147         updateTimeDateEnable();
148     }
149 
150     @Override
onPause()151     public void onPause() {
152         super.onPause();
153         getActivity().unregisterReceiver(mIntentReceiver);
154     }
155 
updateTimeAndDateDisplay(Context context)156     private void updateTimeAndDateDisplay(Context context) {
157         final Calendar now = Calendar.getInstance();
158         mDummyDate.setTimeZone(now.getTimeZone());
159         // We use December 31st because it's unambiguous when demonstrating the date format.
160         // We use 13:00 so we can demonstrate the 12/24 hour options.
161         mDummyDate.set(now.get(Calendar.YEAR), 11, 31, 13, 0, 0);
162         Date dummyDate = mDummyDate.getTime();
163 
164         mDatePref.updatePreference(pref ->
165                 pref.setSummary(DateFormat.getLongDateFormat(context).format(now.getTime())));
166         mTimePref.updatePreference(pref ->
167                 pref.setSummary(DateFormat.getTimeFormat(getActivity()).format(now.getTime())));
168         mTimeZone.updatePreference(pref ->
169                 pref.setSummary(ZoneGetter.getTimeZoneOffsetAndName(getActivity(),
170                         now.getTimeZone(), now.getTime())));
171 
172         mTime24Pref.setSummary(DateFormat.getTimeFormat(getActivity()).format(dummyDate));
173     }
174 
updateTimeDateEnable()175     private void updateTimeDateEnable() {
176         final boolean enable = TextUtils.equals(getAutoDateTimeState(), AUTO_DATE_TIME_OFF);
177 
178         mDatePref.updatePreference(pref -> pref.setEnabled(enable));
179         mTimePref.updatePreference(pref -> pref.setEnabled(enable));
180     }
181 
182     @Override
onPreferenceChange(Preference preference, Object newValue)183     public boolean onPreferenceChange(Preference preference, Object newValue) {
184         if (TextUtils.equals(preference.getKey(), KEY_AUTO_DATE_TIME)) {
185             String value = (String) newValue;
186             if (TextUtils.equals(value, AUTO_DATE_TIME_NTP)) {
187                 logEntrySelected(TvSettingsEnums.SYSTEM_DATE_TIME_AUTOMATIC_USE_NETWORK_TIME);
188                 setAutoDateTime(true);
189             } else if (TextUtils.equals(value, AUTO_DATE_TIME_TS)) {
190                 throw new IllegalStateException("TS date is not yet implemented");
191 //                mTvInputManager.syncTimefromBroadcast(true);
192 //                setAutoDateTime(false);
193             } else if (TextUtils.equals(value, AUTO_DATE_TIME_OFF)) {
194                 logEntrySelected(TvSettingsEnums.SYSTEM_DATE_TIME_AUTOMATIC_OFF);
195                 setAutoDateTime(false);
196             } else {
197                 throw new IllegalArgumentException("Unknown auto time value " + value);
198             }
199             updateTimeDateEnable();
200         } else if (TextUtils.equals(preference.getKey(), KEY_USE_24_HOUR)) {
201             final boolean use24Hour = (Boolean) newValue;
202             logToggleInteracted(TvSettingsEnums.SYSTEM_DATE_TIME_USE_24_HOUR_FORMAT, use24Hour);
203             set24Hour(use24Hour);
204             timeUpdated(use24Hour);
205         }
206         return true;
207     }
208 
209     @Override
onPreferenceTreeClick(Preference preference)210     public boolean onPreferenceTreeClick(Preference preference) {
211         switch (preference.getKey()) {
212             case KEY_SET_DATE:
213                 logEntrySelected(TvSettingsEnums.SYSTEM_DATE_TIME_SET_DATE);
214                 break;
215             case KEY_SET_TIME:
216                 logEntrySelected(TvSettingsEnums.SYSTEM_DATE_TIME_SET_TIME);
217                 break;
218         }
219         return super.onPreferenceTreeClick(preference);
220     }
221 
222     /*  Get & Set values from the system settings  */
223 
is24Hour()224     private boolean is24Hour() {
225         return DateFormat.is24HourFormat(getActivity());
226     }
227 
timeUpdated(boolean use24Hour)228     private void timeUpdated(boolean use24Hour) {
229         Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED);
230         int timeFormatPreference =
231                 use24Hour ? Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR
232                         : Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR;
233         timeChanged.putExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, timeFormatPreference);
234         getContext().sendBroadcast(timeChanged);
235     }
236 
set24Hour(boolean use24Hour)237     private void set24Hour(boolean use24Hour) {
238         Settings.System.putString(getContext().getContentResolver(),
239                 Settings.System.TIME_12_24,
240                 use24Hour ? HOURS_24 : HOURS_12);
241     }
242 
setAutoDateTime(boolean on)243     private void setAutoDateTime(boolean on) {
244         Settings.Global.putInt(getContext().getContentResolver(),
245                 Settings.Global.AUTO_TIME, on ? 1 : 0);
246     }
247 
getAutoDateTimeState()248     private String getAutoDateTimeState() {
249 //        if(mTvInputManager.isUseBroadcastDateTime()) {
250 //            return AUTO_DATE_TIME_TS;
251 //        }
252 
253         int value = Settings.Global.getInt(getContext().getContentResolver(),
254                 Settings.Global.AUTO_TIME, 0);
255         if(value > 0) {
256             return AUTO_DATE_TIME_NTP;
257         }
258 
259         return AUTO_DATE_TIME_OFF;
260     }
261 
262     @Override
getPageId()263     protected int getPageId() {
264         return TvSettingsEnums.SYSTEM_DATE_TIME;
265     }
266 }
267