Add "Adaptive sleep" setting

Adaptive sleep setting, if enabled, will perform an attention check
right before the power manager is scheduled to dim and then turn off the
display. If the attention check says that user is currently paying
attention to the device, the screen sleep timeout timer will be reset,
as if user had interacted with the display.

The animation and explanation strings are still TBC per UX team.

The setting is only displayed on supported devices.

Test: make RunSettingsRoboTests
Bug: 111939367
Change-Id: I191dd8ef06ecec4edbe4357671a7a9360971c06f
This commit is contained in:
Alex Salo
2019-01-17 13:54:03 -08:00
parent 0b880088a4
commit bb4e9ce201
6 changed files with 320 additions and 0 deletions

View File

@@ -2688,6 +2688,15 @@
<!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] --> <!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] -->
<string name="display_white_balance_title">Display white balance</string> <string name="display_white_balance_title">Display white balance</string>
<!-- Display settings screen, setting option name to enable adaptive sleep [CHAR LIMIT=30] -->
<string name="adaptive_sleep_title">Adaptive sleep</string>
<!-- Setting option summary when adaptive sleep is on [CHAR LIMIT=NONE] -->
<string name="adaptive_sleep_summary_on">On</string>
<!-- Setting option summary when adaptive sleep is off [CHAR LIMIT=NONE] -->
<string name="adaptive_sleep_summary_off">Off</string>
<!-- Description about the feature adaptive sleep [CHAR LIMIT=NONE]-->
<string name="adaptive_sleep_description">Your screen would not dim and go to sleep if the device detects your present attention.</string>
<!-- Night display screen, setting option name to enable night display (renamed "Night Light" with title caps). [CHAR LIMIT=30] --> <!-- Night display screen, setting option name to enable night display (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
<string name="night_display_title">Night Light</string> <string name="night_display_title">Night Light</string>
@@ -6707,6 +6716,8 @@
<string name="help_url_display_size" translatable="false"></string> <string name="help_url_display_size" translatable="false"></string>
<!-- Help URL, Auto brightness [DO NOT TRANSLATE] --> <!-- Help URL, Auto brightness [DO NOT TRANSLATE] -->
<string name="help_url_auto_brightness" translatable="false" /> <string name="help_url_auto_brightness" translatable="false" />
<!-- Help URL, Adaptive sleep [DO NOT TRANSLATE] -->
<string name="help_url_adaptive_sleep" translatable="false" />
<!-- Help URL, Previously connected bluetooth devices [DO NOT TRANSLATE] --> <!-- Help URL, Previously connected bluetooth devices [DO NOT TRANSLATE] -->
<string name="help_url_previously_connected_devices" translatable="false"></string> <string name="help_url_previously_connected_devices" translatable="false"></string>
<!-- Help URL, Top level privacy settings [DO NOT TRANSLATE] --> <!-- Help URL, Top level privacy settings [DO NOT TRANSLATE] -->
@@ -7047,6 +7058,9 @@
<!-- Search keywords for adaptive brightness setting [CHAR LIMIT=NONE]--> <!-- Search keywords for adaptive brightness setting [CHAR LIMIT=NONE]-->
<string name="keywords_display_auto_brightness">dim screen, touchscreen, battery, smart brightness, dynamic brightness</string> <string name="keywords_display_auto_brightness">dim screen, touchscreen, battery, smart brightness, dynamic brightness</string>
<!-- Search keywords for adaptive sleep setting [CHAR LIMIT=NONE]-->
<string name="keywords_display_adaptive_sleep">dim screen, sleep, battery, timeout, attention</string>
<!-- List of synonyms for the auto rotate (rotate the virtual display when the device rotates) setting, used to match in settings search [CHAR LIMIT=NONE] --> <!-- List of synonyms for the auto rotate (rotate the virtual display when the device rotates) setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_auto_rotate">rotate, flip, rotation, portrait, landscape, orientation, vertical, horizontal</string> <string name="keywords_auto_rotate">rotate, flip, rotation, portrait, landscape, orientation, vertical, horizontal</string>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="adaptive_sleep_detail"
android:title="@string/adaptive_sleep_title">
<!-- TODO(111939367): add correct animation -->
<com.android.settings.widget.VideoPreference
android:key="adaptive_sleep_video"
android:title="@string/summary_placeholder"
settings:animation="@raw/aab_brightness"
settings:preview="@drawable/aab_brightness"
settings:controller="com.android.settings.widget.VideoPreferenceController"/>
<com.android.settingslib.RestrictedSwitchPreference
android:key="adaptive_sleep"
android:title="@string/adaptive_sleep_title"
settings:keywords="@string/keywords_display_adaptive_sleep"
settings:controller="com.android.settings.display.AdaptiveSleepPreferenceController"
settings:useAdminDisabledSummary="true"
settings:allowDividerAbove="true" />
</PreferenceScreen>

View File

@@ -66,6 +66,13 @@
android:entryValues="@array/screen_timeout_values" android:entryValues="@array/screen_timeout_values"
settings:keywords="@string/keywords_screen_timeout" /> settings:keywords="@string/keywords_screen_timeout" />
<Preference
android:key="adaptive_sleep_entry"
android:title="@string/adaptive_sleep_title"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.display.AdaptiveSleepSettings"
settings:controller="com.android.settings.display.AdaptiveSleepPreferenceController" />
<SwitchPreference <SwitchPreference
android:key="auto_rotate" android:key="auto_rotate"
android:title="@string/accelerometer_title" android:title="@string/accelerometer_title"

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2019 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;
import static android.provider.Settings.System.ADAPTIVE_SLEEP;
import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
public class AdaptiveSleepPreferenceController extends TogglePreferenceController {
private final String SYSTEM_KEY = ADAPTIVE_SLEEP;
private final int DEFAULT_VALUE = 0;
public AdaptiveSleepPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public boolean isChecked() {
return Settings.System.getInt(mContext.getContentResolver(),
SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
}
@Override
public boolean setChecked(boolean isChecked) {
Settings.System.putInt(mContext.getContentResolver(), SYSTEM_KEY,
isChecked ? 1 : DEFAULT_VALUE);
return true;
}
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_adaptive_sleep_available)
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isSliceable() {
return true;
}
@Override
public CharSequence getSummary() {
return mContext.getText(isChecked()
? R.string.adaptive_sleep_summary_on
: R.string.adaptive_sleep_summary_off);
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2019 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;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import java.util.Arrays;
import java.util.List;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class AdaptiveSleepSettings extends DashboardFragment {
private static final String TAG = "AdaptiveSleepSettings";
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mFooterPreferenceMixin.createFooterPreference()
.setTitle(R.string.adaptive_sleep_description);
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.adaptive_sleep_detail;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_ADAPTIVE_SLEEP;
}
@Override
public int getHelpResource() {
return R.string.help_url_adaptive_sleep;
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.adaptive_sleep_detail;
return Arrays.asList(sir);
}
};
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2019 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;
import static android.provider.Settings.System.ADAPTIVE_SLEEP;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class AdaptiveSleepPreferenceControllerTest {
private static final String PREFERENCE_KEY = "adaptive_sleep";
private Context mContext;
private AdaptiveSleepPreferenceController mController;
private ContentResolver mContentResolver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContentResolver = mContext.getContentResolver();
mController = new AdaptiveSleepPreferenceController(mContext, PREFERENCE_KEY);
}
@Test
public void onPreferenceChange_turnOn_returnOn() {
mController.onPreferenceChange(null, true);
final int mode = Settings.System.getInt(mContentResolver, ADAPTIVE_SLEEP, 0);
assertThat(mode).isEqualTo(1);
}
@Test
public void onPreferenceChange_turnOff_returnOff() {
mController.onPreferenceChange(null, false);
final int mode = Settings.System.getInt(mContentResolver, ADAPTIVE_SLEEP, 1);
assertThat(mode).isEqualTo(0);
}
@Test
public void setChecked_updatesCorrectly() {
mController.setChecked(true);
assertThat(mController.isChecked()).isTrue();
mController.setChecked(false);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_no() {
Settings.System.putInt(mContentResolver, ADAPTIVE_SLEEP, 0);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_yes() {
Settings.System.putInt(mContentResolver, ADAPTIVE_SLEEP, 1);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void getSummary_settingOn_shouldReturnOnSummary() {
mController.setChecked(true);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.adaptive_sleep_summary_on));
}
@Test
public void getSummary_settingOff_shouldReturnOffSummary() {
mController.setChecked(false);
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.adaptive_sleep_summary_off));
}
@Test
public void isSliceable_returnsTrue() {
final AdaptiveSleepPreferenceController controller =
new AdaptiveSleepPreferenceController(mContext, "any_key");
assertThat(controller.isSliceable()).isTrue();
}
}