Show pop-up banner when Location is off and user tries to enable GeoTZ.

As of now GeoTZ state remains unchanged even if user enables
Location toggle.

Bug: 152746236
Test: m -j30 RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceControllerTest"
Test: checked manually that dialog opens Location settings page
Change-Id: I5fd3288e9d5a7aac3bc82da6944b4ccd6bb9e0f5
This commit is contained in:
Almaz Mingaleev
2021-03-18 10:30:04 +00:00
parent 8a2e489ac8
commit fcf1fcfe9b
5 changed files with 122 additions and 8 deletions

View File

@@ -4079,6 +4079,18 @@
<!-- [CHAR LIMIT=60] Date&Time settings screen, toggle button title --> <!-- [CHAR LIMIT=60] Date&Time settings screen, toggle button title -->
<string name="location_time_zone_detection_toggle_title">Use location to set time zone</string> <string name="location_time_zone_detection_toggle_title">Use location to set time zone</string>
<!-- [CHAR LIMIT=60] Date&Time settings screen, title of the dialog shown when user tries to
enable GeoTZ when Location toggle is off. -->
<string name="location_time_zone_detection_location_is_off_dialog_title">Device location needed</string>
<!-- [CHAR LIMIT=NONE] Date&Time settings screen, message on the dialog shown when user tries to
enable GeoTZ when Location toggle is off. -->
<string name="location_time_zone_detection_location_is_off_dialog_message">To set the time zone using your location, turn on location, then update time zone settings</string>
<!-- [CHAR LIMIT=30] Date&Time settings screen, button on a dialog shown when user tries to
enable GeoTZ, but Location toggle is off, which leads to Location settings page. -->
<string name="location_time_zone_detection_location_is_off_dialog_ok_button">Location settings</string>
<!-- [CHAR LIMIT=30] Date&Time settings screen, button on a dialog shown when user tries to
enable GeoTZ, but Location toggle is off, which closes the dialog. -->
<string name="location_time_zone_detection_location_is_off_dialog_cancel_button">Cancel</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not <!-- [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 applicable due to other settings like the "automatic time zone detection enabled" setting
being set to "off". --> being set to "off". -->

View File

@@ -59,6 +59,7 @@ public class DateTimeSettings extends DashboardFragment implements
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
getSettingsLifecycle().addObserver(new TimeChangeListenerMixin(context, this)); getSettingsLifecycle().addObserver(new TimeChangeListenerMixin(context, this));
use(LocationTimeZoneDetectionPreferenceController.class).setFragment(this);
} }
@Override @Override
@@ -77,6 +78,7 @@ public class DateTimeSettings extends DashboardFragment implements
final AutoTimeFormatPreferenceController autoTimeFormatPreferenceController = final AutoTimeFormatPreferenceController autoTimeFormatPreferenceController =
new AutoTimeFormatPreferenceController( new AutoTimeFormatPreferenceController(
activity, this /* UpdateTimeAndDateCallback */); activity, this /* UpdateTimeAndDateCallback */);
controllers.add(autoTimeZonePreferenceController); controllers.add(autoTimeZonePreferenceController);
controllers.add(autoTimePreferenceController); controllers.add(autoTimePreferenceController);
controllers.add(autoTimeFormatPreferenceController); controllers.add(autoTimeFormatPreferenceController);

View File

