Updated toggles in Date and time settings page

Design doc: go/dd-android-settings-time-2024

Changes:
- toggling off "automatic time zone" now sets "use location" off and makes it unmodifiable
- removing "use locale default" for time format

Bug: 296835792
Test: on-device and atest
Flag: com.android.settings.flags.revamp_toggles
Change-Id: I31744f104fed06ee9980a6a0160501325175a02d
This commit is contained in:
Geoffrey Boullanger
2024-10-11 16:02:59 +00:00
parent f7d9c87ac7
commit b2dd2e3203
10 changed files with 282 additions and 21 deletions

View File

@@ -9,3 +9,11 @@ flag {
bug: "283239837"
}
flag {
name: "revamp_toggles"
# "location" is used by the Android System Time team for feature flags.
namespace: "location"
description: "Makes the use location toggle dependent on automatic time zone detection"
bug: "296835792"
}

View File

@@ -579,7 +579,7 @@
<!-- Date & time setting screen setting switch summary: whether the time zone should be determined automatically [CHAR LIMIT=100] -->
<string name="zone_auto_title_summary">Set automatically based on mobile networks near you</string>
<!-- Date & time setting screen setting switch summary for non-telephony devices [CHAR LIMIT=100] -->
<string name="auto_zone_requires_location_summary">Set automatically using your device location, if available. An active Wifi connection may also be required.</string>
<string name="auto_zone_requires_location_summary">Set automatically using your device location, if available</string>
<!-- Date & time setting screen setting option summary text for the automatic 24 hour setting checkbox [CHAR LIMIT=100] -->
<string name="date_time_24hour_auto">Use locale default</string>
<!-- Date & time setting screen setting check box title -->

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2024 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/date_and_time"
settings:keywords="@string/keywords_date_and_time">
<com.android.settingslib.RestrictedSwitchPreference
android:key="auto_time"
android:title="@string/date_time_auto"
android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_date_time"
settings:controller="com.android.settings.datetime.AutoTimePreferenceController" />
<com.android.settingslib.RestrictedPreference
android:key="date"
android:title="@string/date_time_set_date_title"
android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_date_time"
settings:controller="com.android.settings.datetime.DatePreferenceController" />
<com.android.settingslib.RestrictedPreference
android:key="time"
android:title="@string/date_time_set_time_title"
android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_date_time"
settings:controller="com.android.settings.datetime.TimePreferenceController" />
<PreferenceCategory
android:key="timezone_preference_category"
android:title="@string/date_time_set_timezone_title">
<com.android.settingslib.RestrictedSwitchPreference
android:key="auto_zone"
android:title="@string/zone_auto_title"
android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_date_time"
settings:controller="com.android.settings.datetime.AutoTimeZonePreferenceController" />
<com.android.settingslib.widget.BannerMessagePreference
android:key="location_time_zone_detection_status"
android:title="@string/location_time_zone_detection_status_title"
settings:controller="com.android.settings.datetime.LocationProviderStatusPreferenceController"/>
<!-- This preference gets removed if location-based time zone detection is not supported -->
<SwitchPreferenceCompat
android:key="location_time_zone_detection"
android:title="@string/location_time_zone_detection_toggle_title"
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceController"/>
<com.android.settingslib.RestrictedPreference
android:key="timezone"
android:title="@string/date_time_set_timezone_title"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.datetime.timezone.TimeZoneSettings"
settings:userRestriction="no_config_date_time"
settings:keywords="@string/keywords_time_zone"
settings:controller="com.android.settings.datetime.TimeZonePreferenceController" />
</PreferenceCategory>
<!-- An optional preference category for feedback. Only displayed up if enabled via flags and config. -->
<PreferenceCategory
android:key="time_feedback_preference_category"
android:title="@string/time_feedback_category_title"
settings:keywords="@string/keywords_time_feedback_category"
settings:controller="com.android.settings.datetime.TimeFeedbackPreferenceCategoryController">
<Preference
android:key="time_feedback"
android:title="@string/time_feedback_title"
settings:keywords="@string/keywords_time_feedback"
settings:controller="com.android.settings.datetime.TimeFeedbackPreferenceController" />
</PreferenceCategory>
<PreferenceCategory
android:key="time_format_preference_category"
android:title="@string/time_format_category_title"
settings:keywords="@string/keywords_time_format">
<SwitchPreferenceCompat
android:key="24 hour"
android:title="@string/date_time_24hour"
settings:controller="com.android.settings.datetime.TimeFormatPreferenceController" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -32,6 +32,7 @@ import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.flags.Flags;
public class AutoTimeZonePreferenceController extends TogglePreferenceController {
@@ -103,10 +104,25 @@ public class AutoTimeZonePreferenceController extends TogglePreferenceController
@Override
public boolean setChecked(boolean isChecked) {
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(isChecked)
.build();
boolean result = mTimeManager.updateTimeZoneConfiguration(configuration);
TimeZoneConfiguration.Builder configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(isChecked);
if (Flags.revampToggles()) {
// "Use location for time zone" is only used if "Automatic time zone" is enabled. If
// the user toggles off automatic time zone, set the toggle off and disable the toggle.
int geoDetectionCapability = mTimeManager
.getTimeZoneCapabilitiesAndConfig()
.getCapabilities()
.getConfigureGeoDetectionEnabledCapability();
if (!isChecked
&& (geoDetectionCapability == CAPABILITY_NOT_APPLICABLE
|| geoDetectionCapability == CAPABILITY_POSSESSED)) {
configuration.setGeoDetectionEnabled(false);
}
}
boolean result = mTimeManager.updateTimeZoneConfiguration(configuration.build());
mCallback.updateTimeAndDateDisplay(mContext);
return result;
@@ -138,8 +154,10 @@ public class AutoTimeZonePreferenceController extends TogglePreferenceController
@VisibleForTesting
boolean isEnabled() {
TimeZoneConfiguration config = getTimeZoneCapabilitiesAndConfig().getConfiguration();
return config.isAutoDetectionEnabled();
return mTimeManager
.getTimeZoneCapabilitiesAndConfig()
.getConfiguration()
.isAutoDetectionEnabled();
}
private TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig() {

View File

@@ -23,6 +23,7 @@ import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
@@ -49,6 +50,9 @@ public class DateTimeSettings extends DashboardFragment implements
@Override
protected int getPreferenceScreenResId() {
if (Flags.revampToggles()) {
return R.xml.date_time_prefs_revamped;
}
return R.xml.date_time_prefs;
}
@@ -119,5 +123,6 @@ public class DateTimeSettings extends DashboardFragment implements
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.date_time_prefs);
new BaseSearchIndexProvider(
Flags.revampToggles() ? R.xml.date_time_prefs_revamped : R.xml.date_time_prefs);
}

View File

@@ -32,6 +32,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.flags.Flags;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -64,8 +65,10 @@ public class LocationTimeZoneDetectionPreferenceController
@Override
public boolean isChecked() {
// forceRefresh set to true as the location toggle may have been turned off by switching off
// automatic time zone
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/false);
getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/ Flags.revampToggles());
TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
return configuration.isGeoDetectionEnabled();
}
@@ -73,7 +76,7 @@ public class LocationTimeZoneDetectionPreferenceController
@Override
public boolean setChecked(boolean isChecked) {
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/false);
getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/ false);
boolean isLocationEnabled =
timeZoneCapabilitiesAndConfig.getCapabilities().isUseLocationEnabled();
if (isChecked && !isLocationEnabled) {
@@ -130,17 +133,30 @@ public class LocationTimeZoneDetectionPreferenceController
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false).getCapabilities();
int capability = timeZoneCapabilities.getConfigureGeoDetectionEnabledCapability();
// The preference only has two states: present and not present. The preference is never
// present but disabled.
// The preference can be present and enabled, present and disabled or not present.
if (capability == CAPABILITY_NOT_SUPPORTED || capability == CAPABILITY_NOT_ALLOWED) {
return UNSUPPORTED_ON_DEVICE;
} else if (capability == CAPABILITY_NOT_APPLICABLE || capability == CAPABILITY_POSSESSED) {
if (Flags.revampToggles()) {
return isAutoTimeZoneEnabled() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
} else {
return AVAILABLE;
}
} else {
throw new IllegalStateException("Unknown capability=" + capability);
}
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (Flags.revampToggles()) {
// enable / disable the toggle based on automatic time zone being enabled or not
preference.setEnabled(isAutoTimeZoneEnabled());
}
}
@Override
public CharSequence getSummary() {
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
@@ -212,4 +228,13 @@ public class LocationTimeZoneDetectionPreferenceController
}
return mTimeZoneCapabilitiesAndConfig;
}
/**
* Returns whether the user can select this preference or not, as it is a sub toggle of
* automatic time zone.
*/
private boolean isAutoTimeZoneEnabled() {
return mTimeManager.getTimeZoneCapabilitiesAndConfig().getConfiguration()
.isAutoDetectionEnabled();
}
}

