Add dark theme custom type into the dark theme settings page

Also fix some test cases.

I'd prefer using Robolectric shadows rather than mocking Android
framework classes. However, I can't do that in this CL due to the
lack of multiple shadow classes support.

Test: make RunSettingsRoboTests -j56
      ROBOTEST_FILTER=com.android.settings.display.darkmode.*
Bug: 215182463
Change-Id: If557d2933927a5dd0fadd3f6db6bb6f0ab7dd5ee
This commit is contained in:
Steven Ng
2022-01-17 17:25:50 +00:00
parent 0128837312
commit 3859251be0
16 changed files with 698 additions and 108 deletions

View File

@@ -0,0 +1,60 @@
/*
* 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 android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
/** Manages Digital Wellbeing bedtime settings' intents. */
public final class BedtimeSettings {
@VisibleForTesting
public static final String ACTION_BEDTIME_SETTINGS = "android.settings.BEDTIME_SETTINGS";
private final Context mContext;
private final PackageManager mPackageManager;
private final String mWellbeingPackage;
public BedtimeSettings(Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
mWellbeingPackage = mContext.getResources().getString(
com.android.internal.R.string.config_defaultWellbeingPackage);
}
/**
* Returns the bedtime settings intent. If the bedtime settings isn't available, returns
* {@code null}.
*/
@Nullable
public Intent getBedtimeSettingsIntent() {
Intent bedtimeSettingsIntent = new Intent(ACTION_BEDTIME_SETTINGS).setPackage(
mWellbeingPackage);
ResolveInfo bedtimeSettingInfo = mPackageManager.resolveActivity(bedtimeSettingsIntent,
PackageManager.MATCH_DEFAULT_ONLY);
if (bedtimeSettingInfo != null && bedtimeSettingInfo.activityInfo.isEnabled()) {
return bedtimeSettingsIntent;
} else {
return null;
}
}
}

View File

