diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java index cbe3cddca3e..749a4ed403c 100644 --- a/src/com/android/settings/DateTimeSettings.java +++ b/src/com/android/settings/DateTimeSettings.java @@ -41,6 +41,8 @@ import android.widget.TimePicker; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.dashboard.SummaryLoader; +import com.android.settings.datetime.TimeFormatPreferenceController; +import com.android.settings.datetime.UpdateTimeAndDateCallback; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settingslib.RestrictedLockUtils; @@ -49,20 +51,13 @@ import com.android.settingslib.datetime.ZoneGetter; import java.util.ArrayList; import java.util.Calendar; -import java.util.Date; import java.util.List; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; public class DateTimeSettings extends SettingsPreferenceFragment - implements OnTimeSetListener, OnDateSetListener, OnPreferenceChangeListener, Indexable { - - private static final String HOURS_12 = "12"; - private static final String HOURS_24 = "24"; - - // Used for showing the current date format, which looks like "12/31/2010", "2010/12/13", etc. - // The date value is dummy (independent of actual date). - private Calendar mDummyDate; + 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"; @@ -71,14 +66,14 @@ public class DateTimeSettings extends SettingsPreferenceFragment private static final int DIALOG_TIMEPICKER = 1; // have we been launched from the setup wizard? - protected static final String EXTRA_IS_FIRST_RUN = "firstRun"; + 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 Preference mTime24Pref; private SwitchPreference mAutoTimeZonePref; private Preference mTimeZone; private Preference mDatePref; @@ -98,19 +93,21 @@ public class DateTimeSettings extends SettingsPreferenceFragment } private void initUI() { + 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()); + mAutoTimePref = (RestrictedSwitchPreference) findPreference(KEY_AUTO_TIME); mAutoTimePref.setOnPreferenceChangeListener(this); - EnforcedAdmin admin = RestrictedLockUtils.checkIfAutoTimeRequired(getActivity()); + EnforcedAdmin admin = RestrictedLockUtils.checkIfAutoTimeRequired(activity); mAutoTimePref.setDisabledByAdmin(admin); - Intent intent = getActivity().getIntent(); - boolean isFirstRun = intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false); - - mDummyDate = Calendar.getInstance(); - // 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); @@ -118,19 +115,15 @@ public class DateTimeSettings extends SettingsPreferenceFragment 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(getActivity()) || isFirstRun) { + if (Utils.isWifiOnly(activity) || isFromSUW) { getPreferenceScreen().removePreference(mAutoTimeZonePref); autoTimeZoneEnabled = false; } mAutoTimeZonePref.setChecked(autoTimeZoneEnabled); mTimePref = findPreference("time"); - mTime24Pref = findPreference("24 hour"); mTimeZone = findPreference("timezone"); mDatePref = findPreference("date"); - if (isFirstRun) { - getPreferenceScreen().removePreference(mTime24Pref); - } mTimePref.setEnabled(!autoTimeEnabled); mDatePref.setEnabled(!autoTimeEnabled); @@ -140,9 +133,6 @@ public class DateTimeSettings extends SettingsPreferenceFragment @Override public void onResume() { super.onResume(); - - ((SwitchPreference)mTime24Pref).setChecked(is24Hour()); - // Register for time ticks and other reasons for time change IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); @@ -159,18 +149,15 @@ public class DateTimeSettings extends SettingsPreferenceFragment getActivity().unregisterReceiver(mIntentReceiver); } + @Override public void updateTimeAndDateDisplay(Context context) { final Calendar now = Calendar.getInstance(); - mDummyDate.setTimeZone(now.getTimeZone()); - // We use December 31st because it's unambiguous when demonstrating the date format. - // We use 13:00 so we can demonstrate the 12/24 hour options. - mDummyDate.set(now.get(Calendar.YEAR), 11, 31, 13, 0, 0); - Date dummyDate = mDummyDate.getTime(); 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())); - mTime24Pref.setSummary(DateFormat.getTimeFormat(getActivity()).format(dummyDate)); + mTimeFormatPreferenceController.updateState(findPreference( + mTimeFormatPreferenceController.getPreferenceKey())); } @Override @@ -216,24 +203,24 @@ public class DateTimeSettings extends SettingsPreferenceFragment 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())); - default: - throw new IllegalArgumentException(); + 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())); + default: + throw new IllegalArgumentException(); } } @@ -288,17 +275,15 @@ public class DateTimeSettings extends SettingsPreferenceFragment */ @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); - } else if (preference == mTime24Pref) { - final boolean is24Hour = ((SwitchPreference)mTime24Pref).isChecked(); - set24Hour(is24Hour); - updateTimeAndDateDisplay(getActivity()); - timeUpdated(is24Hour); } return super.onPreferenceTreeClick(preference); } @@ -309,24 +294,6 @@ public class DateTimeSettings extends SettingsPreferenceFragment updateTimeAndDateDisplay(getActivity()); } - private void timeUpdated(boolean is24Hour) { - Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED); - timeChanged.putExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, is24Hour); - getActivity().sendBroadcast(timeChanged); - } - - /* Get & Set values from the system settings */ - - private boolean is24Hour() { - return DateFormat.is24HourFormat(getActivity()); - } - - private void set24Hour(boolean is24Hour) { - Settings.System.putString(getContentResolver(), - Settings.System.TIME_12_24, - is24Hour? HOURS_24 : HOURS_12); - } - private boolean getAutoState(String name) { try { return Settings.Global.getInt(getContentResolver(), name) > 0; @@ -335,7 +302,8 @@ public class DateTimeSettings extends SettingsPreferenceFragment } } - /* package */ static void setDate(Context context, int year, int month, int day) { + /* package */ + static void setDate(Context context, int year, int month, int day) { Calendar c = Calendar.getInstance(); c.set(Calendar.YEAR, year); @@ -348,7 +316,8 @@ public class DateTimeSettings extends SettingsPreferenceFragment } } - /* package */ static void setTime(Context context, int hourOfDay, int minute) { + /* package */ + static void setTime(Context context, int hourOfDay, int minute) { Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, hourOfDay); @@ -396,7 +365,7 @@ public class DateTimeSettings extends SettingsPreferenceFragment = new SummaryLoader.SummaryProviderFactory() { @Override public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, - SummaryLoader summaryLoader) { + SummaryLoader summaryLoader) { return new SummaryProvider(activity, summaryLoader); } }; diff --git a/src/com/android/settings/datetime/TimeFormatPreferenceController.java b/src/com/android/settings/datetime/TimeFormatPreferenceController.java new file mode 100644 index 00000000000..068b7906126 --- /dev/null +++ b/src/com/android/settings/datetime/TimeFormatPreferenceController.java @@ -0,0 +1,108 @@ +/* + * 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 android.provider.Settings; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.TwoStatePreference; +import android.text.TextUtils; +import android.text.format.DateFormat; + +import com.android.settings.core.PreferenceController; + +import java.util.Calendar; +import java.util.Date; + +public class TimeFormatPreferenceController extends PreferenceController { + + static final String HOURS_12 = "12"; + static final String HOURS_24 = "24"; + + private static final String KEY_TIME_FORMAT = "24 hour"; + + // Used for showing the current date format, which looks like "12/31/2010", "2010/12/13", etc. + // The date value is dummy (independent of actual date). + private final Calendar mDummyDate; + private final boolean mIsFromSUW; + private final UpdateTimeAndDateCallback mUpdateTimeAndDateCallback; + + public TimeFormatPreferenceController(Context context, UpdateTimeAndDateCallback callback, + boolean isFromSUW) { + super(context); + mIsFromSUW = isFromSUW; + mDummyDate = Calendar.getInstance(); + mUpdateTimeAndDateCallback = callback; + } + + @Override + public boolean isAvailable() { + return !mIsFromSUW; + } + + @Override + public void updateState(Preference preference) { + if (!(preference instanceof TwoStatePreference) + || !TextUtils.equals(KEY_TIME_FORMAT, preference.getKey())) { + return; + } + ((TwoStatePreference) preference).setChecked(is24Hour()); + final Calendar now = Calendar.getInstance(); + mDummyDate.setTimeZone(now.getTimeZone()); + // We use December 31st because it's unambiguous when demonstrating the date format. + // We use 13:00 so we can demonstrate the 12/24 hour options. + mDummyDate.set(now.get(Calendar.YEAR), 11, 31, 13, 0, 0); + final Date dummyDate = mDummyDate.getTime(); + preference.setSummary(DateFormat.getTimeFormat(mContext).format(dummyDate)); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!(preference instanceof TwoStatePreference) + || !TextUtils.equals(KEY_TIME_FORMAT, preference.getKey())) { + return false; + } + final boolean is24Hour = ((SwitchPreference) preference).isChecked(); + set24Hour(is24Hour); + timeUpdated(is24Hour); + mUpdateTimeAndDateCallback.updateTimeAndDateDisplay(mContext); + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_TIME_FORMAT; + } + + private boolean is24Hour() { + return DateFormat.is24HourFormat(mContext); + } + + private void timeUpdated(boolean is24Hour) { + Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED); + timeChanged.putExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, is24Hour); + mContext.sendBroadcast(timeChanged); + } + + private void set24Hour(boolean is24Hour) { + Settings.System.putString(mContext.getContentResolver(), + Settings.System.TIME_12_24, + is24Hour ? HOURS_24 : HOURS_12); + } +} diff --git a/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java b/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java new file mode 100644 index 00000000000..e89b5dae78a --- /dev/null +++ b/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java @@ -0,0 +1,24 @@ +/* + * 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; + +public interface UpdateTimeAndDateCallback { + + void updateTimeAndDateDisplay(Context context); +} diff --git a/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java new file mode 100644 index 00000000000..91c6a44a9bd --- /dev/null +++ b/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java @@ -0,0 +1,97 @@ +/* + * 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.PreferenceScreen; + +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.Answers.RETURNS_DEEP_STUBS; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class TimeFormatPreferenceControllerTest { + + @Mock(answer = RETURNS_DEEP_STUBS) + private PreferenceScreen mScreen; + @Mock + private UpdateTimeAndDateCallback mCallback; + + private Context mContext; + private SwitchPreference mPreference; + private TimeFormatPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ShadowApplication.getInstance().getApplicationContext(); + } + + @Test + public void isCalledFromSUW_NotAvailable() { + mController = new TimeFormatPreferenceController(mContext, mCallback, true); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void notCalledFromSUW_shouldBeAvailable() { + mController = new TimeFormatPreferenceController(mContext, mCallback, false); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void updateState_24HourSet_shouldCheckPreference() { + mController = new TimeFormatPreferenceController(mContext, mCallback, false); + mPreference = new SwitchPreference(mContext); + mPreference.setKey(mController.getPreferenceKey()); + Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24, + TimeFormatPreferenceController.HOURS_24); + + mController.updateState(mPreference); + + assertThat(mPreference.isChecked()).isTrue(); + } + + @Test + public void updateState_12HourSet_shouldNotCheckPreference() { + mController = new TimeFormatPreferenceController(mContext, mCallback, false); + mPreference = new SwitchPreference(mContext); + mPreference.setKey(mController.getPreferenceKey()); + Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24, + TimeFormatPreferenceController.HOURS_12); + + mController.updateState(mPreference); + + assertThat(mPreference.isChecked()).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java index e3a4ba366f4..81372cc2996 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java @@ -26,6 +26,7 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import com.android.settings.DevelopmentSettings; +import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import org.junit.Before; @@ -34,7 +35,6 @@ import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; @@ -46,7 +46,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(RobolectricTestRunner.class) +@RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class BuildNumberPreferenceControllerTest {