diff --git a/res/values/strings.xml b/res/values/strings.xml index 8aca71a9dc8..9c87e87aeb8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4092,6 +4092,18 @@ Use location to set time zone + + Device location needed + + To set the time zone using your location, turn on location, then update time zone settings + + Location settings + + Cancel diff --git a/src/com/android/settings/datetime/DateTimeSettings.java b/src/com/android/settings/datetime/DateTimeSettings.java index 469a4c7e1b8..d74847f1411 100644 --- a/src/com/android/settings/datetime/DateTimeSettings.java +++ b/src/com/android/settings/datetime/DateTimeSettings.java @@ -59,6 +59,7 @@ public class DateTimeSettings extends DashboardFragment implements public void onAttach(Context context) { super.onAttach(context); getSettingsLifecycle().addObserver(new TimeChangeListenerMixin(context, this)); + use(LocationTimeZoneDetectionPreferenceController.class).setFragment(this); } @Override @@ -77,6 +78,7 @@ public class DateTimeSettings extends DashboardFragment implements final AutoTimeFormatPreferenceController autoTimeFormatPreferenceController = new AutoTimeFormatPreferenceController( activity, this /* UpdateTimeAndDateCallback */); + controllers.add(autoTimeZonePreferenceController); controllers.add(autoTimePreferenceController); controllers.add(autoTimeFormatPreferenceController); diff --git a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java index 0b0fa27f62c..cb39635cc43 100644 --- a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java +++ b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java @@ -31,6 +31,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; +import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.TogglePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; @@ -46,17 +47,24 @@ public class LocationTimeZoneDetectionPreferenceController extends TogglePreferenceController implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener { + private static final String TAG = "location_time_zone_detection"; + private final TimeManager mTimeManager; private final LocationManager mLocationManager; private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig; + private InstrumentedPreferenceFragment mFragment; private Preference mPreference; - public LocationTimeZoneDetectionPreferenceController(Context context, String key) { - super(context, key); + public LocationTimeZoneDetectionPreferenceController(Context context) { + super(context, TAG); mTimeManager = context.getSystemService(TimeManager.class); mLocationManager = context.getSystemService(LocationManager.class); } + void setFragment(InstrumentedPreferenceFragment fragment) { + mFragment = fragment; + } + @Override public boolean isChecked() { TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = @@ -67,10 +75,17 @@ public class LocationTimeZoneDetectionPreferenceController @Override public boolean setChecked(boolean isChecked) { - TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder() - .setGeoDetectionEnabled(isChecked) - .build(); - return mTimeManager.updateTimeZoneConfiguration(configuration); + if (isChecked && !mLocationManager.isLocationEnabled()) { + new LocationToggleDisabledDialogFragment(mContext) + .show(mFragment.getFragmentManager(), TAG); + // Toggle status is not updated. + return false; + } else { + TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder() + .setGeoDetectionEnabled(isChecked) + .build(); + return mTimeManager.updateTimeZoneConfiguration(configuration); + } } @Override diff --git a/src/com/android/settings/datetime/LocationToggleDisabledDialogFragment.java b/src/com/android/settings/datetime/LocationToggleDisabledDialogFragment.java new file mode 100644 index 00000000000..61d46c67b0a --- /dev/null +++ b/src/com/android/settings/datetime/LocationToggleDisabledDialogFragment.java @@ -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; + } +} diff --git a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java index 68b2990a03b..1262b5045a7 100644 --- a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java @@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.app.time.Capabilities; @@ -36,10 +37,13 @@ import android.location.LocationManager; import android.os.UserHandle; 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.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -53,6 +57,10 @@ public class LocationTimeZoneDetectionPreferenceControllerTest { private LocationManager mLocationManager; private Context mContext; private LocationTimeZoneDetectionPreferenceController mController; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private InstrumentedPreferenceFragment mFragment; + @Mock + private Lifecycle mLifecycle; @Before public void setUp() { @@ -60,11 +68,14 @@ public class LocationTimeZoneDetectionPreferenceControllerTest { mContext = spy(RuntimeEnvironment.application); when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager); when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager); - mController = new LocationTimeZoneDetectionPreferenceController(mContext, "key"); + mController = new LocationTimeZoneDetectionPreferenceController(mContext); + mController.setFragment(mFragment); } @Test - public void setChecked_withTrue_shouldUpdateSetting() { + public void setChecked_withTrue_shouldUpdateSetting_whenLocationIsEnabled() { + when(mLocationManager.isLocationEnabled()).thenReturn(true); + // Simulate the UI being clicked. mController.setChecked(true); @@ -75,6 +86,17 @@ public class LocationTimeZoneDetectionPreferenceControllerTest { 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 public void setChecked_withFalse_shouldUpdateSetting() { // Simulate the UI being clicked.