@@ -31,6 +31,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -46,17 +47,24 @@ public class LocationTimeZoneDetectionPreferenceController
extends TogglePreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener { implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener {
private static final String TAG = "location_time_zone_detection";
private final TimeManager mTimeManager; private final TimeManager mTimeManager;
private final LocationManager mLocationManager; private final LocationManager mLocationManager;
private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig; private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig;
private InstrumentedPreferenceFragment mFragment;
private Preference mPreference; private Preference mPreference;
public LocationTimeZoneDetectionPreferenceController(Context context, String key) { public LocationTimeZoneDetectionPreferenceController(Context context) {
super(context, key); super(context, TAG);
mTimeManager = context.getSystemService(TimeManager.class); mTimeManager = context.getSystemService(TimeManager.class);
mLocationManager = context.getSystemService(LocationManager.class); mLocationManager = context.getSystemService(LocationManager.class);
} }
void setFragment(InstrumentedPreferenceFragment fragment) {
mFragment = fragment;
}
@Override @Override
public boolean isChecked() { public boolean isChecked() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
@@ -67,10 +75,17 @@ public class LocationTimeZoneDetectionPreferenceController
@Override @Override
public boolean setChecked(boolean isChecked) { public boolean setChecked(boolean isChecked) {
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder() if (isChecked && !mLocationManager.isLocationEnabled()) {
.setGeoDetectionEnabled(isChecked) new LocationToggleDisabledDialogFragment(mContext)
.build(); .show(mFragment.getFragmentManager(), TAG);
return mTimeManager.updateTimeZoneConfiguration(configuration); // Toggle status is not updated.
return false;
} else {
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setGeoDetectionEnabled(isChecked)
.build();
return mTimeManager.updateTimeZoneConfiguration(configuration);
}
} }
@Override @Override

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2021 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.AlertDialog;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
/**
* Dialog shown when user tries to enable GeoTZ with Location toggle disabled.
*/
public class LocationToggleDisabledDialogFragment extends InstrumentedDialogFragment {
private final Context mContext;
public LocationToggleDisabledDialogFragment(Context context) {
mContext = context;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.location_time_zone_detection_location_is_off_dialog_title)
.setIcon(R.drawable.ic_warning_24dp)
.setMessage(R.string.location_time_zone_detection_location_is_off_dialog_message)
.setPositiveButton(
R.string.location_time_zone_detection_location_is_off_dialog_ok_button,
(dialog, which) -> {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
})
.setNegativeButton(
R.string.location_time_zone_detection_location_is_off_dialog_cancel_button,
(dialog, which) -> {})
.create();
}
@Override
public int getMetricsCategory() {
return SettingsEnums.DIALOG_DATE_TIME_ENABLE_GEOTZ_WITH_DISABLED_LOCATION;
}
}

View File

@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.time.Capabilities; import android.app.time.Capabilities;
@@ -36,10 +37,13 @@ import android.location.LocationManager;
import android.os.UserHandle; import android.os.UserHandle;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
@@ -53,6 +57,10 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
private LocationManager mLocationManager; private LocationManager mLocationManager;
private Context mContext; private Context mContext;
private LocationTimeZoneDetectionPreferenceController mController; private LocationTimeZoneDetectionPreferenceController mController;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private InstrumentedPreferenceFragment mFragment;
@Mock
private Lifecycle mLifecycle;
@Before @Before
public void setUp() { public void setUp() {
@@ -60,11 +68,14 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
mContext = spy(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager); when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager);
when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager); when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager);
mController = new LocationTimeZoneDetectionPreferenceController(mContext, "key"); mController = new LocationTimeZoneDetectionPreferenceController(mContext);
mController.setFragment(mFragment);
} }
@Test @Test
public void setChecked_withTrue_shouldUpdateSetting() { public void setChecked_withTrue_shouldUpdateSetting_whenLocationIsEnabled() {
when(mLocationManager.isLocationEnabled()).thenReturn(true);
// Simulate the UI being clicked. // Simulate the UI being clicked.
mController.setChecked(true); mController.setChecked(true);
@@ -75,6 +86,17 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
verify(mTimeManager).updateTimeZoneConfiguration(expectedConfiguration); verify(mTimeManager).updateTimeZoneConfiguration(expectedConfiguration);
} }
@Test
public void setChecked_withTrue_shouldDoNothing_whenLocationIsDisabled() {
when(mLocationManager.isLocationEnabled()).thenReturn(false);
// Simulate the UI being clicked.
mController.setChecked(true);
// Verify the TimeManager was not called.
verifyZeroInteractions(mTimeManager);
}
@Test @Test
public void setChecked_withFalse_shouldUpdateSetting() { public void setChecked_withFalse_shouldUpdateSetting() {
// Simulate the UI being clicked. // Simulate the UI being clicked.