Merge "Changes to location settings for geotz"

This commit is contained in:
Neil Fuller
2020-10-23 09:40:45 +00:00
committed by Android (Google) Code Review
12 changed files with 751 additions and 0 deletions

View File

@@ -4002,6 +4002,32 @@
<!-- [CHAR LIMIT=50] Location settings screen, sub category for location services for managed profile -->
<string name="managed_profile_location_services">Location services for work</string>
<!-- [CHAR LIMIT=60] Location settings screen, screen title -->
<string name="location_time_zone_detection_screen_title">Location time zone detection</string>
<!-- [CHAR LIMIT=50] Location settings screen, title for the setting that control whether the
device can use its location for time zone detection. -->
<string name="location_time_zone_detection_enabled_title">Location time zone detection</string>
<!-- [CHAR LIMIT=NONE] Preference description text for location time zone detection -->
<string name="location_time_zone_detection_enabled_description">Allows the device\u2019s location to be used to detect the current time zone. Other location settings such as Wi\u2011Fi scanning can affect the accuracy of time zone detection.</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is on -->
<string name="location_time_zone_detection_on">On</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is off -->
<string name="location_time_zone_detection_off">Off</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not
applicable due to other settings like the "automatic time zone detection enabled" setting
being set to "off". -->
<string name="location_time_zone_detection_auto_is_off">Automatic time zone detection is disabled</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not
applicable for the user for unspecified reasons. More specific messages are used when there
is a clear reason. -->
<string name="location_time_zone_detection_not_applicable">Location time zone detection is disabled</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not supported -->
<string name="location_time_zone_detection_not_supported">Location time zone detection is not supported</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not
allowed for the user, e.g. because of device policy -->
<string name="location_time_zone_detection_not_allowed">Location time zone detection changes are not allowed</string>
<!-- [CHAR LIMIT=30] Security & location settings screen, setting check box label for Google location service (cell ID, wifi, etc.) -->
<string name="location_network_based">Wi\u2011Fi &amp; mobile network location</string>
<!-- [CHAR LIMIT=130] Security & location settings screen, setting summary for Google location service check box-->

View File

@@ -65,6 +65,13 @@
settings:forWork="true"
settings:useAdminDisabledSummary="true"/>
<!-- This preference gets removed if location-based time zone detection is not supported -->
<Preference
android:key="location_time_zone_detection"
android:title="@string/location_time_zone_detection_screen_title"
settings:controller="com.android.settings.location.LocationTimeZoneDetectionPreferenceController"
android:fragment="com.android.settings.location.TimeZoneDetectionSettings" />
<PreferenceCategory
android:key="location_services"
android:layout="@layout/preference_category_no_label"

View File

@@ -51,6 +51,13 @@
android:fragment="com.android.settings.location.ScanningSettings"
settings:controller="com.android.settings.location.LocationScanningPreferenceController"/>
<!-- This preference gets removed if location-based time zone detection is not supported -->
<Preference
android:key="location_time_zone_detection"
android:title="@string/location_time_zone_detection_screen_title"
settings:controller="com.android.settings.location.LocationTimeZoneDetectionPreferenceController"
android:fragment="com.android.settings.location.TimeZoneDetectionSettings" />
<PreferenceCategory
android:key="location_services"
android:layout="@layout/preference_category_no_label"

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 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"
android:title="@string/location_time_zone_detection_screen_title">
<SwitchPreference
android:title="@string/location_time_zone_detection_enabled_title"
android:summary="@string/location_time_zone_detection_enabled_description"
android:key="location_time_zone_detection_enabled" />
</PreferenceScreen>

View File

@@ -58,6 +58,8 @@ public class LocationPersonalSettings extends DashboardFragment {
RecentLocationRequestPreferenceController.class);
controller.init(this);
controller.setProfileType(profileType);
use(LocationTimeZoneDetectionPreferenceController.class);
}
@Override

View File