@@ -18,7 +18,6 @@ package com.android.settings.display.darkmode;
import android.app.UiModeManager;
import android.content.Context;
import android.content.res.Configuration;
import android.os.PowerManager;
import android.widget.Switch;
import androidx.preference.Preference;
@@ -41,13 +40,11 @@ public class DarkModeActivationPreferenceController extends BasePreferenceContro
private final UiModeManager mUiModeManager;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private PowerManager mPowerManager;
private TimeFormatter mFormat;
private MainSwitchPreference mPreference;
public DarkModeActivationPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPowerManager = context.getSystemService(PowerManager.class);
mUiModeManager = context.getSystemService(UiModeManager.class);
mFormat = new TimeFormatter(context);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
@@ -76,6 +73,13 @@ public class DarkModeActivationPreferenceController extends BasePreferenceContro
? R.string.dark_ui_summary_on_auto_mode_auto
: R.string.dark_ui_summary_off_auto_mode_auto);
} else if (mode == UiModeManager.MODE_NIGHT_CUSTOM) {
if (mUiModeManager.getNightModeCustomType()
== UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
return mContext.getString(isActivated
? R.string.dark_ui_summary_on_auto_mode_custom_bedtime
: R.string.dark_ui_summary_off_auto_mode_custom_bedtime);
}
final LocalTime time = isActivated
? mUiModeManager.getCustomNightModeEnd()
: mUiModeManager.getCustomNightModeStart();

View File

@@ -0,0 +1,68 @@
/*
* 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_CUSTOM_TYPE_BEDTIME;
import android.app.UiModeManager;
import android.content.Context;
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 night mode bedtime custom mode footer. */
public class DarkModeCustomBedtimePreferenceController extends BasePreferenceController {
private final UiModeManager mUiModeManager;
private FooterPreference mFooterPreference;
private BedtimeSettings mBedtimeSettings;
public DarkModeCustomBedtimePreferenceController(Context context, String key) {
super(context, key);
mUiModeManager = context.getSystemService(UiModeManager.class);
mBedtimeSettings = new BedtimeSettings(context);
}
@Override
public int getAvailabilityStatus() {
return mBedtimeSettings.getBedtimeSettingsIntent() == null
? UNSUPPORTED_ON_DEVICE
: AVAILABLE_UNSEARCHABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mFooterPreference = screen.findPreference(getPreferenceKey());
mFooterPreference.setLearnMoreAction(
v -> v.getContext().startActivity(mBedtimeSettings.getBedtimeSettingsIntent()));
mFooterPreference.setLearnMoreText(
mContext.getString(R.string.dark_ui_bedtime_footer_action));
}
@Override
public void updateState(Preference preference) {
if (mUiModeManager.getNightModeCustomType() != MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
preference.setVisible(false);
return;
}
preference.setVisible(true);
}
}

View File

@@ -15,21 +15,20 @@
package com.android.settings.display.darkmode;
import android.app.Dialog;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
import android.app.TimePickerDialog;
import android.app.UiModeManager;
import android.content.Context;
import android.text.TextUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
/**
* Controller for custom mode night mode time settings
*/
@@ -89,7 +88,9 @@ public class DarkModeCustomPreferenceController extends BasePreferenceController
@Override
protected void refreshSummary(Preference preference) {
if (mUiModeManager.getNightMode() != MODE_NIGHT_CUSTOM) {
if (mUiModeManager.getNightMode() != MODE_NIGHT_CUSTOM
|| mUiModeManager.getNightModeCustomType()
!= UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE) {
preference.setVisible(false);
return;
}

View File

@@ -25,6 +25,7 @@ import android.os.Looper;
import android.os.PowerManager;
import android.provider.Settings;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
/**
@@ -64,12 +65,16 @@ public class DarkModeObserver {
callback.run();
mCallback = callback;
final Uri uri = Settings.Secure.getUriFor(Settings.Secure.UI_NIGHT_MODE);
final Uri customType =
Settings.Secure.getUriFor(Settings.Secure.UI_NIGHT_MODE_CUSTOM_TYPE);
final Uri customStart =
Settings.Secure.getUriFor(Settings.Secure.DARK_THEME_CUSTOM_START_TIME);
final Uri customEnd =
Settings.Secure.getUriFor(Settings.Secure.DARK_THEME_CUSTOM_END_TIME);
mContext.getContentResolver()
.registerContentObserver(uri, false, mContentObserver);
mContext.getContentResolver()
.registerContentObserver(customType, false, mContentObserver);
mContext.getContentResolver()
.registerContentObserver(customStart, false, mContentObserver);
mContext.getContentResolver()

View File

@@ -81,13 +81,20 @@ public class DarkModePreference extends PrimarySwitchPreference {
? R.string.dark_ui_summary_on_auto_mode_auto
: R.string.dark_ui_summary_off_auto_mode_auto);
} else if (mode == UiModeManager.MODE_NIGHT_CUSTOM) {
final LocalTime time = active
? mUiModeManager.getCustomNightModeEnd()
: mUiModeManager.getCustomNightModeStart();
final String timeStr = mFormat.of(time);
summary = getContext().getString(active
? R.string.dark_ui_summary_on_auto_mode_custom
: R.string.dark_ui_summary_off_auto_mode_custom, timeStr);
if (mUiModeManager.getNightModeCustomType()
== UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
summary = getContext().getString(active
? R.string.dark_ui_summary_on_auto_mode_custom_bedtime
: R.string.dark_ui_summary_off_auto_mode_custom_bedtime);
} else {
final LocalTime time = active
? mUiModeManager.getCustomNightModeEnd()
: mUiModeManager.getCustomNightModeStart();
final String timeStr = mFormat.of(time);
summary = getContext().getString(active
? R.string.dark_ui_summary_on_auto_mode_custom
: R.string.dark_ui_summary_off_auto_mode_custom, timeStr);
}
} else {
summary = getContext().getString(active
? R.string.dark_ui_summary_on_auto_mode_never

View File

@@ -34,10 +34,13 @@ import com.android.settings.display.TwilightLocationDialog;
public class DarkModeScheduleSelectorController extends BasePreferenceController
implements Preference.OnPreferenceChangeListener {
private static final String TAG = DarkModeScheduleSelectorController.class.getSimpleName();
private final UiModeManager mUiModeManager;
private PowerManager mPowerManager;
private final PowerManager mPowerManager;
private final LocationManager mLocationManager;
private final BedtimeSettings mBedtimeSettings;
private DropDownPreference mPreference;
private LocationManager mLocationManager;
private int mCurrentMode;
public DarkModeScheduleSelectorController(Context context, String key) {
@@ -45,12 +48,19 @@ public class DarkModeScheduleSelectorController extends BasePreferenceController
mUiModeManager = context.getSystemService(UiModeManager.class);
mPowerManager = context.getSystemService(PowerManager.class);
mLocationManager = context.getSystemService(LocationManager.class);
mBedtimeSettings = new BedtimeSettings(context);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
if (mBedtimeSettings.getBedtimeSettingsIntent() != null) {
String[] entries = mContext.getResources().getStringArray(
R.array.dark_ui_scheduler_with_bedtime_preference_titles);
mPreference.setEntries(entries);
mPreference.setEntryValues(entries);
}
}
@Override
@@ -73,7 +83,12 @@ public class DarkModeScheduleSelectorController extends BasePreferenceController
resId = R.string.dark_ui_auto_mode_auto;
break;
case UiModeManager.MODE_NIGHT_CUSTOM:
resId = R.string.dark_ui_auto_mode_custom;
boolean isCustomBedtime = mBedtimeSettings.getBedtimeSettingsIntent() != null
&& mUiModeManager.getNightModeCustomType()
== UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
resId = isCustomBedtime
? R.string.dark_ui_auto_mode_custom_bedtime
: R.string.dark_ui_auto_mode_custom;
break;
default:
resId = R.string.dark_ui_auto_mode_never;
@@ -104,6 +119,9 @@ public class DarkModeScheduleSelectorController extends BasePreferenceController
} else if (newMode == mPreference.findIndexOfValue(
mContext.getString(R.string.dark_ui_auto_mode_custom))) {
mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_CUSTOM);
} else if (newMode == mPreference.findIndexOfValue(
mContext.getString(R.string.dark_ui_auto_mode_custom_bedtime))) {
mUiModeManager.setNightModeCustomType(UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
}
mCurrentMode = newMode;
return true;