diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java index 749a4ed403c..fc47fefe55b 100644 --- a/src/com/android/settings/DateTimeSettings.java +++ b/src/com/android/settings/DateTimeSettings.java @@ -17,208 +17,106 @@ package com.android.settings; import android.app.Activity; -import android.app.AlarmManager; -import android.app.DatePickerDialog; -import android.app.DatePickerDialog.OnDateSetListener; import android.app.Dialog; -import android.app.TimePickerDialog; -import android.app.TimePickerDialog.OnTimeSetListener; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.os.Bundle; import android.os.UserManager; import android.provider.SearchIndexableResource; -import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.Preference; -import android.support.v7.preference.Preference.OnPreferenceChangeListener; -import android.text.format.DateFormat; -import android.widget.DatePicker; -import android.widget.TimePicker; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.settings.core.PreferenceController; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.SummaryLoader; +import com.android.settings.datetime.AutoTimePreferenceController; +import com.android.settings.datetime.AutoTimeZonePreferenceController; +import com.android.settings.datetime.DatePreferenceController; +import com.android.settings.datetime.TimeChangeListenerMixin; import com.android.settings.datetime.TimeFormatPreferenceController; -import com.android.settings.datetime.UpdateTimeAndDateCallback; +import com.android.settings.datetime.TimePreferenceController; +import com.android.settings.datetime.TimeZonePreferenceController; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; -import com.android.settingslib.RestrictedLockUtils; -import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.datetime.ZoneGetter; import java.util.ArrayList; import java.util.Calendar; import java.util.List; -import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +public class DateTimeSettings extends DashboardFragment implements + TimePreferenceController.TimePreferenceHost, DatePreferenceController.DatePreferenceHost { -public class DateTimeSettings extends SettingsPreferenceFragment - implements UpdateTimeAndDateCallback, OnTimeSetListener, OnDateSetListener, - OnPreferenceChangeListener, Indexable { - - private static final String KEY_AUTO_TIME = "auto_time"; - private static final String KEY_AUTO_TIME_ZONE = "auto_zone"; - - private static final int DIALOG_DATEPICKER = 0; - private static final int DIALOG_TIMEPICKER = 1; + private static final String TAG = "DateTimeSettings"; // have we been launched from the setup wizard? protected static final String EXTRA_IS_FROM_SUW = "firstRun"; - // Minimum time is Nov 5, 2007, 0:00. - private static final long MIN_DATE = 1194220800000L; - - private TimeFormatPreferenceController mTimeFormatPreferenceController; - private RestrictedSwitchPreference mAutoTimePref; - private Preference mTimePref; - private SwitchPreference mAutoTimeZonePref; - private Preference mTimeZone; - private Preference mDatePref; - @Override public int getMetricsCategory() { return MetricsEvent.DATE_TIME; } @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - addPreferencesFromResource(R.xml.date_time_prefs); - - initUI(); + protected String getCategoryKey() { + return null; } - private void initUI() { + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.date_time_prefs; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + getLifecycle().addObserver(new TimeChangeListenerMixin(context, this)); + } + + @Override + protected List getPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); final Activity activity = getActivity(); final Intent intent = activity.getIntent(); final boolean isFromSUW = intent.getBooleanExtra(EXTRA_IS_FROM_SUW, false); - boolean autoTimeEnabled = getAutoState(Settings.Global.AUTO_TIME); - boolean autoTimeZoneEnabled = getAutoState(Settings.Global.AUTO_TIME_ZONE); - mTimeFormatPreferenceController = new TimeFormatPreferenceController( - activity, this /* UpdateTimeAndDateCallback */, isFromSUW); - mTimeFormatPreferenceController.displayPreference(getPreferenceScreen()); + final AutoTimeZonePreferenceController autoTimeZonePreferenceController = + new AutoTimeZonePreferenceController( + activity, this /* UpdateTimeAndDateCallback */, isFromSUW); + final AutoTimePreferenceController autoTimePreferenceController = + new AutoTimePreferenceController( + activity, this /* UpdateTimeAndDateCallback */); + controllers.add(autoTimeZonePreferenceController); + controllers.add(autoTimePreferenceController); - mAutoTimePref = (RestrictedSwitchPreference) findPreference(KEY_AUTO_TIME); - mAutoTimePref.setOnPreferenceChangeListener(this); - EnforcedAdmin admin = RestrictedLockUtils.checkIfAutoTimeRequired(activity); - mAutoTimePref.setDisabledByAdmin(admin); - - // If device admin requires auto time device policy manager will set - // Settings.Global.AUTO_TIME to true. Note that this app listens to that change. - mAutoTimePref.setChecked(autoTimeEnabled); - mAutoTimeZonePref = (SwitchPreference) findPreference(KEY_AUTO_TIME_ZONE); - mAutoTimeZonePref.setOnPreferenceChangeListener(this); - // Override auto-timezone if it's a wifi-only device or if we're still in setup wizard. - // TODO: Remove the wifiOnly test when auto-timezone is implemented based on wifi-location. - if (Utils.isWifiOnly(activity) || isFromSUW) { - getPreferenceScreen().removePreference(mAutoTimeZonePref); - autoTimeZoneEnabled = false; - } - mAutoTimeZonePref.setChecked(autoTimeZoneEnabled); - - mTimePref = findPreference("time"); - mTimeZone = findPreference("timezone"); - mDatePref = findPreference("date"); - - mTimePref.setEnabled(!autoTimeEnabled); - mDatePref.setEnabled(!autoTimeEnabled); - mTimeZone.setEnabled(!autoTimeZoneEnabled); - } - - @Override - public void onResume() { - super.onResume(); - // Register for time ticks and other reasons for time change - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_TIME_TICK); - filter.addAction(Intent.ACTION_TIME_CHANGED); - filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); - getActivity().registerReceiver(mIntentReceiver, filter, null, null); - - updateTimeAndDateDisplay(getActivity()); - } - - @Override - public void onPause() { - super.onPause(); - getActivity().unregisterReceiver(mIntentReceiver); + controllers.add(new TimeFormatPreferenceController( + activity, this /* UpdateTimeAndDateCallback */, isFromSUW)); + controllers.add(new TimeZonePreferenceController( + activity, autoTimeZonePreferenceController)); + controllers.add(new TimePreferenceController( + activity, this /* UpdateTimeAndDateCallback */, autoTimePreferenceController)); + controllers.add(new DatePreferenceController( + activity, this /* UpdateTimeAndDateCallback */, autoTimePreferenceController)); + return controllers; } @Override public void updateTimeAndDateDisplay(Context context) { - final Calendar now = Calendar.getInstance(); - mDatePref.setSummary(DateFormat.getLongDateFormat(context).format(now.getTime())); - mTimePref.setSummary(DateFormat.getTimeFormat(getActivity()).format(now.getTime())); - mTimeZone.setSummary(ZoneGetter.getTimeZoneOffsetAndName(context, - now.getTimeZone(), now.getTime())); - mTimeFormatPreferenceController.updateState(findPreference( - mTimeFormatPreferenceController.getPreferenceKey())); - } - - @Override - public void onDateSet(DatePicker view, int year, int month, int day) { - final Activity activity = getActivity(); - if (activity != null) { - setDate(activity, year, month, day); - updateTimeAndDateDisplay(activity); - } - } - - @Override - public void onTimeSet(TimePicker view, int hourOfDay, int minute) { - final Activity activity = getActivity(); - if (activity != null) { - setTime(activity, hourOfDay, minute); - updateTimeAndDateDisplay(activity); - } - - // We don't need to call timeUpdated() here because the TIME_CHANGED - // broadcast is sent by the AlarmManager as a side effect of setting the - // SystemClock time. - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if (preference.getKey().equals(KEY_AUTO_TIME)) { - boolean autoEnabled = (Boolean) newValue; - Settings.Global.putInt(getContentResolver(), Settings.Global.AUTO_TIME, - autoEnabled ? 1 : 0); - mTimePref.setEnabled(!autoEnabled); - mDatePref.setEnabled(!autoEnabled); - } else if (preference.getKey().equals(KEY_AUTO_TIME_ZONE)) { - boolean autoZoneEnabled = (Boolean) newValue; - Settings.Global.putInt( - getContentResolver(), Settings.Global.AUTO_TIME_ZONE, autoZoneEnabled ? 1 : 0); - mTimeZone.setEnabled(!autoZoneEnabled); - } - return true; + updatePreferenceStates(); } @Override public Dialog onCreateDialog(int id) { - final Calendar calendar = Calendar.getInstance(); switch (id) { - case DIALOG_DATEPICKER: - DatePickerDialog d = new DatePickerDialog( - getActivity(), - this, - calendar.get(Calendar.YEAR), - calendar.get(Calendar.MONTH), - calendar.get(Calendar.DAY_OF_MONTH)); - configureDatePicker(d.getDatePicker()); - return d; - case DIALOG_TIMEPICKER: - return new TimePickerDialog( - getActivity(), - this, - calendar.get(Calendar.HOUR_OF_DAY), - calendar.get(Calendar.MINUTE), - DateFormat.is24HourFormat(getActivity())); + case DatePreferenceController.DIALOG_DATEPICKER: + return getPreferenceController(DatePreferenceController.class) + .buildDatePicker(getActivity()); + case TimePreferenceController.DIALOG_TIMEPICKER: + return getPreferenceController(TimePreferenceController.class) + .buildTimePicker(getActivity()); default: throw new IllegalArgumentException(); } @@ -227,120 +125,26 @@ public class DateTimeSettings extends SettingsPreferenceFragment @Override public int getDialogMetricsCategory(int dialogId) { switch (dialogId) { - case DIALOG_DATEPICKER: + case DatePreferenceController.DIALOG_DATEPICKER: return MetricsEvent.DIALOG_DATE_PICKER; - case DIALOG_TIMEPICKER: + case TimePreferenceController.DIALOG_TIMEPICKER: return MetricsEvent.DIALOG_TIME_PICKER; default: return 0; } } - static void configureDatePicker(DatePicker datePicker) { - // The system clock can't represent dates outside this range. - Calendar t = Calendar.getInstance(); - t.clear(); - t.set(1970, Calendar.JANUARY, 1); - datePicker.setMinDate(t.getTimeInMillis()); - t.clear(); - t.set(2037, Calendar.DECEMBER, 31); - datePicker.setMaxDate(t.getTimeInMillis()); - } - - /* @Override - public void onPrepareDialog(int id, Dialog d) { - switch (id) { - case DIALOG_DATEPICKER: { - DatePickerDialog datePicker = (DatePickerDialog)d; - final Calendar calendar = Calendar.getInstance(); - datePicker.updateDate( - calendar.get(Calendar.YEAR), - calendar.get(Calendar.MONTH), - calendar.get(Calendar.DAY_OF_MONTH)); - break; - } - case DIALOG_TIMEPICKER: { - TimePickerDialog timePicker = (TimePickerDialog)d; - final Calendar calendar = Calendar.getInstance(); - timePicker.updateTime( - calendar.get(Calendar.HOUR_OF_DAY), - calendar.get(Calendar.MINUTE)); - break; - } - default: - break; - } - } - */ - @Override - public boolean onPreferenceTreeClick(Preference preference) { - if (mTimeFormatPreferenceController.handlePreferenceTreeClick(preference)) { - return super.onPreferenceTreeClick(preference); - } - if (preference == mDatePref) { - showDialog(DIALOG_DATEPICKER); - } else if (preference == mTimePref) { - // The 24-hour mode may have changed, so recreate the dialog - removeDialog(DIALOG_TIMEPICKER); - showDialog(DIALOG_TIMEPICKER); - } - return super.onPreferenceTreeClick(preference); + public void showTimePicker() { + removeDialog(TimePreferenceController.DIALOG_TIMEPICKER); + showDialog(TimePreferenceController.DIALOG_TIMEPICKER); } @Override - public void onActivityResult(int requestCode, int resultCode, - Intent data) { - updateTimeAndDateDisplay(getActivity()); + public void showDatePicker() { + showDialog(DatePreferenceController.DIALOG_DATEPICKER); } - private boolean getAutoState(String name) { - try { - return Settings.Global.getInt(getContentResolver(), name) > 0; - } catch (SettingNotFoundException snfe) { - return false; - } - } - - /* package */ - static void setDate(Context context, int year, int month, int day) { - Calendar c = Calendar.getInstance(); - - c.set(Calendar.YEAR, year); - c.set(Calendar.MONTH, month); - c.set(Calendar.DAY_OF_MONTH, day); - long when = Math.max(c.getTimeInMillis(), MIN_DATE); - - if (when / 1000 < Integer.MAX_VALUE) { - ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when); - } - } - - /* package */ - static void setTime(Context context, int hourOfDay, int minute) { - Calendar c = Calendar.getInstance(); - - c.set(Calendar.HOUR_OF_DAY, hourOfDay); - c.set(Calendar.MINUTE, minute); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - long when = Math.max(c.getTimeInMillis(), MIN_DATE); - - if (when / 1000 < Integer.MAX_VALUE) { - ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when); - } - } - - private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final Activity activity = getActivity(); - if (activity != null) { - updateTimeAndDateDisplay(activity); - } - } - }; - private static class SummaryProvider implements SummaryLoader.SummaryProvider { private final Context mContext; @@ -370,6 +174,7 @@ public class DateTimeSettings extends SettingsPreferenceFragment } }; + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new DateTimeSearchIndexProvider(); diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java index b0f87341758..28fb851ecb2 100644 --- a/src/com/android/settings/dashboard/DashboardFragment.java +++ b/src/com/android/settings/dashboard/DashboardFragment.java @@ -249,7 +249,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment /** * Update state of each preference managed by PreferenceController. */ - private void updatePreferenceStates() { + protected void updatePreferenceStates() { Collection controllers = mPreferenceControllers.values(); final PreferenceScreen screen = getPreferenceScreen(); for (PreferenceController controller : controllers) { diff --git a/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java b/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java index 75251b3e1eb..8110f32df15 100644 --- a/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java +++ b/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java @@ -38,7 +38,7 @@ public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickL private static final String TAG = "ProgressiveDisclosure"; private static final String STATE_USER_EXPANDED = "state_user_expanded"; - private static final int DEFAULT_TILE_LIMIT = 3; + private static final int DEFAULT_TILE_LIMIT = 300; private int mTileLimit = DEFAULT_TILE_LIMIT; diff --git a/src/com/android/settings/datetime/AutoTimePreferenceController.java b/src/com/android/settings/datetime/AutoTimePreferenceController.java new file mode 100644 index 00000000000..a372a49c2f4 --- /dev/null +++ b/src/com/android/settings/datetime/AutoTimePreferenceController.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.provider.Settings; +import android.support.v7.preference.Preference; + +import com.android.settings.core.PreferenceController; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedSwitchPreference; + +public class AutoTimePreferenceController extends PreferenceController + implements Preference.OnPreferenceChangeListener { + + private static final String KEY_AUTO_TIME = "auto_time"; + private final UpdateTimeAndDateCallback mCallback; + + public AutoTimePreferenceController(Context context, UpdateTimeAndDateCallback callback) { + super(context); + mCallback = callback; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public void updateState(Preference preference) { + if (!(preference instanceof RestrictedSwitchPreference)) { + return; + } + ((RestrictedSwitchPreference) preference).setDisabledByAdmin( + getEnforcedAdminProperty()); + ((RestrictedSwitchPreference) preference).setChecked(isEnabled()); + } + + @Override + public String getPreferenceKey() { + return KEY_AUTO_TIME; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean autoEnabled = (Boolean) newValue; + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTO_TIME, + autoEnabled ? 1 : 0); + mCallback.updateTimeAndDateDisplay(mContext); + return true; + } + + public boolean isEnabled() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AUTO_TIME, 0) > 0; + } + + private RestrictedLockUtils.EnforcedAdmin getEnforcedAdminProperty() { + return RestrictedLockUtils.checkIfAutoTimeRequired(mContext); + } +} diff --git a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java new file mode 100644 index 00000000000..760b2a00253 --- /dev/null +++ b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.provider.Settings; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.Preference; + +import com.android.settings.Utils; +import com.android.settings.core.PreferenceController; + +public class AutoTimeZonePreferenceController extends PreferenceController + implements Preference.OnPreferenceChangeListener { + + private static final String KEY_AUTO_TIME_ZONE = "auto_zone"; + + private final boolean mIsFromSUW; + private final UpdateTimeAndDateCallback mCallback; + + public AutoTimeZonePreferenceController(Context context, UpdateTimeAndDateCallback callback, + boolean isFromSUW) { + super(context); + mCallback = callback; + mIsFromSUW = isFromSUW; + } + + @Override + public boolean isAvailable() { + return !(Utils.isWifiOnly(mContext) || mIsFromSUW); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_AUTO_TIME_ZONE; + } + + @Override + public void updateState(Preference preference) { + if (!(preference instanceof SwitchPreference)) { + return; + } + ((SwitchPreference) preference).setChecked(isEnabled()); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean autoZoneEnabled = (Boolean) newValue; + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTO_TIME_ZONE, + autoZoneEnabled ? 1 : 0); + mCallback.updateTimeAndDateDisplay(mContext); + return true; + } + + public boolean isEnabled() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AUTO_TIME_ZONE, 0) > 0; + } +} diff --git a/src/com/android/settings/datetime/DatePreferenceController.java b/src/com/android/settings/datetime/DatePreferenceController.java new file mode 100644 index 00000000000..2a06e5a8901 --- /dev/null +++ b/src/com/android/settings/datetime/DatePreferenceController.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.app.Activity; +import android.app.AlarmManager; +import android.app.DatePickerDialog; +import android.content.Context; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.widget.DatePicker; + +import com.android.settings.core.PreferenceController; + +import java.util.Calendar; + +public class DatePreferenceController extends PreferenceController implements + DatePickerDialog.OnDateSetListener { + + public interface DatePreferenceHost extends UpdateTimeAndDateCallback { + void showDatePicker(); + } + + public static final int DIALOG_DATEPICKER = 0; + + private static final String KEY_DATE = "date"; + + private final DatePreferenceHost mHost; + private final AutoTimePreferenceController mAutoTimePreferenceController; + + public DatePreferenceController(Context context, DatePreferenceHost host, + AutoTimePreferenceController autoTimePreferenceController) { + super(context); + mHost = host; + mAutoTimePreferenceController = autoTimePreferenceController; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public void updateState(Preference preference) { + final Calendar now = Calendar.getInstance(); + preference.setSummary(DateFormat.getLongDateFormat(mContext).format(now.getTime())); + preference.setEnabled(!mAutoTimePreferenceController.isEnabled()); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), KEY_DATE)) { + return false; + } + mHost.showDatePicker(); + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_DATE; + } + + @Override + public void onDateSet(DatePicker view, int year, int month, int day) { + setDate(year, month, day); + mHost.updateTimeAndDateDisplay(mContext); + } + + public DatePickerDialog buildDatePicker(Activity activity) { + final Calendar calendar = Calendar.getInstance(); + final DatePickerDialog d = new DatePickerDialog( + activity, + this, + calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH), + calendar.get(Calendar.DAY_OF_MONTH)); + // The system clock can't represent dates outside this range. + calendar.clear(); + calendar.set(2007, Calendar.JANUARY, 1); + d.getDatePicker().setMinDate(calendar.getTimeInMillis()); + calendar.clear(); + calendar.set(2037, Calendar.DECEMBER, 31); + d.getDatePicker().setMaxDate(calendar.getTimeInMillis()); + return d; + } + + @VisibleForTesting + void setDate(int year, int month, int day) { + Calendar c = Calendar.getInstance(); + + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month); + c.set(Calendar.DAY_OF_MONTH, day); + long when = Math.max(c.getTimeInMillis(), DatePreferenceHost.MIN_DATE); + + if (when / 1000 < Integer.MAX_VALUE) { + ((AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE)).setTime(when); + } + } +} diff --git a/src/com/android/settings/datetime/TimeChangeListenerMixin.java b/src/com/android/settings/datetime/TimeChangeListenerMixin.java new file mode 100644 index 00000000000..f3729ae69a5 --- /dev/null +++ b/src/com/android/settings/datetime/TimeChangeListenerMixin.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import com.android.settings.core.lifecycle.LifecycleObserver; +import com.android.settings.core.lifecycle.events.OnPause; +import com.android.settings.core.lifecycle.events.OnResume; + +public class TimeChangeListenerMixin extends BroadcastReceiver + implements LifecycleObserver, OnPause, OnResume { + + private final Context mContext; + private final UpdateTimeAndDateCallback mCallback; + + public TimeChangeListenerMixin(Context context, UpdateTimeAndDateCallback callback) { + mContext = context; + mCallback = callback; + } + + @Override + public void onResume() { + // Register for time ticks and other reasons for time change + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_TIME_TICK); + filter.addAction(Intent.ACTION_TIME_CHANGED); + filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); + + mContext.registerReceiver(this, filter, null, null); + } + + @Override + public void onPause() { + mContext.unregisterReceiver(this); + } + + @Override + public void onReceive(Context context, Intent intent) { + if (mCallback != null) { + mCallback.updateTimeAndDateDisplay(mContext); + } + } +} diff --git a/src/com/android/settings/datetime/TimeFormatPreferenceController.java b/src/com/android/settings/datetime/TimeFormatPreferenceController.java index 068b7906126..60db5925459 100644 --- a/src/com/android/settings/datetime/TimeFormatPreferenceController.java +++ b/src/com/android/settings/datetime/TimeFormatPreferenceController.java @@ -58,8 +58,7 @@ public class TimeFormatPreferenceController extends PreferenceController { @Override public void updateState(Preference preference) { - if (!(preference instanceof TwoStatePreference) - || !TextUtils.equals(KEY_TIME_FORMAT, preference.getKey())) { + if (!(preference instanceof TwoStatePreference)) { return; } ((TwoStatePreference) preference).setChecked(is24Hour()); diff --git a/src/com/android/settings/datetime/TimePreferenceController.java b/src/com/android/settings/datetime/TimePreferenceController.java new file mode 100644 index 00000000000..4862588f25f --- /dev/null +++ b/src/com/android/settings/datetime/TimePreferenceController.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.app.Activity; +import android.app.AlarmManager; +import android.app.TimePickerDialog; +import android.content.Context; +import android.support.v7.preference.Preference; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.widget.TimePicker; + +import com.android.settings.core.PreferenceController; + +import java.util.Calendar; + +public class TimePreferenceController extends PreferenceController implements + TimePickerDialog.OnTimeSetListener { + + public interface TimePreferenceHost extends UpdateTimeAndDateCallback { + void showTimePicker(); + } + + public static final int DIALOG_TIMEPICKER = 1; + + private static final String KEY_TIME = "time"; + + private final AutoTimePreferenceController mAutoTimePreferenceController; + private final TimePreferenceHost mHost; + + + public TimePreferenceController(Context context, + TimePreferenceHost callback, + AutoTimePreferenceController autoTimePreferenceController) { + super(context); + mHost = callback; + mAutoTimePreferenceController = autoTimePreferenceController; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public void updateState(Preference preference) { + final Calendar now = Calendar.getInstance(); + preference.setSummary(DateFormat.getTimeFormat(mContext).format(now.getTime())); + preference.setEnabled(!mAutoTimePreferenceController.isEnabled()); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(KEY_TIME, preference.getKey())) { + return false; + } + mHost.showTimePicker(); + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_TIME; + } + + @Override + public void onTimeSet(TimePicker view, int hourOfDay, int minute) { + if (mContext != null) { + setTime(hourOfDay, minute); + mHost.updateTimeAndDateDisplay(mContext); + } + // We don't need to call timeUpdated() here because the TIME_CHANGED + // broadcast is sent by the AlarmManager as a side effect of setting the + // SystemClock time. + } + + public TimePickerDialog buildTimePicker(Activity activity) { + final Calendar calendar = Calendar.getInstance(); + return new TimePickerDialog( + activity, + this, + calendar.get(Calendar.HOUR_OF_DAY), + calendar.get(Calendar.MINUTE), + DateFormat.is24HourFormat(activity)); + } + + void setTime(int hourOfDay, int minute) { + Calendar c = Calendar.getInstance(); + + c.set(Calendar.HOUR_OF_DAY, hourOfDay); + c.set(Calendar.MINUTE, minute); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + long when = Math.max(c.getTimeInMillis(), TimePreferenceHost.MIN_DATE); + + if (when / 1000 < Integer.MAX_VALUE) { + ((AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE)).setTime(when); + } + } +} diff --git a/src/com/android/settings/datetime/TimeZonePreferenceController.java b/src/com/android/settings/datetime/TimeZonePreferenceController.java new file mode 100644 index 00000000000..57c1bc7e304 --- /dev/null +++ b/src/com/android/settings/datetime/TimeZonePreferenceController.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; + +import com.android.settings.core.PreferenceController; +import com.android.settingslib.datetime.ZoneGetter; + +import java.util.Calendar; + +public class TimeZonePreferenceController extends PreferenceController { + + private static final String KEY_TIMEZONE = "timezone"; + + private final AutoTimeZonePreferenceController mAutoTimeZonePreferenceController; + + public TimeZonePreferenceController(Context context, + AutoTimeZonePreferenceController autoTimeZonePreferenceController) { + super(context); + mAutoTimeZonePreferenceController = autoTimeZonePreferenceController; + } + + @Override + public void updateState(Preference preference) { + preference.setSummary(getTimeZoneOffsetAndName()); + preference.setEnabled(!mAutoTimeZonePreferenceController.isEnabled()); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_TIMEZONE; + } + + @VisibleForTesting + CharSequence getTimeZoneOffsetAndName() { + final Calendar now = Calendar.getInstance(); + return ZoneGetter.getTimeZoneOffsetAndName(mContext, + now.getTimeZone(), now.getTime()); + } +} diff --git a/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java b/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java index e89b5dae78a..333b9aad29e 100644 --- a/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java +++ b/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java @@ -19,6 +19,8 @@ package com.android.settings.datetime; import android.content.Context; public interface UpdateTimeAndDateCallback { + // Minimum time is Nov 5, 2007, 0:00. + long MIN_DATE = 1194220800000L; void updateTimeAndDateDisplay(Context context); } diff --git a/tests/robotests/src/com/android/settings/datetime/AutoTimePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/AutoTimePreferenceControllerTest.java new file mode 100644 index 00000000000..d0bd67bd3e7 --- /dev/null +++ b/tests/robotests/src/com/android/settings/datetime/AutoTimePreferenceControllerTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.provider.Settings; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settingslib.RestrictedSwitchPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class AutoTimePreferenceControllerTest { + + @Mock + private UpdateTimeAndDateCallback mCallback; + + private Context mContext; + private RestrictedSwitchPreference mPreference; + private AutoTimePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ShadowApplication.getInstance().getApplicationContext(); + mPreference = new RestrictedSwitchPreference(mContext); + mController = new AutoTimePreferenceController(mContext, mCallback); + } + + @Test + public void testIsEnabled_shouldReadFromSettingsProvider() { + // Disabled + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.AUTO_TIME, 0); + assertThat(mController.isEnabled()).isFalse(); + + // Enabled + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.AUTO_TIME, 1); + assertThat(mController.isEnabled()).isTrue(); + } + + @Test + public void updatePreferenceChange_prefIsChecked_shouldUpdatePreferenceAndNotifyCallback() { + mController.onPreferenceChange(mPreference, true); + + assertThat(mController.isEnabled()).isTrue(); + verify(mCallback).updateTimeAndDateDisplay(mContext); + } + + @Test + public void updatePreferenceChange_prefIsUnchecked_shouldUpdatePreferenceAndNotifyCallback() { + mController.onPreferenceChange(mPreference, false); + + assertThat(mController.isEnabled()).isFalse(); + verify(mCallback).updateTimeAndDateDisplay(mContext); + } +} diff --git a/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java new file mode 100644 index 00000000000..cc8d84a8539 --- /dev/null +++ b/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.provider.Settings; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class AutoTimeZonePreferenceControllerTest { + + @Mock + private Context mMockContext; + @Mock + private ConnectivityManager mCm; + @Mock + private UpdateTimeAndDateCallback mCallback; + + private Context mContext; + private AutoTimeZonePreferenceController mController; + private Preference mPreference; + + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ShadowApplication.getInstance().getApplicationContext(); + mPreference = new Preference(mContext); + when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mCm); + when(mCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true); + } + + @Test + public void isFromSUW_notAvailable() { + mController = new AutoTimeZonePreferenceController( + mMockContext, null /* callback */, true /* isFromSUW */); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void notFromSUW_isAvailable() { + mController = new AutoTimeZonePreferenceController( + mMockContext, null /* callback */, false /* isFromSUW */); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void isWifiOnly_notAvailable() { + when(mCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false); + + mController = new AutoTimeZonePreferenceController( + mMockContext, null /* callback */, false /* isFromSUW */); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsEnabled_shouldReadFromSettingsProvider() { + mController = new AutoTimeZonePreferenceController( + mContext, null /* callback */, false /* isFromSUW */); + + // Disabled + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.AUTO_TIME_ZONE, 0); + assertThat(mController.isEnabled()).isFalse(); + + // Enabled + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.AUTO_TIME_ZONE, 1); + assertThat(mController.isEnabled()).isTrue(); + } + + @Test + public void updatePreferenceChange_prefIsChecked_shouldUpdatePreferenceAndNotifyCallback() { + mController = new AutoTimeZonePreferenceController( + mContext, mCallback, false /* isFromSUW */); + + mController.onPreferenceChange(mPreference, true); + + assertThat(mController.isEnabled()).isTrue(); + verify(mCallback).updateTimeAndDateDisplay(mContext); + } + + @Test + public void updatePreferenceChange_prefIsUnchecked_shouldUpdatePreferenceAndNotifyCallback() { + mController = new AutoTimeZonePreferenceController( + mContext, mCallback, false /* isFromSUW */); + + mController.onPreferenceChange(mPreference, false); + + assertThat(mController.isEnabled()).isFalse(); + verify(mCallback).updateTimeAndDateDisplay(mContext); + } +} diff --git a/tests/robotests/src/com/android/settings/datetime/DatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/DatePreferenceControllerTest.java new file mode 100644 index 00000000000..4b9d3ec167b --- /dev/null +++ b/tests/robotests/src/com/android/settings/datetime/DatePreferenceControllerTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.app.AlarmManager; +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class DatePreferenceControllerTest { + + @Mock + private Context mContext; + @Mock + private AlarmManager mAlarmManager; + @Mock + private DatePreferenceController.DatePreferenceHost mHost; + @Mock + private AutoTimePreferenceController mAutoTimePreferenceController; + + private Preference mPreference; + private DatePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager); + mPreference = new Preference(ShadowApplication.getInstance().getApplicationContext()); + mController = new DatePreferenceController(mContext, mHost, mAutoTimePreferenceController); + } + + @Test + public void isAlwaysAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void shouldHandleDateSetCallback() { + mController.onDateSet(null, 2016, 1, 1); + verify(mHost).updateTimeAndDateDisplay(mContext); + } + + @Test + public void updateState_autoTimeEnabled_shouldDisablePref() { + when(mAutoTimePreferenceController.isEnabled()).thenReturn(true); + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + } + + @Test + public void updateState_autoTimeDisabled_shouldEnablePref() { + when(mAutoTimePreferenceController.isEnabled()).thenReturn(false); + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isTrue(); + } + + @Test + public void clickPreference_showDatePicker() { + // Click a preference that's not controlled by this controller. + mPreference.setKey("fake_key"); + assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse(); + + // Click a preference controlled by this controller. + mPreference.setKey(mController.getPreferenceKey()); + mController.handlePreferenceTreeClick(mPreference); + // Should show date picker + verify(mHost).showDatePicker(); + } +} diff --git a/tests/robotests/src/com/android/settings/datetime/TimeChangeListenerMixinTest.java b/tests/robotests/src/com/android/settings/datetime/TimeChangeListenerMixinTest.java new file mode 100644 index 00000000000..8a8c066af08 --- /dev/null +++ b/tests/robotests/src/com/android/settings/datetime/TimeChangeListenerMixinTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.content.Intent; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.core.lifecycle.LifecycleObserver; +import com.android.settings.core.lifecycle.events.OnPause; +import com.android.settings.core.lifecycle.events.OnResume; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class TimeChangeListenerMixinTest { + + @Mock + private UpdateTimeAndDateCallback mCallback; + + private Context mContext; + private TimeChangeListenerMixin mMixin; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ShadowApplication.getInstance().getApplicationContext(); + mMixin = new TimeChangeListenerMixin(mContext, mCallback); + } + + @Test + public void shouldImplementMixinInterfaces() { + assertThat(mMixin instanceof LifecycleObserver).isTrue(); + assertThat(mMixin instanceof OnPause).isTrue(); + assertThat(mMixin instanceof OnResume).isTrue(); + } + + @Test + public void onResume_shouldRegisterIntentFilter() { + mMixin.onResume(); + mContext.sendBroadcast(new Intent(Intent.ACTION_TIME_TICK)); + mContext.sendBroadcast(new Intent(Intent.ACTION_TIME_CHANGED)); + mContext.sendBroadcast(new Intent(Intent.ACTION_TIMEZONE_CHANGED)); + + verify(mCallback, times(3)).updateTimeAndDateDisplay(mContext); + } + + @Test + public void onPause_shouldUnregisterIntentFilter() { + mMixin.onResume(); + mMixin.onPause(); + mContext.sendBroadcast(new Intent(Intent.ACTION_TIME_TICK)); + mContext.sendBroadcast(new Intent(Intent.ACTION_TIME_CHANGED)); + mContext.sendBroadcast(new Intent(Intent.ACTION_TIMEZONE_CHANGED)); + + verify(mCallback, never()).updateTimeAndDateDisplay(mContext); + } +} diff --git a/tests/robotests/src/com/android/settings/datetime/TimePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/TimePreferenceControllerTest.java new file mode 100644 index 00000000000..3995f37fe68 --- /dev/null +++ b/tests/robotests/src/com/android/settings/datetime/TimePreferenceControllerTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class TimePreferenceControllerTest { + + @Mock + private Context mContext; + @Mock + private TimePreferenceController.TimePreferenceHost mHost; + @Mock + private AutoTimePreferenceController mAutoTimePreferenceController; + + private TimePreferenceController mController; + private Preference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mPreference = new Preference(ShadowApplication.getInstance().getApplicationContext()); + mController = new TimePreferenceController(mContext, mHost, mAutoTimePreferenceController); + } + + @Test + public void isAlwaysAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void updateState_autoTimeEnabled_shouldDisablePref() { + when(mAutoTimePreferenceController.isEnabled()).thenReturn(true); + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + } + + @Test + public void updateState_autoTimeDisabled_shouldEnablePref() { + when(mAutoTimePreferenceController.isEnabled()).thenReturn(false); + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isTrue(); + } + + @Test + public void clickPreference_showTimePicker() { + // Click a preference that's not controlled by this controller. + mPreference.setKey("fake_key"); + assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse(); + + // Click a preference controlled by this controller. + mPreference.setKey(mController.getPreferenceKey()); + mController.handlePreferenceTreeClick(mPreference); + // Should show date picker + verify(mHost).showTimePicker(); + } + +} diff --git a/tests/robotests/src/com/android/settings/datetime/TimeZonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/TimeZonePreferenceControllerTest.java new file mode 100644 index 00000000000..cab6f711de0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/datetime/TimeZonePreferenceControllerTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 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.settings.datetime; + +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class TimeZonePreferenceControllerTest { + + @Mock + private AutoTimeZonePreferenceController mAutoTimeZonePreferenceController; + private Context mContext; + private TimeZonePreferenceController mController; + private Preference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ShadowApplication.getInstance().getApplicationContext(); + mPreference = new Preference(mContext); + mController = spy(new TimeZonePreferenceController(mContext, + mAutoTimeZonePreferenceController)); + } + + @Test + public void isAlwaysAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void updateState_autoTimeZoneEnabled_shouldDisablePref() { + doReturn("test timezone").when(mController).getTimeZoneOffsetAndName(); + when(mAutoTimeZonePreferenceController.isEnabled()).thenReturn(true); + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + } + + @Test + public void updateState_autoTimeZoneDisabled_shouldEnablePref() { + doReturn("test timezone").when(mController).getTimeZoneOffsetAndName(); + when(mAutoTimeZonePreferenceController.isEnabled()).thenReturn(false); + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isTrue(); + } +}