From 157030dcefd31a36aff8d507bef859e788de55d3 Mon Sep 17 00:00:00 2001 From: Marcelo Arteiro Date: Tue, 11 Mar 2025 14:48:38 +0000 Subject: [PATCH] Pending Location information added to Dark Theme Resolved an issue in Settings where sunset/sunrise dark mode failed silently when a location was unavailable. Now, an error dialog is shown, even if location services are enabled, but a specific location is missing. A footer stating the same issue is now present while the location is pending. Existing banner that appears when Location is disabled is now being removed once Location is turned on. Previously the UI would refresh only after exiting and returning to the preference view. Bug: 324548844 Bug: 402025928 Test: atest UiModeManagerServiceTest Flag: EXEMPT bugfix Change-Id: I914937185f11a686b453f929728b6329ebd05389 --- res/values/strings.xml | 2 + res/xml/dark_mode_settings.xml | 7 ++ ...htDisplayAutoModePreferenceController.java | 2 +- .../display/TwilightLocationDialog.java | 24 ++++++- .../TwilightLocationPreferenceController.java | 8 ++- ...dePendingLocationPreferenceController.java | 69 +++++++++++++++++++ .../DarkModeScheduleSelectorController.java | 8 ++- ...lightLocationPreferenceControllerTest.java | 6 +- ...arkModeScheduleSelectorControllerTest.java | 2 + 9 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 src/com/android/settings/display/darkmode/DarkModePendingLocationPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index a6c6078ae71..4d6e55da329 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3163,6 +3163,8 @@ Device location needed to determine your sunset and sunrise times. Location settings + + Location services are active. Schedule will activate once location is determined. diff --git a/res/xml/dark_mode_settings.xml b/res/xml/dark_mode_settings.xml index f886daf2e5b..0208f6a67f4 100644 --- a/res/xml/dark_mode_settings.xml +++ b/res/xml/dark_mode_settings.xml @@ -65,6 +65,13 @@ settings:searchable="false"/> + + { Log.d(TAG, "clicked forget"); @@ -44,4 +49,17 @@ public class TwilightLocationDialog { .create(); dialog.show(); } + + /** + * This method launches a dialog when users try to use twilight scheduling but the location + * could not be determined. + * @param context The context of the calling activity. + */ + public static void showLocationPending(Context context) { + final AlertDialog dialog = new AlertDialog.Builder(context) + .setPositiveButton(R.string.dlg_ok, null /* listener */) + .setMessage(R.string.twilight_mode_pending_location) + .create(); + dialog.show(); + } } diff --git a/src/com/android/settings/display/TwilightLocationPreferenceController.java b/src/com/android/settings/display/TwilightLocationPreferenceController.java index 9e35fc666c3..1b77939cd74 100644 --- a/src/com/android/settings/display/TwilightLocationPreferenceController.java +++ b/src/com/android/settings/display/TwilightLocationPreferenceController.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.location.LocationManager; +import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; @@ -57,10 +58,15 @@ public class TwilightLocationPreferenceController extends BasePreferenceControll @Override public int getAvailabilityStatus() { - return mLocationManager.isLocationEnabled() ? CONDITIONALLY_UNAVAILABLE + return mLocationManager.isLocationEnabled() ? DISABLED_DEPENDENT_SETTING : AVAILABLE_UNSEARCHABLE; } + @Override + public void updateState(Preference preference) { + preference.setVisible(!mLocationManager.isLocationEnabled()); + } + private void launchLocationSettings() { final Intent intent = new Intent(); intent.setClass(mContext, Settings.LocationSettingsActivity.class); diff --git a/src/com/android/settings/display/darkmode/DarkModePendingLocationPreferenceController.java b/src/com/android/settings/display/darkmode/DarkModePendingLocationPreferenceController.java new file mode 100644 index 00000000000..03264461c2b --- /dev/null +++ b/src/com/android/settings/display/darkmode/DarkModePendingLocationPreferenceController.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 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.display.darkmode; + +import static android.app.UiModeManager.MODE_NIGHT_AUTO; + +import static com.google.common.base.Preconditions.checkNotNull; + +import android.app.UiModeManager; +import android.content.Context; +import android.location.LocationManager; + +import androidx.annotation.NonNull; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.widget.FooterPreference; + +/** Controller for the Twilight location custom footer. */ +public class DarkModePendingLocationPreferenceController extends BasePreferenceController { + private final UiModeManager mUiModeManager; + private final LocationManager mLocationManager; + + public DarkModePendingLocationPreferenceController(@NonNull Context context, + @NonNull String key) { + super(context, key); + mUiModeManager = context.getSystemService(UiModeManager.class); + mLocationManager = context.getSystemService(LocationManager.class); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE_UNSEARCHABLE; + } + + @Override + public void displayPreference(@NonNull PreferenceScreen screen) { + super.displayPreference(screen); + FooterPreference footerPreference = checkNotNull(screen.findPreference(getPreferenceKey())); + footerPreference.setIcon(R.drawable.ic_settings_location_filled); + } + + @Override + public void updateState(Preference preference) { + preference.setVisible(isActive()); + } + + public boolean isActive() { + return mUiModeManager.getNightMode() == MODE_NIGHT_AUTO + && mLocationManager.isLocationEnabled() + && mLocationManager.getLastLocation() == null; + } +} diff --git a/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorController.java b/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorController.java index e122ad06864..faca631742a 100644 --- a/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorController.java +++ b/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorController.java @@ -112,8 +112,12 @@ public class DarkModeScheduleSelectorController extends BasePreferenceController } else if (newMode == mPreference.findIndexOfValue( mContext.getString(R.string.dark_ui_auto_mode_auto))) { if (!mLocationManager.isLocationEnabled()) { - TwilightLocationDialog.show(mContext); - return true; + TwilightLocationDialog.showLocationOff(mContext); + return false; + } + + if (mLocationManager.getLastLocation() == null) { + TwilightLocationDialog.showLocationPending(mContext); } mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_AUTO); } else if (newMode == mPreference.findIndexOfValue( diff --git a/tests/robotests/src/com/android/settings/display/TwilightLocationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TwilightLocationPreferenceControllerTest.java index 983fc519bb9..e5a3e83a28b 100644 --- a/tests/robotests/src/com/android/settings/display/TwilightLocationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/TwilightLocationPreferenceControllerTest.java @@ -16,7 +16,7 @@ package com.android.settings.display; import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; -import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; import static com.google.common.truth.Truth.assertThat; @@ -53,10 +53,10 @@ public class TwilightLocationPreferenceControllerTest { } @Test - public void getAvailabilityStatus_locationEnabled_shouldBeCONDITIONALLY_UNAVAILABLE() { + public void getAvailabilityStatus_locationEnabled_shouldBeDISABLED_DEPENDENT_SETTING() { when(mLocationManager.isLocationEnabled()).thenReturn(true); - assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); } @Test diff --git a/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java index d95635e6437..1003d9d2ad7 100644 --- a/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java @@ -31,6 +31,7 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.content.res.Resources; +import android.location.Location; import android.location.LocationManager; import android.os.PowerManager; @@ -98,6 +99,7 @@ public class DarkModeScheduleSelectorControllerTest { mPreference.setEntryValues(new CharSequence[]{"never", "auto", "custom"}); doNothing().when(mPreference).setValueIndex(anyInt()); when(mLocationManager.isLocationEnabled()).thenReturn(true); + when(mLocationManager.getLastLocation()).thenReturn(new Location("mock")); when(mScreen.findPreference(anyString())).thenReturn(mPreference); when(mUiService.setNightModeActivated(anyBoolean())).thenReturn(true); mController = new DarkModeScheduleSelectorController(mContext, mPreferenceKey);