1 /*
2  * Copyright (C) 2015 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 static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
20 
21 import android.app.Activity;
22 import android.app.Application;
23 import android.app.settings.SettingsEnums;
24 import android.app.usage.IUsageStatsManager;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.os.Bundle;
28 import android.os.ServiceManager;
29 import android.os.UserHandle;
30 import android.os.UserManager;
31 import android.provider.SearchIndexableResource;
32 import android.text.TextUtils;
33 
34 import androidx.annotation.VisibleForTesting;
35 import androidx.fragment.app.Fragment;
36 import androidx.preference.Preference;
37 import androidx.preference.PreferenceCategory;
38 import androidx.preference.PreferenceScreen;
39 
40 import com.android.settings.R;
41 import com.android.settings.RingtonePreference;
42 import com.android.settings.core.OnActivityResultListener;
43 import com.android.settings.dashboard.DashboardFragment;
44 import com.android.settings.dashboard.SummaryLoader;
45 import com.android.settings.search.BaseSearchIndexProvider;
46 import com.android.settings.search.Indexable;
47 import com.android.settingslib.core.AbstractPreferenceController;
48 import com.android.settingslib.core.lifecycle.Lifecycle;
49 import com.android.settingslib.search.SearchIndexable;
50 
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.List;
54 
55 @SearchIndexable
56 public class ConfigureNotificationSettings extends DashboardFragment implements
57         OnActivityResultListener {
58     private static final String TAG = "ConfigNotiSettings";
59 
60     @VisibleForTesting
61     static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint_notifications";
62     static final String KEY_LOCKSCREEN = "lock_screen_notifications";
63 
64     private static final String KEY_NOTI_DEFAULT_RINGTONE = "notification_default_ringtone";
65     private static final int REQUEST_CODE = 200;
66     private static final String SELECTED_PREFERENCE_KEY = "selected_preference";
67     private static final String KEY_ADVANCED_CATEGORY = "configure_notifications_advanced";
68 
69     private RingtonePreference mRequestPreference;
70 
71     @Override
getMetricsCategory()72     public int getMetricsCategory() {
73         return SettingsEnums.CONFIGURE_NOTIFICATION;
74     }
75 
76     @Override
getLogTag()77     protected String getLogTag() {
78         return TAG;
79     }
80 
81     @Override
getPreferenceScreenResId()82     protected int getPreferenceScreenResId() {
83         return R.xml.configure_notification_settings;
84     }
85 
86     @Override
createPreferenceControllers(Context context)87     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
88         final Activity activity = getActivity();
89         final Application app;
90         if (activity != null) {
91             app = activity.getApplication();
92         } else {
93             app = null;
94         }
95         return buildPreferenceControllers(context, app, this);
96     }
97 
buildPreferenceControllers(Context context, Application app, Fragment host)98     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
99             Application app, Fragment host) {
100         final List<AbstractPreferenceController> controllers = new ArrayList<>();
101         controllers.add(new RecentNotifyingAppsPreferenceController(
102                 context, new NotificationBackend(), IUsageStatsManager.Stub.asInterface(
103                         ServiceManager.getService(Context.USAGE_STATS_SERVICE)),
104                 context.getSystemService(UserManager.class), app, host));
105         controllers.add(new ShowOnLockScreenNotificationPreferenceController(
106                 context, KEY_LOCKSCREEN));
107         controllers.add(new NotificationRingtonePreferenceController(context) {
108             @Override
109             public String getPreferenceKey() {
110                 return KEY_NOTI_DEFAULT_RINGTONE;
111             }
112 
113         });
114         return controllers;
115     }
116 
117     @Override
onCreate(Bundle icicle)118     public void onCreate(Bundle icicle) {
119         super.onCreate(icicle);
120         final PreferenceScreen screen = getPreferenceScreen();
121         final Bundle arguments = getArguments();
122 
123         if (screen == null) {
124             return;
125         }
126         if (arguments != null) {
127             final String highlightKey = arguments.getString(EXTRA_FRAGMENT_ARG_KEY);
128             if (!TextUtils.isEmpty(highlightKey)) {
129                 final PreferenceCategory advancedCategory =
130                         screen.findPreference(KEY_ADVANCED_CATEGORY);
131                 // Has highlight row - expand everything
132                 advancedCategory.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
133                 scrollToPreference(advancedCategory);
134             }
135         }
136     }
137 
138     @Override
onPreferenceTreeClick(Preference preference)139     public boolean onPreferenceTreeClick(Preference preference) {
140         if (preference instanceof RingtonePreference) {
141             mRequestPreference = (RingtonePreference) preference;
142             mRequestPreference.onPrepareRingtonePickerIntent(mRequestPreference.getIntent());
143             getActivity().startActivityForResultAsUser(
144                     mRequestPreference.getIntent(),
145                     REQUEST_CODE,
146                     null,
147                     UserHandle.of(mRequestPreference.getUserId()));
148             return true;
149         }
150         return super.onPreferenceTreeClick(preference);
151     }
152 
153     @Override
onActivityResult(int requestCode, int resultCode, Intent data)154     public void onActivityResult(int requestCode, int resultCode, Intent data) {
155         if (mRequestPreference != null) {
156             mRequestPreference.onActivityResult(requestCode, resultCode, data);
157             mRequestPreference = null;
158         }
159     }
160 
161     @Override
onSaveInstanceState(Bundle outState)162     public void onSaveInstanceState(Bundle outState) {
163         super.onSaveInstanceState(outState);
164         if (mRequestPreference != null) {
165             outState.putString(SELECTED_PREFERENCE_KEY, mRequestPreference.getKey());
166         }
167     }
168 
169     /**
170      * For summary
171      */
172     static class SummaryProvider implements SummaryLoader.SummaryProvider {
173 
174         private final Context mContext;
175         private final SummaryLoader mSummaryLoader;
176         private NotificationBackend mBackend;
177 
SummaryProvider(Context context, SummaryLoader summaryLoader)178         public SummaryProvider(Context context, SummaryLoader summaryLoader) {
179             mContext = context;
180             mSummaryLoader = summaryLoader;
181             mBackend = new NotificationBackend();
182         }
183 
184         @VisibleForTesting
setBackend(NotificationBackend backend)185         protected void setBackend(NotificationBackend backend) {
186             mBackend = backend;
187         }
188 
189         @Override
setListening(boolean listening)190         public void setListening(boolean listening) {
191             if (!listening) {
192                 return;
193             }
194             int blockedAppCount = mBackend.getBlockedAppCount();
195             if (blockedAppCount == 0) {
196                 mSummaryLoader.setSummary(this,
197                         mContext.getText(R.string.app_notification_listing_summary_zero));
198             } else {
199                 mSummaryLoader.setSummary(this,
200                         mContext.getResources().getQuantityString(
201                                 R.plurals.app_notification_listing_summary_others,
202                                 blockedAppCount, blockedAppCount));
203             }
204         }
205     }
206 
207     public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY =
208             new SummaryLoader.SummaryProviderFactory() {
209                 @Override
210                 public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
211                         SummaryLoader summaryLoader) {
212                     return new ConfigureNotificationSettings.SummaryProvider(
213                             activity, summaryLoader);
214                 }
215             };
216 
217     /**
218      * For Search.
219      */
220     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
221             new BaseSearchIndexProvider() {
222                 @Override
223                 public List<SearchIndexableResource> getXmlResourcesToIndex(
224                         Context context, boolean enabled) {
225                     final SearchIndexableResource sir = new SearchIndexableResource(context);
226                     sir.xmlResId = R.xml.configure_notification_settings;
227                     return Arrays.asList(sir);
228                 }
229 
230                 @Override
231                 public List<AbstractPreferenceController> createPreferenceControllers(
232                         Context context) {
233                     return buildPreferenceControllers(context, null, null);
234                 }
235 
236                 @Override
237                 public List<String> getNonIndexableKeys(Context context) {
238                     final List<String> keys = super.getNonIndexableKeys(context);
239                     keys.add(KEY_SWIPE_DOWN);
240                     return keys;
241                 }
242             };
243 }
244