Changes to location settings for geotz
This change adds a new entry for geolocation-based time zone detection (shorthand: "geotz") to the location settings. The UI code uses information retrieved via the TimeManager API to keep the conditional logic in one place, i.e. to avoid the UI needing to know too much about the various conditions that affect the availability / applicability of the toggle. Screen variations / conditions / other info: Location settings screen: 1) The entry only shows up on a device at all if geotz detection is enabled for the device (currently a compile time setting, off by default). 2) The new entry is hidden on the screen when the user first opens it. To see it, the user has to expand "Advanced". The setting is in the shared (non-GMS) section of the screen. 3) When visible, the entry has a summary that shows the current status: either a reason why the setting is not applicable, or the user's current setting value. 4) Selecting the entry opens a sub-screen. The code included here distinguishes between different cases with the summary message (i.e. the text underneath the entry). See strings.xml for the placeholder text. Some strings will not show up currently, but are included in case the rules change as they are valid possibilities from the TimeManager API. The same changes have been made for the "personal" tab when a work profile is enabled. Location Time Zone Detection settings screen: 1) The toggle is always enabled and always shows the user's current configuration setting. All manual tests run with the geotz feature enabled with: adb shell setprop \ persist.sys.location_time_zone_detection_feature_enabled 1 Bug: 152746236 Test: Manual: build / boot / toggle switch in SettingsUI / inspect output of adb shell dumpsys time_zone_detector Test: Manual: build / boot / install TestDPC / toggle switch in work profile in SettingsUI / inspect output of adb shell dumpsys time_zone_detector Test: m -j30 RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.location.TimeZoneDetectionPreferenceControllerTest" Test: m -j30 RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.location.LocationTimeZoneDetectionPreferenceControllerTest" Test: m -j30 RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.location.TimeZoneDetectionSettingsTest" Change-Id: Ia853d30bc54a113000b30f48776418f262d98358
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user