diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cbf1eae63d7..ef775631b15 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -921,6 +921,26 @@
android:value="true" />
+
+
+
+
+
+
+
+
+
+
+
+
Apps, background sync, and other features related to your work profile are turned off.
+
+ Set Night Light schedule
+
+
+ Tint screen amber to help you fall asleep
+
Night Light is on
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 38b6e1b625e..7892011c17b 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -52,6 +52,7 @@ public class Settings extends SettingsActivity {
public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ }
public static class DisplaySettingsActivity extends SettingsActivity { /* empty */ }
public static class NightDisplaySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class NightDisplaySuggestionActivity extends NightDisplaySettingsActivity { /* empty */ }
public static class DeviceInfoSettingsActivity extends SettingsActivity { /* empty */ }
public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ }
@@ -65,7 +66,7 @@ public class Settings extends SettingsActivity {
return true;
}
return super.isValidFragment(className);
- }
+ }
}
public static class BackgroundCheckSummaryActivity extends SettingsActivity { /* empty */ }
public static class StorageUseActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
index 638f85f94f2..4b4e03f0bc7 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
@@ -21,9 +21,13 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
+import android.content.ContentResolver;
+import android.provider.Settings.Secure;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.Settings.NightDisplaySuggestionActivity;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
@@ -50,6 +54,9 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
@Override
public boolean isSuggestionCompleted(Context context, @NonNull ComponentName component) {
final String className = component.getClassName();
+ if (className.equals(NightDisplaySuggestionActivity.class.getName())) {
+ return hasUsedNightDisplay(context);
+ }
if (className.equals(NewDeviceIntroSuggestionActivity.class.getName())) {
return NewDeviceIntroSuggestionActivity.isSuggestionComplete(context);
}
@@ -119,4 +126,11 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
return packageName;
}
+ @VisibleForTesting
+ boolean hasUsedNightDisplay(Context context) {
+ final ContentResolver cr = context.getContentResolver();
+ final long lastActivatedTimeMillis = Secure.getLong(cr,
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1);
+ return lastActivatedTimeMillis > 0;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/applications/assist/AssistFlashScreenPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/assist/AssistFlashScreenPreferenceControllerTest.java
index 7fa11cf8418..d68229fb981 100644
--- a/tests/robotests/src/com/android/settings/applications/assist/AssistFlashScreenPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/assist/AssistFlashScreenPreferenceControllerTest.java
@@ -78,8 +78,8 @@ public class AssistFlashScreenPreferenceControllerTest {
@Config(shadows = {ShadowSecureSettings.class})
public void isAvailable_hasAssistantAndAllowDisclosure_shouldReturnTrue() {
ReflectionHelpers.setField(mController, "mContext", mMockContext);
- ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT,
- "com.android.settings/assist");
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putString(cr, Settings.Secure.ASSISTANT, "com.android.settings/assist");
doReturn(true).when(mController).allowDisablingAssistDisclosure();
assertThat(mController.isAvailable()).isTrue();
@@ -89,8 +89,8 @@ public class AssistFlashScreenPreferenceControllerTest {
@Config(shadows = {ShadowSecureSettings.class})
public void isAvailable_hasAssistantAndDisallowDisclosure_shouldReturnTrue() {
ReflectionHelpers.setField(mController, "mContext", mMockContext);
- ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT,
- "com.android.settings/assist");
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putString(cr, Settings.Secure.ASSISTANT, "com.android.settings/assist");
doReturn(false).when(mController).allowDisablingAssistDisclosure();
assertThat(mController.isAvailable()).isFalse();
@@ -98,8 +98,7 @@ public class AssistFlashScreenPreferenceControllerTest {
@Test
public void isAvailable_hasNoAssistant_shouldReturnFalse() {
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.ASSISTANT, "");
+ Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.ASSISTANT, "");
assertThat(mController.isAvailable()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java
index 037bd10f37a..f382b9034b8 100644
--- a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java
@@ -78,7 +78,7 @@ public class DefaultAssistPreferenceControllerTest {
@Config(shadows = {ShadowSecureSettings.class})
public void getDefaultAppInfo_hasDefaultAssist_shouldReturnKey() {
final String flattenKey = "com.android.settings/assist";
- ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT, flattenKey);
+ Settings.Secure.putString(null, Settings.Secure.ASSISTANT, flattenKey);
DefaultAppInfo appInfo = mController.getDefaultAppInfo();
assertThat(appInfo.getKey()).isEqualTo(flattenKey);
@@ -87,7 +87,7 @@ public class DefaultAssistPreferenceControllerTest {
@Test
public void getSettingIntent_noSettingsActivity_shouldNotCrash() {
final String flattenKey = "com.android.settings/assist";
- ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT, flattenKey);
+ Settings.Secure.putString(null, Settings.Secure.ASSISTANT, flattenKey);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
DefaultAssistPreferenceController controller =
spy(new DefaultAssistPreferenceController(mContext));
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
index d5d87b1b34f..e263e2cc0ec 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
@@ -16,14 +16,19 @@
package com.android.settings.dashboard.suggestions;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.provider.Settings.Secure;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.Settings.NightDisplaySuggestionActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.Settings;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowSecureSettings;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.suggestions.SuggestionParser;
@@ -50,7 +55,9 @@ import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = ShadowSecureSettings.class)
public class SuggestionFeatureProviderImplTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -172,4 +179,30 @@ public class SuggestionFeatureProviderImplTest {
assertThat(suggestions).hasSize(3);
}
+
+ @Test
+ public void hasUsedNightDisplay_returnsFalse_byDefault() {
+ assertThat(mProvider.hasUsedNightDisplay(mContext)).isFalse();
+ }
+
+ @Test
+ public void hasUsedNightDisplay_returnsTrue_ifPreviouslyActivated() {
+ Secure.putLong(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, 1L);
+ assertThat(mProvider.hasUsedNightDisplay(mContext)).isTrue();
+ }
+
+ @Test
+ public void nightDisplaySuggestion_isCompleted_ifPreviouslyActivated() {
+ Secure.putLong(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, 1L);
+ final ComponentName componentName =
+ new ComponentName(mContext, NightDisplaySuggestionActivity.class);
+ assertThat(mProvider.isSuggestionCompleted(mContext, componentName)).isTrue();
+ }
+
+ @Test
+ public void nightDisplaySuggestion_isNotCompleted_byDefault() {
+ final ComponentName componentName =
+ new ComponentName(mContext, NightDisplaySuggestionActivity.class);
+ assertThat(mProvider.isSuggestionCompleted(mContext, componentName)).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
index 5f3c0f0c38b..b46ee087c2c 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
@@ -90,7 +90,6 @@ public class SuggestionsChecksTest {
assertThat(mSuggestionsChecks.isSuggestionComplete(tile)).isFalse();
}
-
@Test
public void testFingerprintEnrollmentIntroductionIsCompleteWhenFingerprintNotSupported() {
stubFingerprintSupported(false);
@@ -115,7 +114,7 @@ public class SuggestionsChecksTest {
}
private Tile createFingerprintTile() {
- Tile tile = new Tile();
+ final Tile tile = new Tile();
tile.intent = new Intent();
tile.intent.setComponent(new ComponentName(mContext,
Settings.FingerprintEnrollSuggestionActivity.class));
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
index a06395a0775..4d8509211e0 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
@@ -26,7 +26,6 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,11 +64,6 @@ public class DoubleTwistPreferenceControllerTest {
mController = new DoubleTwistPreferenceController(mContext, null, KEY_DOUBLE_TWIST);
}
- @After
- public void tearDown() {
- ShadowSecureSettings.clear();
- }
-
@Test
public void isAvailable_hasSensor_shouldReturnTrue() {
// Mock sensors
diff --git a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
index b3af6b83b40..e229653ea29 100644
--- a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
@@ -19,6 +19,7 @@ package com.android.settings.language;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.input.InputManager;
@@ -119,7 +120,6 @@ public class LanguageAndInputSettingsTest {
}
@Test
-
public void testGetPreferenceControllers_shouldAllBeCreated() {
final List controllers =
mFragment.getPreferenceControllers(mActivity);
@@ -135,7 +135,8 @@ public class LanguageAndInputSettingsTest {
final Activity activity = mock(Activity.class);
final SummaryLoader loader = mock(SummaryLoader.class);
final ComponentName componentName = new ComponentName("pkg", "cls");
- ShadowSecureSettings.putString(null, Settings.Secure.DEFAULT_INPUT_METHOD,
+ final ContentResolver cr = activity.getContentResolver();
+ Settings.Secure.putString(cr, Settings.Secure.DEFAULT_INPUT_METHOD,
componentName.flattenToString());
when(activity.getSystemService(Context.INPUT_METHOD_SERVICE))
.thenReturn(mInputMethodManager);
@@ -168,11 +169,12 @@ public class LanguageAndInputSettingsTest {
SummaryLoader.SummaryProvider provider = mFragment.SUMMARY_PROVIDER_FACTORY
.createSummaryProvider(mActivity, loader);
- ShadowSecureSettings.putInt(null, Settings.Secure.ASSIST_GESTURE_ENABLED, 0);
+ final ContentResolver cr = mActivity.getContentResolver();
+ Settings.Secure.putInt(cr, Settings.Secure.ASSIST_GESTURE_ENABLED, 0);
provider.setListening(true);
verify(mActivity).getString(R.string.language_input_gesture_summary_off);
- ShadowSecureSettings.putInt(null, Settings.Secure.ASSIST_GESTURE_ENABLED, 1);
+ Settings.Secure.putInt(cr, Settings.Secure.ASSIST_GESTURE_ENABLED, 1);
provider.setListening(true);
verify(mActivity).getString(R.string.language_input_gesture_summary_on_with_assist);
}
diff --git a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
index 574894ea168..4cc4148e826 100644
--- a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
+++ b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
@@ -79,6 +79,13 @@ public class SettingsSuggestionsTest {
R.string.wifi_calling_suggestion_title, R.string.wifi_calling_suggestion_summary);
}
+ @Test
+ public void nightDisplaySuggestion_isValid() {
+ assertSuggestionEquals("Settings$NightDisplaySuggestionActivity",
+ CATEGORY_FIRST_IMPRESSION,
+ R.string.night_display_suggestion_title, R.string.night_display_suggestion_summary);
+ }
+
private void assertSuggestionEquals(String activityName, String category, @StringRes int title,
@StringRes int summary) {
final AndroidManifest androidManifest = ShadowApplication.getInstance().getAppManifest();
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSecureSettings.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSecureSettings.java
index 64e188eccfd..1ae5398657e 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSecureSettings.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSecureSettings.java
@@ -18,58 +18,85 @@ package com.android.settings.testutils.shadow;
import android.content.ContentResolver;
import android.provider.Settings;
-
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import java.util.Map;
+import java.util.WeakHashMap;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
-import java.util.HashMap;
-import java.util.Map;
-
@Implements(Settings.Secure.class)
public class ShadowSecureSettings {
- private static final Map mValueMap = new HashMap<>();
+ private static final Map> sUserDataMap =
+ new WeakHashMap<>();
@Implementation
- public static boolean putInt(ContentResolver resolver, String name, int value) {
- mValueMap.put(name, value);
- return true;
- }
-
- @Implementation
- public static boolean putString(ContentResolver resolver, String name, String value) {
- mValueMap.put(name, value);
- return true;
- }
-
- @Implementation
- public static String getString(ContentResolver resolver, String name) {
- return (String) mValueMap.get(name);
+ public static boolean putStringForUser(ContentResolver resolver, String name, String value,
+ int userHandle) {
+ final Table userTable = getUserTable(resolver);
+ synchronized (userTable) {
+ userTable.put(userHandle, name, value);
+ return true;
+ }
}
@Implementation
public static String getStringForUser(ContentResolver resolver, String name, int userHandle) {
- return getString(resolver, name);
+ final Table userTable = getUserTable(resolver);
+ synchronized (userTable) {
+ return (String) userTable.get(userHandle, name);
+ }
}
@Implementation
- public static boolean putIntForUser(ContentResolver cr, String name, int value,
- int userHandle) {
- return putInt(cr, name, value);
+ public static boolean putIntForUser(ContentResolver resolver, String name, int value,
+ int userHandle) {
+ final Table userTable = getUserTable(resolver);
+ synchronized (userTable) {
+ userTable.put(userHandle, name, value);
+ return true;
+ }
}
@Implementation
- public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) {
- return getInt(cr, name, def);
+ public static int getIntForUser(ContentResolver resolver, String name, int def,
+ int userHandle) {
+ final Table userTable = getUserTable(resolver);
+ synchronized (userTable) {
+ final Object object = userTable.get(userHandle, name);
+ return object instanceof Integer ? (Integer) object : def;
+ }
}
@Implementation
- public static int getInt(ContentResolver resolver, String name, int defaultValue) {
- Integer value = (Integer) mValueMap.get(name);
- return value == null ? defaultValue : value;
+ public static boolean putLongForUser(ContentResolver resolver, String name, long value,
+ int userHandle) {
+ final Table userTable = getUserTable(resolver);
+ synchronized (userTable) {
+ userTable.put(userHandle, name, value);
+ return true;
+ }
}
- public static void clear() {
- mValueMap.clear();
+ @Implementation
+ public static long getLongForUser(ContentResolver resolver, String name, long def,
+ int userHandle) {
+ final Table userTable = getUserTable(resolver);
+ synchronized (userTable) {
+ final Object object = userTable.get(userHandle, name);
+ return object instanceof Long ? (Long) object : def;
+ }
+ }
+
+ private static Table getUserTable(ContentResolver contentResolver) {
+ synchronized (sUserDataMap) {
+ Table table = sUserDataMap.get(contentResolver);
+ if (table == null) {
+ table = HashBasedTable.create();
+ sUserDataMap.put(contentResolver, table);
+ }
+ return table;
+ }
}
}