View File

@@ -25,6 +25,7 @@ import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.flags.Flags;
import java.util.Calendar;
import java.util.Date;
@@ -72,9 +73,11 @@ public class TimeFormatPreferenceController extends TogglePreferenceController {
if (mIsFromSUW) {
return DISABLED_DEPENDENT_SETTING;
}
if (!Flags.revampToggles()) {
if (AutoTimeFormatPreferenceController.isAutoTimeFormatSelection(mContext)) {
return DISABLED_DEPENDENT_SETTING;
}
}
return AVAILABLE;
}

View File

@@ -40,12 +40,17 @@ import android.app.time.TimeZoneConfiguration;
import android.app.time.TimeZoneDetectorStatus;
import android.content.Context;
import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -57,6 +62,9 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class AutoTimeZonePreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private UpdateTimeAndDateCallback mCallback;
private Context mContext;
@@ -238,8 +246,53 @@ public class AutoTimeZonePreferenceControllerTest {
mContext.getString(R.string.auto_zone_requires_location_summary));
}
@Test
@EnableFlags({Flags.FLAG_REVAMP_TOGGLES})
public void toggleOff_revampFlagOn_shouldToggleOffUseLocation() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(
/* autoSupported= */ true,
/* autoEnabled= */ true,
/* telephonySupported= */ true,
/* locationSupported= */ true);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
mController.setChecked(false);
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(false)
.setGeoDetectionEnabled(false)
.build();
verify(mTimeManager).updateTimeZoneConfiguration(configuration);
}
@Test
@DisableFlags({Flags.FLAG_REVAMP_TOGGLES})
public void toggleOff_revampFlagOff_shouldToggleOffUseLocation() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(
/* autoSupported= */ true,
/* autoEnabled= */ true,
/* telephonySupported= */ true,
/* locationSupported= */ true);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
mController.setChecked(false);
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(false)
.build();
verify(mTimeManager).updateTimeZoneConfiguration(configuration);
}
private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig(
boolean autoSupported, boolean autoEnabled, boolean telephonySupported) {
return createCapabilitiesAndConfig(autoSupported, autoEnabled, telephonySupported, false);
}
private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig(
boolean autoSupported, boolean autoEnabled, boolean telephonySupported,
boolean locationSupported) {
TimeZoneDetectorStatus status = new TimeZoneDetectorStatus(DETECTOR_STATUS_RUNNING,
new TelephonyTimeZoneAlgorithmStatus(
telephonySupported ? DETECTION_ALGORITHM_STATUS_RUNNING
@@ -253,12 +306,14 @@ public class AutoTimeZonePreferenceControllerTest {
TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(UserHandle.SYSTEM)
.setConfigureAutoDetectionEnabledCapability(configureAutoDetectionEnabledCapability)
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(Capabilities.CAPABILITY_NOT_SUPPORTED)
.setConfigureGeoDetectionEnabledCapability(
locationSupported ? Capabilities.CAPABILITY_POSSESSED
: Capabilities.CAPABILITY_NOT_SUPPORTED)
.setSetManualTimeZoneCapability(Capabilities.CAPABILITY_POSSESSED)
.build();
TimeZoneConfiguration config = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(autoEnabled)
.setGeoDetectionEnabled(false)
.setGeoDetectionEnabled(locationSupported)
.build();
return new TimeZoneCapabilitiesAndConfig(status, capabilities, config);
}

View File

@@ -25,6 +25,8 @@ import static android.app.time.DetectorStatusTypes.DETECTOR_STATUS_RUNNING;
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_PRESENT;
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_READY;
import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -43,11 +45,17 @@ import android.app.time.TimeZoneConfiguration;
import android.app.time.TimeZoneDetectorStatus;
import android.content.Context;
import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.flags.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -62,9 +70,14 @@ import org.robolectric.annotation.Config;
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class LocationTimeZoneDetectionPreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private TimeManager mTimeManager;
private Context mContext;
private SwitchPreference mPreference;
private LocationTimeZoneDetectionPreferenceController mController;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private InstrumentedPreferenceFragment mFragment;
@@ -76,6 +89,9 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager);
mController = new LocationTimeZoneDetectionPreferenceController(mContext);
mController.setFragment(mFragment);
mPreference = new SwitchPreference(mContext);
mPreference.setKey("location_time_zone_detection");
}
@Test
@@ -114,6 +130,17 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
verify(mTimeManager, never()).updateTimeZoneConfiguration(any());
}
@Test
@EnableFlags({Flags.FLAG_REVAMP_TOGGLES})
public void flagRevampTogglesOn_toggleOff_automaticTimeZone_disablesLocationToggle() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
createTimeZoneCapabilitiesAndConfig(/* useLocationEnabled= */ true,
CAPABILITY_POSSESSED, /* setAutoDetectionEnabled= */ false);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
}
@Test
public void setChecked_withFalse_shouldUpdateSetting() {
boolean useLocationEnabled = false;
@@ -181,7 +208,14 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
private static TimeZoneCapabilitiesAndConfig createTimeZoneCapabilitiesAndConfig(
boolean useLocationEnabled,
@CapabilityState int configureGeoDetectionEnabledCapability) {
return createTimeZoneCapabilitiesAndConfig(useLocationEnabled,
configureGeoDetectionEnabledCapability, /* setAutoDetectionEnabled= */ true);
}
private static TimeZoneCapabilitiesAndConfig createTimeZoneCapabilitiesAndConfig(
boolean useLocationEnabled,
@CapabilityState int configureGeoDetectionEnabledCapability,
boolean setAutoDetectionEnabled) {
// Create a status that matches the user's capability state.
LocationTimeZoneAlgorithmStatus locationAlgorithmStatus;
switch (configureGeoDetectionEnabledCapability) {
@@ -213,7 +247,7 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
.build();
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.setAutoDetectionEnabled(setAutoDetectionEnabled)
.setGeoDetectionEnabled(true)
.build();

View File

@@ -23,11 +23,16 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.Intent;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import com.android.settings.flags.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -41,6 +46,9 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class TimeFormatPreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private UpdateTimeAndDateCallback mCallback;
@@ -97,6 +105,7 @@ public class TimeFormatPreferenceControllerTest {
}
@Test
@DisableFlags({Flags.FLAG_REVAMP_TOGGLES})
public void updateState_autoSet_shouldNotEnablePreference() {
Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24, null);