1 /*
2  * Copyright (C) 2020 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.zen;
18 
19 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
20 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
21 
22 import android.app.NotificationManager;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.pm.PackageManager;
26 import android.provider.Contacts;
27 import android.view.View;
28 
29 import androidx.annotation.VisibleForTesting;
30 import androidx.preference.Preference;
31 import androidx.preference.PreferenceCategory;
32 import androidx.preference.PreferenceScreen;
33 
34 import com.android.settings.R;
35 import com.android.settingslib.core.lifecycle.Lifecycle;
36 import com.android.settingslib.widget.RadioButtonPreference;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 
41 /**
42  * Common preference controller functionality shared by
43  * ZenModePriorityMessagesPreferenceController and ZenModePriorityCallsPreferenceController.
44  *
45  * This includes the options to choose the priority senders that are allowed to bypass DND for
46  * calls or messages. This can be one of four values: starred contacts, all contacts, anyone, or
47  * no one.
48  */
49 public class ZenModePrioritySendersPreferenceController
50         extends AbstractZenModePreferenceController {
51     @VisibleForTesting static final String KEY_ANY = "senders_anyone";
52     @VisibleForTesting static final String KEY_CONTACTS = "senders_contacts";
53     @VisibleForTesting static final String KEY_STARRED = "senders_starred_contacts";
54     @VisibleForTesting static final String KEY_NONE = "senders_none";
55 
56     private static final Intent ALL_CONTACTS_INTENT =
57             new Intent(Contacts.Intents.UI.LIST_DEFAULT)
58                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
59     private static final Intent STARRED_CONTACTS_INTENT =
60             new Intent(Contacts.Intents.UI.LIST_STARRED_ACTION)
61                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK  | Intent.FLAG_ACTIVITY_CLEAR_TASK);
62     private static final Intent FALLBACK_INTENT = new Intent(Intent.ACTION_MAIN)
63             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
64 
65     private final PackageManager mPackageManager;
66     private final boolean mIsMessages; // if this is false, then this preference is for calls
67 
68     private PreferenceCategory mPreferenceCategory;
69     private List<RadioButtonPreference> mRadioButtonPreferences = new ArrayList<>();
70 
ZenModePrioritySendersPreferenceController(Context context, String key, Lifecycle lifecycle, boolean isMessages)71     public ZenModePrioritySendersPreferenceController(Context context, String key,
72             Lifecycle lifecycle, boolean isMessages) {
73         super(context, key, lifecycle);
74         mIsMessages = isMessages;
75 
76         mPackageManager = mContext.getPackageManager();
77         if (!FALLBACK_INTENT.hasCategory(Intent.CATEGORY_APP_CONTACTS)) {
78             FALLBACK_INTENT.addCategory(Intent.CATEGORY_APP_CONTACTS);
79         }
80     }
81 
82     @Override
displayPreference(PreferenceScreen screen)83     public void displayPreference(PreferenceScreen screen) {
84         mPreferenceCategory = screen.findPreference(getPreferenceKey());
85         if (mPreferenceCategory.findPreference(KEY_ANY) == null) {
86             makeRadioPreference(KEY_STARRED,
87                     com.android.settings.R.string.zen_mode_from_starred);
88             makeRadioPreference(KEY_CONTACTS,
89                     com.android.settings.R.string.zen_mode_from_contacts);
90             makeRadioPreference(KEY_ANY,
91                     com.android.settings.R.string.zen_mode_from_anyone);
92             makeRadioPreference(KEY_NONE,
93                     mIsMessages
94                             ? com.android.settings.R.string.zen_mode_none_messages
95                             : com.android.settings.R.string.zen_mode_none_calls);
96             updateSummaries();
97         }
98 
99         super.displayPreference(screen);
100     }
101 
102     @Override
isAvailable()103     public boolean isAvailable() {
104         return true;
105     }
106 
107     @Override
getPreferenceKey()108     public String getPreferenceKey() {
109         return KEY;
110     }
111 
112     @Override
updateState(Preference preference)113     public void updateState(Preference preference) {
114         final int currSetting = getPrioritySenders();
115 
116         for (RadioButtonPreference pref : mRadioButtonPreferences) {
117             pref.setChecked(keyToSetting(pref.getKey()) == currSetting);
118         }
119     }
120 
121     @Override
onResume()122     public void onResume() {
123         super.onResume();
124         updateSummaries();
125     }
126 
updateSummaries()127     private void updateSummaries() {
128         for (RadioButtonPreference pref : mRadioButtonPreferences) {
129             pref.setSummary(getSummary(pref.getKey()));
130         }
131     }
132 
keyToSetting(String key)133     private static int keyToSetting(String key) {
134         switch (key) {
135             case KEY_STARRED:
136                 return NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
137             case KEY_CONTACTS:
138                 return NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS;
139             case KEY_ANY:
140                 return NotificationManager.Policy.PRIORITY_SENDERS_ANY;
141             case KEY_NONE:
142             default:
143                 return ZenModeBackend.SOURCE_NONE;
144         }
145     }
146 
getSummary(String key)147     private String getSummary(String key) {
148         switch (key) {
149             case KEY_STARRED:
150                 return mBackend.getStarredContactsSummary(mContext);
151             case KEY_CONTACTS:
152                 return mBackend.getContactsNumberSummary(mContext);
153             case KEY_ANY:
154                 return mContext.getResources().getString(mIsMessages
155                                 ? R.string.zen_mode_all_messages_summary
156                                 : R.string.zen_mode_all_calls_summary);
157             case KEY_NONE:
158             default:
159                 return null;
160         }
161     }
162 
getPrioritySenders()163     private int getPrioritySenders() {
164         if (mIsMessages) {
165             return mBackend.getPriorityMessageSenders();
166         } else {
167             return mBackend.getPriorityCallSenders();
168         }
169     }
170 
makeRadioPreference(String key, int titleId)171     private RadioButtonPreference makeRadioPreference(String key, int titleId) {
172         final RadioButtonPreference pref =
173                 new RadioButtonPreference(mPreferenceCategory.getContext());
174         pref.setKey(key);
175         pref.setTitle(titleId);
176         pref.setOnClickListener(mRadioButtonClickListener);
177 
178         View.OnClickListener widgetClickListener = getWidgetClickListener(key);
179         if (widgetClickListener != null) {
180             pref.setExtraWidgetOnClickListener(widgetClickListener);
181         }
182 
183         mPreferenceCategory.addPreference(pref);
184         mRadioButtonPreferences.add(pref);
185         return pref;
186     }
187 
188     private RadioButtonPreference.OnClickListener mRadioButtonClickListener =
189             new RadioButtonPreference.OnClickListener() {
190         @Override
191         public void onRadioButtonClicked(RadioButtonPreference preference) {
192             int selectedSetting = keyToSetting(preference.getKey());
193             if (selectedSetting != getPrioritySenders()) {
194                 mBackend.saveSenders(
195                         mIsMessages ? PRIORITY_CATEGORY_MESSAGES : PRIORITY_CATEGORY_CALLS,
196                         selectedSetting);
197             }
198         }
199     };
200 
getWidgetClickListener(String key)201     private View.OnClickListener getWidgetClickListener(String key) {
202         if (!KEY_CONTACTS.equals(key) && !KEY_STARRED.equals(key)) {
203             return null;
204         }
205 
206         if (KEY_STARRED.equals(key) && !isStarredIntentValid()) {
207             return null;
208         }
209 
210         if (KEY_CONTACTS.equals(key) && !isContactsIntentValid()) {
211             return null;
212         }
213 
214         return new View.OnClickListener() {
215             @Override
216             public void onClick(View v) {
217                 if (KEY_STARRED.equals(key)
218                         && STARRED_CONTACTS_INTENT.resolveActivity(mPackageManager) != null) {
219                     mContext.startActivity(STARRED_CONTACTS_INTENT);
220                 } else if (KEY_CONTACTS.equals(key)
221                         && ALL_CONTACTS_INTENT.resolveActivity(mPackageManager) != null) {
222                     mContext.startActivity(ALL_CONTACTS_INTENT);
223                 } else {
224                     mContext.startActivity(FALLBACK_INTENT);
225                 }
226             }
227         };
228     }
229 
230     private boolean isStarredIntentValid() {
231         return STARRED_CONTACTS_INTENT.resolveActivity(mPackageManager) != null
232                 || FALLBACK_INTENT.resolveActivity(mPackageManager) != null;
233     }
234 
235     private boolean isContactsIntentValid() {
236         return ALL_CONTACTS_INTENT.resolveActivity(mPackageManager) != null
237                 || FALLBACK_INTENT.resolveActivity(mPackageManager) != null;
238     }
239 }
240