@@ -88,6 +88,7 @@ public class LocationSettings extends DashboardFragment {
use(LocationFooterPreferenceController.class).init(this);
use(LocationForWorkPreferenceController.class).init(this);
use(LocationServiceForWorkPreferenceController.class).init(this);
use(LocationTimeZoneDetectionPreferenceController.class);
}
@Override

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2020 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.location;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import android.app.time.TimeManager;
import android.app.time.TimeZoneCapabilities;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
import android.content.Context;
import android.location.LocationManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.concurrent.Executor;
/**
* The controller for the "location time zone detection" entry in the Location settings
* screen.
*/
public class LocationTimeZoneDetectionPreferenceController
extends BasePreferenceController
implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener {
private final TimeManager mTimeManager;
private final LocationManager mLocationManager;
private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig;
private Preference mPreference;
public LocationTimeZoneDetectionPreferenceController(Context context, String key) {
super(context, key);
mTimeManager = context.getSystemService(TimeManager.class);
mLocationManager = context.getSystemService(LocationManager.class);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public void onStart() {
// Register for updates to the user's time zone capabilities or configuration which could
// require UI changes.
Executor mainExecutor = mContext.getMainExecutor();
mTimeManager.addTimeZoneDetectorListener(mainExecutor, this);
// Setup the initial state of the summary.
refreshUi();
}
@Override
public void onStop() {
mTimeManager.removeTimeZoneDetectorListener(this);
}
@Override
public int getAvailabilityStatus() {
TimeZoneCapabilities timeZoneCapabilities =
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.
if (capability == CAPABILITY_NOT_SUPPORTED || capability == CAPABILITY_NOT_ALLOWED) {
return UNSUPPORTED_ON_DEVICE;
} else if (capability == CAPABILITY_NOT_APPLICABLE || capability == CAPABILITY_POSSESSED) {
return AVAILABLE;
} else {
throw new IllegalStateException("Unknown capability=" + capability);
}
}
@Override
public CharSequence getSummary() {
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false);
TimeZoneCapabilities capabilities = timeZoneCapabilitiesAndConfig.getCapabilities();
int configureGeoDetectionEnabledCapability =
capabilities.getConfigureGeoDetectionEnabledCapability();
TimeZoneConfiguration configuration = timeZoneCapabilitiesAndConfig.getConfiguration();
int summaryResId;
if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_SUPPORTED) {
// The preference should not be visible, but text is referenced in case this changes.
summaryResId = R.string.location_time_zone_detection_not_supported;
} else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_ALLOWED) {
// The preference should not be visible, but text is referenced in case this changes.
summaryResId = R.string.location_time_zone_detection_not_allowed;
} else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_APPLICABLE) {
// The TimeZoneCapabilities deliberately doesn't provide information about why the user
// doesn't have the capability, but the user's "location enabled" being off and the
// global automatic detection setting will always be considered overriding reasons why
// location time zone detection cannot be used.
if (!mLocationManager.isLocationEnabled()) {
summaryResId = R.string.location_app_permission_summary_location_off;
} else if (!configuration.isAutoDetectionEnabled()) {
summaryResId = R.string.location_time_zone_detection_auto_is_off;
} else {
// This is in case there are other reasons in future why location time zone
// detection is not applicable.
summaryResId = R.string.location_time_zone_detection_not_applicable;
}
} else if (configureGeoDetectionEnabledCapability == CAPABILITY_POSSESSED) {
boolean isGeoDetectionEnabled = configuration.isGeoDetectionEnabled();
summaryResId = isGeoDetectionEnabled
? R.string.location_time_zone_detection_on
: R.string.location_time_zone_detection_off;
} else {
// This is unexpected: getAvailabilityStatus() should ensure that the UI element isn't
// even shown for known cases, or the capability is unknown.
throw new IllegalStateException("Unexpected configureGeoDetectionEnabledCapability="
+ configureGeoDetectionEnabledCapability);
}
return mContext.getString(summaryResId);
}
@Override
public void onChange() {
refreshUi();
}
private void refreshUi() {
// Force a refresh of cached user capabilities and config before refreshing the summary.
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ true);
refreshSummary(mPreference);
}
/**
* Returns the current user capabilities and configuration. {@code forceRefresh} can be {@code
* true} to discard any cached copy.
*/
private TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig(boolean forceRefresh) {
if (forceRefresh || mTimeZoneCapabilitiesAndConfig == null) {
mTimeZoneCapabilitiesAndConfig = mTimeManager.getTimeZoneCapabilitiesAndConfig();
}
return mTimeZoneCapabilitiesAndConfig;
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2020 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.location;
import android.app.time.TimeManager;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
import android.content.Context;
import android.text.TextUtils;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
/**
* The controller for the "location time zone detection" switch on the location time zone detection
* screen.
*/
public class TimeZoneDetectionPreferenceController extends AbstractPreferenceController {
private static final String KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED =
"location_time_zone_detection_enabled";
private final TimeManager mTimeManager;
public TimeZoneDetectionPreferenceController(Context context) {
super(context);
mTimeManager = context.getSystemService(TimeManager.class);
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED;
}
@Override
public void updateState(Preference preference) {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
mTimeManager.getTimeZoneCapabilitiesAndConfig();
setPreferenceUiState((SwitchPreference) preference, capabilitiesAndConfig);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(preference.getKey(), KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED)) {
SwitchPreference switchPreference = (SwitchPreference) preference;
final boolean switchState = switchPreference.isChecked();
// Update the settings to match the UI.
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setGeoDetectionEnabled(switchState)
.build();
// The return value is ignored, but the current state is read back below ensuring it
// does not matter.
mTimeManager.updateTimeZoneConfiguration(configuration);
// Configure the UI preference state from the configuration. This means that even in the
// unlikely event that the update failed, the UI should reflect current settings.
setPreferenceUiState(switchPreference, mTimeManager.getTimeZoneCapabilitiesAndConfig());
return true;
}
return false;
}
/**
* Sets the switch's checked state from the supplied {@link TimeZoneCapabilitiesAndConfig}.
*/
@android.annotation.UiThread
private void setPreferenceUiState(SwitchPreference preference,
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig) {
TimeZoneConfiguration configuration = timeZoneCapabilitiesAndConfig.getConfiguration();
boolean checked = configuration.isGeoDetectionEnabled();
preference.setChecked(checked);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2020 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.location;
import android.app.settings.SettingsEnums;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
/**
* The controller for the "location time zone detection" screen.
*/
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class TimeZoneDetectionSettings extends DashboardFragment {
private static final String TAG = "LTZDetectionSettings";
@Override
public int getMetricsCategory() {
return SettingsEnums.LOCATION_TIME_ZONE_DETECTION;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.location_time_zone_detection;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new TimeZoneDetectionPreferenceController(context));
return controllers;
}
/**
* For Search.
*/
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.location_time_zone_detection) {
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
return buildPreferenceControllers(context);
}
};
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2018 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.location;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.time.TimeManager;
import android.app.time.TimeZoneCapabilities;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
import android.content.Context;
import android.location.LocationManager;
import android.os.UserHandle;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class LocationTimeZoneDetectionPreferenceControllerTest {
@Mock
private TimeManager mTimeManager;
@Mock
private LocationManager mLocationManager;
private Context mContext;
private LocationTimeZoneDetectionPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager);
when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager);
mController = new LocationTimeZoneDetectionPreferenceController(mContext, "key");
}
@Test
public void testLocationTimeZoneDetection_supported_shouldBeShown() {
TimeZoneCapabilities capabilities =
createTimeZoneCapabilities(/* geoDetectionSupported= */ true);
TimeZoneConfiguration configuration = createTimeZoneConfig(/* geoDetectionEnabled= */ true);
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
new TimeZoneCapabilitiesAndConfig(capabilities, configuration);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void testLocationTimeZoneDetection_unsupported_shouldNotBeShown() {
TimeZoneCapabilities capabilities =
createTimeZoneCapabilities(/* geoDetectionSupported= */ false);
TimeZoneConfiguration configuration = createTimeZoneConfig(/* geoDetectionEnabled= */ true);
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
new TimeZoneCapabilitiesAndConfig(capabilities, configuration);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
assertThat(mController.isAvailable()).isFalse();
}
/**
* Tests that the summary is set in just one of many cases. Exhaustive testing would be brittle.
*/
@Test
public void testLocationTimeZoneDetection_summary_geoDetectionEnabled() {
TimeZoneCapabilities capabilities =
createTimeZoneCapabilities(/* geoDetectionSupported= */ true);
TimeZoneConfiguration configuration = createTimeZoneConfig(/* geoDetectionEnabled= */ true);
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
new TimeZoneCapabilitiesAndConfig(capabilities, configuration);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
assertThat(mController.getSummary()).isEqualTo(
mContext.getString(R.string.location_time_zone_detection_on));
}
private static TimeZoneCapabilities createTimeZoneCapabilities(boolean geoDetectionSupported) {
UserHandle arbitraryUserHandle = UserHandle.of(123);
int geoDetectionCapability =
geoDetectionSupported ? CAPABILITY_POSSESSED : CAPABILITY_NOT_SUPPORTED;
return new TimeZoneCapabilities.Builder(arbitraryUserHandle)
.setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setConfigureGeoDetectionEnabledCapability(geoDetectionCapability)
.setSuggestManualTimeZoneCapability(CAPABILITY_NOT_APPLICABLE)
.build();
}
private static TimeZoneConfiguration createTimeZoneConfig(boolean geoDetectionEnabled) {
return new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.setGeoDetectionEnabled(geoDetectionEnabled)
.build();
}
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright (C) 2017 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.location;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.time.TimeManager;
import android.app.time.TimeZoneCapabilities;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
import android.content.ContentResolver;
import android.content.Context;
import android.os.UserHandle;
import androidx.preference.SwitchPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class TimeZoneDetectionPreferenceControllerTest {
@Mock
private SwitchPreference mPreference;
@Mock
private TimeManager mTimeManager;
private Context mContext;
private ContentResolver mContentResolver;
private TimeZoneDetectionPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContentResolver = RuntimeEnvironment.application.getContentResolver();
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager);
mController = new TimeZoneDetectionPreferenceController(mContext);
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
}
@Test
public void updateState_locationDetectionEnabled_shouldCheckPreference() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
createTimeZoneCapabilitiesAndConfig(/* geoDetectionEnabled= */ true);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
mController.updateState(mPreference);
verify(mPreference).setChecked(true);
}
@Test
public void updateState_locationDetectionDisabled_shouldUncheckPreference() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
createTimeZoneCapabilitiesAndConfig(/* geoDetectionEnabled= */ false);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
mController.updateState(mPreference);
verify(mPreference).setChecked(false);
}
@Test
public void handlePreferenceTreeClick_unchecked_shouldDisableGeoDetection() {
// getTimeZoneCapabilitiesAndConfig() is called after updateTimeZoneConfiguration() to
// obtain the new state.
boolean postUpdateResponseValue = false;
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createTimeZoneCapabilitiesAndConfig(
/* geoDetectionEnabled= */postUpdateResponseValue);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
// Simulate the UI being clicked.
boolean preferenceCheckedState = false;
when(mPreference.isChecked()).thenReturn(preferenceCheckedState);
mController.handlePreferenceTreeClick(mPreference);
// Verify the TimeManager was updated with the UI value.
TimeZoneConfiguration expectedConfiguration = new TimeZoneConfiguration.Builder()
.setGeoDetectionEnabled(preferenceCheckedState)
.build();
verify(mTimeManager).updateTimeZoneConfiguration(expectedConfiguration);
// Confirm the UI state was reset using the getTimeZoneCapabilitiesAndConfig() response.
verify(mPreference).setChecked(postUpdateResponseValue);
}
@Test
public void handlePreferenceTreeClick_checked_shouldEnableGeoDetection() {
// getTimeZoneCapabilitiesAndConfig() is called after updateTimeZoneConfiguration() to
// obtain the new state.
boolean postUpdateResponseValue = true;
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createTimeZoneCapabilitiesAndConfig(
/* geoDetectionEnabled= */ postUpdateResponseValue);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
// Simulate the UI being clicked.
boolean preferenceCheckedState = true;
when(mPreference.isChecked()).thenReturn(preferenceCheckedState);
mController.handlePreferenceTreeClick(mPreference);
// Verify the TimeManager was updated with the UI value.
TimeZoneConfiguration expectedConfiguration = new TimeZoneConfiguration.Builder()
.setGeoDetectionEnabled(preferenceCheckedState)
.build();
verify(mTimeManager).updateTimeZoneConfiguration(expectedConfiguration);
// Confirm the UI state was reset using the getTimeZoneCapabilitiesAndConfig() response.
verify(mPreference).setChecked(postUpdateResponseValue);
}
@Test
public void handlePreferenceTreeClick_checked_shouldEnableGeoDetection_updateRefused() {
// getTimeZoneCapabilitiesAndConfig() is called after updateTimeZoneConfiguration() to
// obtain the new state.
boolean postUpdateResponseValue = false;
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createTimeZoneCapabilitiesAndConfig(
/* geoDetectionEnabled= */ postUpdateResponseValue);
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
// Simulate the UI being clicked.
boolean preferenceCheckedState = true;
when(mPreference.isChecked()).thenReturn(preferenceCheckedState);
mController.handlePreferenceTreeClick(mPreference);
// Verify the TimeManager was updated with the UI value.
TimeZoneConfiguration expectedConfiguration = new TimeZoneConfiguration.Builder()
.setGeoDetectionEnabled(preferenceCheckedState)
.build();
verify(mTimeManager).updateTimeZoneConfiguration(expectedConfiguration);
// Confirm the UI state was reset using the getTimeZoneCapabilitiesAndConfig() response.
verify(mPreference).setChecked(postUpdateResponseValue);
}
private static TimeZoneCapabilitiesAndConfig createTimeZoneCapabilitiesAndConfig(
boolean geoDetectionEnabled) {
UserHandle arbitraryUserHandle = UserHandle.of(123);
TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(arbitraryUserHandle)
.setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setSuggestManualTimeZoneCapability(CAPABILITY_NOT_APPLICABLE)
.build();
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.setGeoDetectionEnabled(geoDetectionEnabled)
.build();
return new TimeZoneCapabilitiesAndConfig(capabilities, configuration);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2017 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.location;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.SearchIndexableResource;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class TimeZoneDetectionSettingsTest {
private Context mContext;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
}
@Test
public void searchProvider_shouldIndexDefaultXml() {
final List<SearchIndexableResource> sir =
TimeZoneDetectionSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
mContext, /* enabled= */ true);
assertThat(sir).hasSize(1);
assertThat(sir.get(0).xmlResId).isEqualTo(R.xml.location_time_zone_detection);
}
}