diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 060429e9007..d55493cdbd0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -742,6 +742,27 @@
android:value="true" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:height="24dp"
+ android:width="24dp" >
+ android:fillColor="?android:attr/colorControlActivated"
+ android:pathData="M 12 2 C 6.48 2 2 6.48 2 12 s 4.48 10 10 10 10 -4.48 10 -10 S 17.52 2 12 2 z m 4 11 H 8 c -.55 0 -1 -.45 -1 -1 s .45 -1 1 -1 h 8c.55 0 1 .45 1 1 s -.45 1 -1 1z" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8bdfb5f857a..da957918836 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9874,6 +9874,12 @@
+
+ Update Do Not Disturb
+
+
+ Hide notifications to stay focused
+
What\'s new and exciting?
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
index d0c0b253baa..257e8c39024 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.service.settings.suggestions.Suggestion;
import android.support.annotation.NonNull;
-import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.util.Pair;
@@ -32,6 +31,8 @@ import com.android.settings.Settings.NightDisplaySuggestionActivity;
import com.android.settings.display.NightDisplayPreferenceController;
import com.android.settings.fingerprint.FingerprintEnrollSuggestionActivity;
import com.android.settings.fingerprint.FingerprintSuggestionActivity;
+import com.android.settings.notification.ZenOnboardingActivity;
+import com.android.settings.notification.ZenSuggestionActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ScreenLockSuggestionActivity;
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
@@ -88,6 +89,8 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
return NightDisplayPreferenceController.isSuggestionComplete(context);
} else if (className.equals(NewDeviceIntroSuggestionActivity.class.getName())) {
return NewDeviceIntroSuggestionActivity.isSuggestionComplete(context);
+ } else if (className.equals(ZenSuggestionActivity.class.getName())) {
+ return ZenOnboardingActivity.isSuggestionComplete(context);
}
return false;
}
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index d5792564cc2..9e2b650346a 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -135,6 +135,9 @@ public class ZenModeBackend {
}
protected void saveVisualEffectsPolicy(int category, boolean suppress) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_UPDATED, 1);
+
int suppressedEffects = getNewSuppressedEffects(suppress, category);
savePolicy(mPolicy.priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, suppressedEffects);
diff --git a/src/com/android/settings/notification/ZenOnboardingActivity.java b/src/com/android/settings/notification/ZenOnboardingActivity.java
index 9d71f54c712..ff86ef6ff34 100644
--- a/src/com/android/settings/notification/ZenOnboardingActivity.java
+++ b/src/com/android/settings/notification/ZenOnboardingActivity.java
@@ -19,16 +19,33 @@ package com.android.settings.notification;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
+import android.content.Context;
+import android.content.SharedPreferences;
import android.os.Bundle;
-import android.support.annotation.VisibleForTesting;
+import android.provider.Settings;
+import android.text.format.DateUtils;
+import android.util.Log;
import android.view.View;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
public class ZenOnboardingActivity extends Activity {
+ private static final String TAG = "ZenOnboardingActivity";
+
+ @VisibleForTesting
+ static final String PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME =
+ "pref_zen_suggestion_first_display_time_ms";
+ @VisibleForTesting
+ static final String PREF_KEY_SUGGESTION_VIEWED = "pref_zen_suggestion_viewed";
+ @VisibleForTesting
+ static final long ALWAYS_SHOW_THRESHOLD = DateUtils.DAY_IN_MILLIS * 14;
+
private NotificationManager mNm;
private MetricsLogger mMetrics;
@@ -38,6 +55,10 @@ public class ZenOnboardingActivity extends Activity {
setNotificationManager(getSystemService(NotificationManager.class));
setMetricsLogger(new MetricsLogger());
+ Context context = getApplicationContext();
+ Settings.Global.putInt(context.getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_SUGGESTION_VIEWED, 1);
+
setupUI();
}
@@ -60,20 +81,79 @@ public class ZenOnboardingActivity extends Activity {
public void close(View button) {
mMetrics.action(MetricsEvent.ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS);
+
+ Settings.Global.putInt(getApplicationContext().getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_UPDATED, 1);
+
finishAndRemoveTask();
}
public void save(View button) {
mMetrics.action(MetricsEvent.ACTION_ZEN_ONBOARDING_OK);
- Policy policy = mNm.getNotificationPolicy();
+ NotificationManager.Policy policy = mNm.getNotificationPolicy();
- Policy newPolicy = new NotificationManager.Policy(
+ NotificationManager.Policy newPolicy = new NotificationManager.Policy(
Policy.PRIORITY_CATEGORY_REPEAT_CALLERS | policy.priorityCategories,
Policy.PRIORITY_SENDERS_STARRED,
policy.priorityMessageSenders,
- Policy.getAllSuppressedVisualEffects());
+ NotificationManager.Policy.getAllSuppressedVisualEffects());
mNm.setNotificationPolicy(newPolicy);
+ Settings.Global.putInt(getApplicationContext().getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_UPDATED, 1);
+
finishAndRemoveTask();
}
+
+ public static boolean isSuggestionComplete(Context context) {
+ if (wasZenUpdated(context)) {
+ return true;
+ }
+
+ if (showSuggestion(context) || withinShowTimeThreshold(context)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static boolean wasZenUpdated(Context context) {
+ // ZEN_SETTINGS_UPDATED is true for:
+ // - fresh P+ device
+ // - if zen visual effects values were changed by the user in Settings
+ return Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_UPDATED, 0) != 0;
+ }
+
+ private static boolean showSuggestion(Context context) {
+ // SHOW_ZEN_SETTINGS_SUGGESTION is by default true, but false when:
+ // - user manually turns on dnd
+
+ // SHOW_ZEN_SETTINGS_SUGGESTION is also true when:
+ // - automatic rule has started DND and user has not seen the first use dialog
+ return Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.SHOW_ZEN_SETTINGS_SUGGESTION, 0) != 0;
+
+ }
+
+ private static boolean withinShowTimeThreshold(Context context) {
+ final SuggestionFeatureProvider featureProvider = FeatureFactory.getFactory(context)
+ .getSuggestionFeatureProvider(context);
+ final SharedPreferences prefs = featureProvider.getSharedPrefs(context);
+ final long currentTimeMs = System.currentTimeMillis();
+ final long firstDisplayTimeMs;
+
+ if (!prefs.contains(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME)) {
+ firstDisplayTimeMs = currentTimeMs;
+ prefs.edit().putLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME, currentTimeMs).commit();
+ } else {
+ firstDisplayTimeMs = prefs.getLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME, -1);
+ }
+
+ final long showTimeMs = firstDisplayTimeMs + ALWAYS_SHOW_THRESHOLD;
+ final boolean stillShow = currentTimeMs < showTimeMs;
+
+ Log.d(TAG, "still show zen suggestion based on time: " + stillShow);
+ return stillShow;
+ }
}
diff --git a/src/com/android/settings/notification/ZenSuggestionActivity.java b/src/com/android/settings/notification/ZenSuggestionActivity.java
new file mode 100644
index 00000000000..9d2148c7e50
--- /dev/null
+++ b/src/com/android/settings/notification/ZenSuggestionActivity.java
@@ -0,0 +1,24 @@
+package com.android.settings.notification;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+
+public class ZenSuggestionActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // start up zen settings activity
+ Intent settingsIntent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
+ startActivity(settingsIntent);
+
+ // start up onboarding activity
+ Intent onboardingActivity = new Intent(Settings.ZEN_MODE_ONBOARDING);
+ startActivity(onboardingActivity);
+
+ finish();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java b/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
index 7bc93713977..b4d3700bece 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
@@ -29,6 +29,12 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OF
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+import static com.android.settings.notification.ZenOnboardingActivity.ALWAYS_SHOW_THRESHOLD;
+import static com.android.settings.notification.ZenOnboardingActivity.PREF_KEY_SUGGESTION_VIEWED;
+import static com.android.settings.notification.ZenOnboardingActivity
+ .PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME;
+import static com.android.settings.notification.ZenOnboardingActivity.isSuggestionComplete;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -39,20 +45,22 @@ import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.provider.Settings;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
+import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenOnboardingActivityTest {
@@ -64,6 +72,9 @@ public class ZenOnboardingActivityTest {
ZenOnboardingActivity mActivity;
+ private Context mContext;
+ private FakeFeatureFactory mFeatureFactory;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -75,6 +86,11 @@ public class ZenOnboardingActivityTest {
mActivity.setMetricsLogger(mMetricsLogger);
mActivity.setupUI();
+
+ mContext = RuntimeEnvironment.application;
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ when(mFeatureFactory.suggestionsFeatureProvider.getSharedPrefs(any(Context.class)))
+ .thenReturn(getSharedPreferences());
}
@Test
@@ -124,4 +140,73 @@ public class ZenOnboardingActivityTest {
verify(mNm, never()).setNotificationPolicy(any());
}
+
+ @Test
+ public void isSuggestionComplete_zenUpdated() {
+ setZenUpdated(true);
+ setShowSettingsSuggestion(false);
+ setWithinTimeThreshold(true);
+ assertThat(isSuggestionComplete(mContext)).isTrue();
+ }
+
+ @Test
+ public void isSuggestionComplete_withinTimeThreshold() {
+ setZenUpdated(false);
+ setShowSettingsSuggestion(false);
+ setWithinTimeThreshold(true);
+ assertThat(isSuggestionComplete(mContext)).isFalse();
+ }
+
+ @Test
+ public void isSuggestionComplete_showSettingsSuggestionTrue() {
+ setZenUpdated(false);
+ setShowSettingsSuggestion(true);
+ setWithinTimeThreshold(false);
+ assertThat(isSuggestionComplete(mContext)).isFalse();
+ }
+
+ @Test
+ public void isSuggestionComplete_showSettingsSuggestionFalse_notWithinTimeThreshold() {
+ setZenUpdated(false);
+ setShowSettingsSuggestion(false);
+ setWithinTimeThreshold(false);
+ assertThat(isSuggestionComplete(mContext)).isTrue();
+ }
+
+ private void setZenUpdated(boolean updated) {
+ int zenUpdated = 0;
+ if (updated) {
+ zenUpdated = 1;
+ }
+
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_UPDATED, zenUpdated);
+ }
+
+ private void setWithinTimeThreshold(boolean withinTime) {
+ long firstTime = System.currentTimeMillis();
+
+ if (withinTime) {
+ firstTime -= ALWAYS_SHOW_THRESHOLD / 2;
+ } else {
+ firstTime -= ALWAYS_SHOW_THRESHOLD * 2;
+ }
+
+ getSharedPreferences().edit().putLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME,
+ firstTime).commit();
+ }
+
+ private void setShowSettingsSuggestion(boolean show) {
+ int showZenSuggestion = 0;
+ if (show) {
+ showZenSuggestion = 1;
+ }
+
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_ZEN_SETTINGS_SUGGESTION, showZenSuggestion);
+ }
+
+ private SharedPreferences getSharedPreferences() {
+ return mContext.getSharedPreferences("test_zen_sugg", Context.MODE_PRIVATE);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
index bb14667fce8..c6583c7eb03 100644
--- a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
+++ b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
@@ -30,6 +30,8 @@ import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.fingerprint.FingerprintEnrollSuggestionActivity;
import com.android.settings.fingerprint.FingerprintSuggestionActivity;
+import com.android.settings.notification.ZenOnboardingActivity;
+import com.android.settings.notification.ZenSuggestionActivity;
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wallpaper.WallpaperSuggestionActivity;
@@ -82,6 +84,14 @@ public class SettingsSuggestionsTest {
R.string.night_display_suggestion_summary);
}
+ @Test
+ public void zenSuggestion_isValid() {
+ assertSuggestionEquals(
+ ZenSuggestionActivity.class.getName(),
+ R.string.zen_suggestion_title,
+ R.string.zen_suggestion_summary);
+ }
+
@Test
public void newDeviceIntroSuggestion_isValid() {
assertSuggestionEquals(
diff --git a/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java b/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
index 15975689c7e..286676dd0d0 100644
--- a/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
@@ -78,7 +78,7 @@ public class NewDeviceIntroSuggestionActivityTest {
final long currentTime = System.currentTimeMillis();
getSharedPreferences().edit().putLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME,
- currentTime - 2 * PERMANENT_DISMISS_THRESHOLD);
+ currentTime - 2 * PERMANENT_DISMISS_THRESHOLD).commit();
assertThat(isSuggestionComplete(mContext)).isTrue();
}