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
This commit is contained in:
Marcelo Arteiro
2025-03-11 14:48:38 +00:00
parent cf5646c92b
commit 157030dcef
9 changed files with 118 additions and 10 deletions

View File

@@ -3163,6 +3163,8 @@
<string name="twilight_mode_location_off_dialog_message">Device location needed to determine your sunset and sunrise times.</string>
<!-- When location mode is off, twilight scheduling does not function. [CHAR LIMIT=40] -->
<string name="twilight_mode_launch_location">Location settings</string>
<!-- When location mode is on but a location could not be determined, twilight scheduling does not function. [CHAR LIMIT=120] -->
<string name="twilight_mode_pending_location">Location services are active. Schedule will activate once location is determined.</string>
<!-- Dark ui screen-->
<!-- Display settings screen, activation button action for manual mode. [CHAR LIMIT=40] -->

View File

@@ -65,6 +65,13 @@
settings:searchable="false"/>
</PreferenceCategory>
<com.android.settingslib.widget.FooterPreference
android:key="dark_theme_connection_footer"
android:title= "@string/twilight_mode_pending_location"
android:selectable="false"
settings:searchable="false"
settings:controller="com.android.settings.display.darkmode.DarkModePendingLocationPreferenceController" />
<com.android.settingslib.widget.FooterPreference
android:key="dark_theme_custom_bedtime_footer"
android:title="@string/dark_ui_bedtime_footer_summary"

View File

@@ -73,7 +73,7 @@ public class NightDisplayAutoModePreferenceController extends BasePreferenceCont
public final boolean onPreferenceChange(Preference preference, Object newValue) {
if (String.valueOf(ColorDisplayManager.AUTO_MODE_TWILIGHT).equals(newValue)
&& !mLocationManager.isLocationEnabled()) {
TwilightLocationDialog.show(mContext);
TwilightLocationDialog.showLocationOff(mContext);
return true;
}
return mColorDisplayManager.setNightDisplayAutoMode(Integer.parseInt((String) newValue));

View File

@@ -24,14 +24,19 @@ import android.util.Log;
import com.android.settings.R;
import com.android.settings.Settings;
/*
* This class lauches a dialog when users try to use twilight scheduling without
/**
* This class launches a dialog when users try to use twilight scheduling without
* turning on location services
*/
public class TwilightLocationDialog {
public static String TAG = "TwilightLocationDialog";
public static void show(Context context) {
/**
* This method launches a dialog when users try to use twilight scheduling without
* turning on location services.
* @param context The context of the calling activity.
*/
public static void showLocationOff(Context context) {
final AlertDialog dialog = new AlertDialog.Builder(context)
.setPositiveButton(R.string.twilight_mode_launch_location, ((dialog1, which) -> {
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();
}
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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(

View File

@@ -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

View File

@@ -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);