Main location switch toggle off warning.
Bug: 193048804
Test: unit tests and manual test.
Change-Id: Icbceb19a4280a742081d4d8b85c04c9c3d924d50
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
index a513719..77fc291 100644
--- a/res/values/overlayable.xml
+++ b/res/values/overlayable.xml
@@ -916,6 +916,7 @@
<item type="string" name="location_state_switch_content_description"/>
<item type="string" name="location_toggle_title"/>
<item type="string" name="location_use_location_title"/>
+ <item type="string" name="location_toggle_off_warning"/>
<item type="string" name="lock_settings_enter_password"/>
<item type="string" name="lock_settings_enter_pattern"/>
<item type="string" name="lock_settings_enter_pin"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7b50652..bd1950b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -827,6 +827,12 @@
<string name="location_settings_title">Location</string>
<!-- Title of location toggle setting [CHAR LIMIT=40] -->
<string name="location_toggle_title">Use location</string>
+ <!-- Warning message when users try to toggle location off [CHAR LIMIT=NONE] -->
+ <string name="location_toggle_off_warning">
+ Turning off Location will turn off location access for all apps, Driver assistance features
+ will still have access. Turning off Driver assistance toggle will stop Driver assistance
+ features from using your location.
+ </string>
<!-- Title of Recent Location Requests setting [CHAR LIMIT=60] -->
<string name="location_settings_recent_requests_title">Recent Location Requests</string>
<!-- Message indicating that no apps have requested location recently [CHAR LIMIT=60] -->
diff --git a/src/com/android/car/settings/location/LocationStateSwitchPreferenceController.java b/src/com/android/car/settings/location/LocationStateSwitchPreferenceController.java
index 9f7468a..c3f3f33 100644
--- a/src/com/android/car/settings/location/LocationStateSwitchPreferenceController.java
+++ b/src/com/android/car/settings/location/LocationStateSwitchPreferenceController.java
@@ -32,6 +32,7 @@
import com.android.car.settings.R;
import com.android.car.settings.common.ClickableWhileDisabledSwitchPreference;
+import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PowerPolicyListener;
import com.android.car.settings.common.PreferenceController;
@@ -85,6 +86,11 @@
protected boolean handlePreferenceChanged(ClickableWhileDisabledSwitchPreference preference,
Object newValue) {
boolean locationEnabled = (Boolean) newValue;
+ if (!locationEnabled) {
+ getFragmentController().showDialog(getConfirmationDialog(),
+ ConfirmationDialogFragment.TAG);
+ return false;
+ }
Utils.updateLocationEnabled(
mContext,
locationEnabled,
@@ -132,4 +138,17 @@
boolean enabled) {
preference.setEnabled(enabled);
}
+
+ private ConfirmationDialogFragment getConfirmationDialog() {
+ return new ConfirmationDialogFragment.Builder(getContext())
+ .setMessage(mContext.getString(R.string.location_toggle_off_warning))
+ .setPositiveButton(android.R.string.ok, arguments -> {
+ Utils.updateLocationEnabled(
+ mContext,
+ false,
+ UserHandle.myUserId(),
+ Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
+ })
+ .build();
+ }
}
diff --git a/tests/unit/src/com/android/car/settings/location/LocationStateSwitchPreferenceControllerTest.java b/tests/unit/src/com/android/car/settings/location/LocationStateSwitchPreferenceControllerTest.java
index 883f726..729f015 100644
--- a/tests/unit/src/com/android/car/settings/location/LocationStateSwitchPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/car/settings/location/LocationStateSwitchPreferenceControllerTest.java
@@ -19,13 +19,18 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AlertDialog;
import android.car.drivingstate.CarUxRestrictions;
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.location.LocationManager;
import android.os.UserHandle;
@@ -34,13 +39,18 @@
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
import com.android.car.settings.common.ClickableWhileDisabledSwitchPreference;
+import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
+import com.android.car.settings.testutils.BaseCarSettingsTestActivity;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -60,6 +70,9 @@
private FragmentController mFragmentController;
@Mock
private LocationManager mLocationManager;
+ @Rule
+ public ActivityTestRule<BaseCarSettingsTestActivity> mActivityTestRule =
+ new ActivityTestRule<>(BaseCarSettingsTestActivity.class);
@Before
public void setUp() {
@@ -94,23 +107,78 @@
}
@Test
- public void onPreferenceClicked_locationDisabled_shouldEnable() {
+ public void onPreferenceClicked_locationDisabled_shouldEnable_notShowDialog() {
initializePreference(/* checked= */ false, /* enabled= */ true);
mSwitchPreference.performClick();
assertThat(mSwitchPreference.isChecked()).isTrue();
verify(mLocationManager).setLocationEnabledForUser(/* enabled= */ true, mUserHandle);
+ verify(mFragmentController, never()).showDialog(any(ConfirmationDialogFragment.class),
+ any());
}
@Test
- public void onPreferenceClicked_locationEnabled_shouldDisable() {
+ public void onPreferenceClicked_locationEnabled_shouldStayEnable_showDialog() {
initializePreference(/* checked= */ true, /* enabled= */ true);
mSwitchPreference.performClick();
- assertThat(mSwitchPreference.isChecked()).isFalse();
- verify(mLocationManager).setLocationEnabledForUser(/* enabled= */ false, mUserHandle);
+ assertThat(mSwitchPreference.isChecked()).isTrue();
+ verify(mLocationManager, never()).setLocationEnabledForUser(/* enabled= */ anyBoolean(),
+ any());
+ verify(mFragmentController).showDialog(any(ConfirmationDialogFragment.class),
+ eq(ConfirmationDialogFragment.TAG));
+ }
+
+ @Test
+ public void confirmDialog_turnOffLocation() throws Throwable {
+ initializePreference(/* checked= */ true, /* enabled= */ true);
+
+ mSwitchPreference.performClick();
+
+ // Capture the dialog that is shown on toggle.
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mFragmentController).showDialog(dialogCaptor.capture(),
+ eq(ConfirmationDialogFragment.TAG));
+
+ // Show the captured dialog on press the confirmation button.
+ ConfirmationDialogFragment dialog = dialogCaptor.getValue();
+ assertThat(dialogCaptor).isNotNull();
+ AlertDialog alertDialog = showDialog(dialog);
+ mActivityTestRule.runOnUiThread(() -> {
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+ verify(mLocationManager).setLocationEnabledForUser(/* enabled= */ false,
+ mUserHandle);
+ }
+
+ @Test
+ public void cancelDialog_LocationStaysOn() throws Throwable {
+ initializePreference(/* checked= */ true, /* enabled= */ true);
+
+ mSwitchPreference.performClick();
+
+ // Capture the dialog that is shown on toggle.
+ ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
+ ConfirmationDialogFragment.class);
+ verify(mFragmentController).showDialog(dialogCaptor.capture(),
+ eq(ConfirmationDialogFragment.TAG));
+
+ // Show the captured dialog on press the confirmation button.
+ ConfirmationDialogFragment dialog = dialogCaptor.getValue();
+ assertThat(dialogCaptor).isNotNull();
+ AlertDialog alertDialog = showDialog(dialog);
+ mActivityTestRule.runOnUiThread(() -> {
+ alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).performClick();
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+ verify(mLocationManager, never()).setLocationEnabledForUser(/* enabled= */ false,
+ mUserHandle);
}
@Test
@@ -138,4 +206,13 @@
mSwitchPreference.setChecked(checked);
mSwitchPreference.setEnabled(enabled);
}
+
+ private AlertDialog showDialog(ConfirmationDialogFragment dialog) throws Throwable {
+ mActivityTestRule.runOnUiThread(() -> {
+ dialog.show(mActivityTestRule.getActivity().getSupportFragmentManager(),
+ /* tag= */ null);
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ return (AlertDialog) dialog.getDialog();
+ }
}