1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.notification; 18 19 import android.app.Activity; 20 import android.app.NotificationManager; 21 import android.app.NotificationManager.Policy; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.SharedPreferences; 25 import android.os.Bundle; 26 import android.provider.Settings; 27 import android.text.format.DateUtils; 28 import android.util.Log; 29 import android.view.View; 30 import android.widget.RadioButton; 31 32 import com.android.internal.annotations.VisibleForTesting; 33 import com.android.internal.logging.MetricsLogger; 34 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 35 import com.android.settings.R; 36 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; 37 import com.android.settings.overlay.FeatureFactory; 38 39 public class ZenOnboardingActivity extends Activity { 40 41 private static final String TAG = "ZenOnboardingActivity"; 42 43 @VisibleForTesting 44 static final String PREF_KEY_SUGGESTION_FIRST_DISPLAY_TIME = 45 "pref_zen_suggestion_first_display_time_ms"; 46 @VisibleForTesting 47 static final long ALWAYS_SHOW_THRESHOLD = DateUtils.DAY_IN_MILLIS * 14; 48 49 View mNewSetting; 50 View mKeepCurrentSetting; 51 RadioButton mNewSettingButton; 52 RadioButton mKeepCurrentSettingButton; 53 54 private NotificationManager mNm; 55 private MetricsLogger mMetrics; 56 57 @Override onCreate(Bundle savedInstanceState)58 protected void onCreate(Bundle savedInstanceState) { 59 super.onCreate(savedInstanceState); 60 setNotificationManager(getSystemService(NotificationManager.class)); 61 setMetricsLogger(new MetricsLogger()); 62 63 Context context = getApplicationContext(); 64 Settings.Global.putInt(context.getContentResolver(), 65 Settings.Global.ZEN_SETTINGS_SUGGESTION_VIEWED, 1); 66 67 setupUI(); 68 } 69 70 @VisibleForTesting setupUI()71 protected void setupUI() { 72 setContentView(R.layout.zen_onboarding); 73 74 mNewSetting = findViewById(R.id.zen_onboarding_new_setting); 75 mKeepCurrentSetting = findViewById(R.id.zen_onboarding_current_setting); 76 mNewSettingButton = findViewById(R.id.zen_onboarding_new_setting_button); 77 mKeepCurrentSettingButton = findViewById(R.id.zen_onboarding_current_setting_button); 78 79 View.OnClickListener newSettingClickListener = new View.OnClickListener() { 80 @Override 81 public void onClick(View v) { 82 mKeepCurrentSettingButton.setChecked(false); 83 mNewSettingButton.setChecked(true); 84 } 85 }; 86 87 View.OnClickListener currentSettingClickListener = new View.OnClickListener() { 88 @Override 89 public void onClick(View v) { 90 mKeepCurrentSettingButton.setChecked(true); 91 mNewSettingButton.setChecked(false); 92 } 93 }; 94 95 mNewSetting.setOnClickListener(newSettingClickListener); 96 mNewSettingButton.setOnClickListener(newSettingClickListener); 97 98 mKeepCurrentSetting.setOnClickListener(currentSettingClickListener); 99 mKeepCurrentSettingButton.setOnClickListener(currentSettingClickListener); 100 101 mKeepCurrentSettingButton.setChecked(true); 102 mMetrics.visible(MetricsEvent.SETTINGS_ZEN_ONBOARDING); 103 } 104 105 @VisibleForTesting setNotificationManager(NotificationManager nm)106 protected void setNotificationManager(NotificationManager nm) { 107 mNm = nm; 108 } 109 110 @VisibleForTesting setMetricsLogger(MetricsLogger ml)111 protected void setMetricsLogger(MetricsLogger ml) { 112 mMetrics = ml; 113 } 114 launchSettings(View button)115 public void launchSettings(View button) { 116 mMetrics.action(MetricsEvent.ACTION_ZEN_ONBOARDING_SETTINGS); 117 Intent settings = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS); 118 settings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 119 startActivity(settings); 120 } 121 save(View button)122 public void save(View button) { 123 NotificationManager.Policy policy = mNm.getNotificationPolicy(); 124 125 if (mNewSettingButton.isChecked()) { 126 NotificationManager.Policy newPolicy = new NotificationManager.Policy( 127 Policy.PRIORITY_CATEGORY_REPEAT_CALLERS | policy.priorityCategories, 128 Policy.PRIORITY_SENDERS_STARRED, 129 policy.priorityMessageSenders, 130 NotificationManager.Policy.getAllSuppressedVisualEffects()); 131 mNm.setNotificationPolicy(newPolicy); 132 mMetrics.action(MetricsEvent.ACTION_ZEN_ONBOARDING_OK); 133 } else { 134 mMetrics.action(MetricsEvent.ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS); 135 } 136 137 Settings.Global.putInt(getApplicationContext().getContentResolver(), 138 Settings.Global.ZEN_SETTINGS_UPDATED, 1); 139 140 finishAndRemoveTask(); 141 } 142 isSuggestionComplete(Context context)143 public static boolean isSuggestionComplete(Context context) { 144 if (wasZenUpdated(context)) { 145 return true; 146 } 147 148 if (showSuggestion(context) || withinShowTimeThreshold(context)) { 149 return false; 150 } 151 152 return true; 153 } 154 wasZenUpdated(Context context)155 private static boolean wasZenUpdated(Context context) { 156 // ZEN_SETTINGS_UPDATED is true for: 157 // - fresh P+ device 158 // - if zen visual effects values were changed by the user in Settings 159 NotificationManager nm = context.getSystemService(NotificationManager.class); 160 if (NotificationManager.Policy.areAllVisualEffectsSuppressed( 161 nm.getNotificationPolicy().suppressedVisualEffects)) { 162 Settings.Global.putInt(context.getContentResolver(), 163 Settings.Global.ZEN_SETTINGS_UPDATED, 1); 164 } 165 return Settings.Global.getInt(context.getContentResolver(), 166 Settings.Global.ZEN_SETTINGS_UPDATED, 0) != 0; 167 } 168 showSuggestion(Context context)169 private static boolean showSuggestion(Context context) { 170 // SHOW_ZEN_SETTINGS_SUGGESTION is by default true, but false when: 171 // - user manually turns on dnd 172 173 // SHOW_ZEN_SETTINGS_SUGGESTION is also true when: 174 // - automatic rule has started DND and user has not seen the first use dialog 175 return Settings.Global.getInt(context.getContentResolver(), 176 Settings.Global.SHOW_ZEN_SETTINGS_SUGGESTION, 0) != 0; 177 178 } 179 withinShowTimeThreshold(Context context)180 private static boolean withinShowTimeThreshold(Context context) { 181 final SuggestionFeatureProvider featureProvider = FeatureFactory.getFactory(context) 182 .getSuggestionFeatureProvider(context); 183 final SharedPreferences prefs = featureProvider.getSharedPrefs(context); 184 final long currentTimeMs = System.currentTimeMillis(); 185 final long firstDisplayTimeMs; 186 187 if (!prefs.contains(PREF_KEY_SUGGESTION_FIRST_DISPLAY_TIME)) { 188 firstDisplayTimeMs = currentTimeMs; 189 prefs.edit().putLong(PREF_KEY_SUGGESTION_FIRST_DISPLAY_TIME, currentTimeMs).commit(); 190 } else { 191 firstDisplayTimeMs = prefs.getLong(PREF_KEY_SUGGESTION_FIRST_DISPLAY_TIME, -1); 192 } 193 194 final long showTimeMs = firstDisplayTimeMs + ALWAYS_SHOW_THRESHOLD; 195 final boolean stillShow = currentTimeMs < showTimeMs; 196 197 Log.d(TAG, "still show zen suggestion based on time: " + stillShow); 198 return stillShow; 199 } 200 } 201