• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Application;
20 import android.app.NotificationChannel;
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.os.Bundle;
24 import android.provider.Settings;
25 
26 import androidx.annotation.VisibleForTesting;
27 import androidx.core.text.BidiFormatter;
28 import androidx.fragment.app.Fragment;
29 import androidx.preference.Preference;
30 import androidx.preference.PreferenceScreen;
31 
32 import com.android.settings.R;
33 import com.android.settings.applications.AppInfoBase;
34 import com.android.settings.core.PreferenceControllerMixin;
35 import com.android.settings.core.SubSettingLauncher;
36 import com.android.settingslib.applications.ApplicationsState;
37 import com.android.settingslib.core.AbstractPreferenceController;
38 import com.android.settingslib.widget.apppreference.AppPreference;
39 
40 import java.util.ArrayList;
41 import java.util.List;
42 
43 /**
44  * Adds a preference to the PreferenceScreen for each notification channel that can bypass DND.
45  */
46 public class ZenModeAllBypassingAppsPreferenceController extends AbstractPreferenceController
47         implements PreferenceControllerMixin {
48 
49     private final String KEY = "zen_mode_bypassing_apps_category";
50 
51     @VisibleForTesting ApplicationsState mApplicationsState;
52     @VisibleForTesting PreferenceScreen mPreferenceScreen;
53     @VisibleForTesting Context mPrefContext;
54 
55     private ApplicationsState.Session mAppSession;
56     private NotificationBackend mNotificationBackend = new NotificationBackend();
57     private Fragment mHostFragment;
58 
ZenModeAllBypassingAppsPreferenceController(Context context, Application app, Fragment host)59     public ZenModeAllBypassingAppsPreferenceController(Context context, Application app,
60             Fragment host) {
61 
62         this(context, app == null ? null : ApplicationsState.getInstance(app), host);
63     }
64 
ZenModeAllBypassingAppsPreferenceController(Context context, ApplicationsState appState, Fragment host)65     private ZenModeAllBypassingAppsPreferenceController(Context context, ApplicationsState appState,
66             Fragment host) {
67         super(context);
68         mApplicationsState = appState;
69         mHostFragment = host;
70 
71         if (mApplicationsState != null && host != null) {
72             mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle());
73         }
74     }
75 
76     @Override
displayPreference(PreferenceScreen screen)77     public void displayPreference(PreferenceScreen screen) {
78         mPreferenceScreen = screen;
79         mPrefContext = mPreferenceScreen.getContext();
80         updateNotificationChannelList();
81         super.displayPreference(screen);
82     }
83 
84     @Override
isAvailable()85     public boolean isAvailable() {
86         return true;
87     }
88 
89     @Override
getPreferenceKey()90     public String getPreferenceKey() {
91         return KEY;
92     }
93 
94     /**
95      * Call this method to trigger the notification channels list to refresh.
96      */
updateNotificationChannelList()97     public void updateNotificationChannelList() {
98         if (mAppSession == null) {
99             return;
100         }
101 
102         ApplicationsState.AppFilter filter = ApplicationsState.FILTER_ALL_ENABLED;
103         List<ApplicationsState.AppEntry> apps = mAppSession.rebuild(filter,
104                 ApplicationsState.ALPHA_COMPARATOR);
105         if (apps != null) {
106             updateNotificationChannelList(apps);
107         }
108     }
109 
110     @VisibleForTesting
updateNotificationChannelList(List<ApplicationsState.AppEntry> apps)111     void updateNotificationChannelList(List<ApplicationsState.AppEntry> apps) {
112         if (mPreferenceScreen == null || apps == null) {
113             return;
114         }
115 
116         List<Preference> channelsBypassingDnd = new ArrayList<>();
117         for (ApplicationsState.AppEntry entry : apps) {
118             String pkg = entry.info.packageName;
119             mApplicationsState.ensureIcon(entry);
120             for (NotificationChannel channel : mNotificationBackend
121                     .getNotificationChannelsBypassingDnd(pkg, entry.info.uid).getList()) {
122                 Preference pref = new AppPreference(mPrefContext);
123                 pref.setKey(pkg + "|" + channel.getId());
124                 pref.setTitle(BidiFormatter.getInstance().unicodeWrap(entry.label));
125                 pref.setIcon(entry.icon);
126                 pref.setSummary(BidiFormatter.getInstance().unicodeWrap(channel.getName()));
127 
128                 pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
129                     @Override
130                     public boolean onPreferenceClick(Preference preference) {
131                         Bundle args = new Bundle();
132                         args.putString(AppInfoBase.ARG_PACKAGE_NAME, entry.info.packageName);
133                         args.putInt(AppInfoBase.ARG_PACKAGE_UID, entry.info.uid);
134                         args.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
135                         new SubSettingLauncher(mContext)
136                                 .setDestination(ChannelNotificationSettings.class.getName())
137                                 .setArguments(args)
138                                 .setTitleRes(R.string.notification_channel_title)
139                                 .setResultListener(mHostFragment, 0)
140                                 .setSourceMetricsCategory(
141                                         SettingsEnums.NOTIFICATION_ZEN_MODE_OVERRIDING_APP)
142                                 .launch();
143                         return true;
144                     }
145                 });
146                 channelsBypassingDnd.add(pref);
147             }
148 
149             mPreferenceScreen.removeAll();
150             if (channelsBypassingDnd.size() > 0) {
151                 for (Preference prefToAdd : channelsBypassingDnd) {
152                     mPreferenceScreen.addPreference(prefToAdd);
153                 }
154             }
155         }
156     }
157 
158     private final ApplicationsState.Callbacks mAppSessionCallbacks =
159             new ApplicationsState.Callbacks() {
160 
161                 @Override
162                 public void onRunningStateChanged(boolean running) {
163                     updateNotificationChannelList();
164                 }
165 
166                 @Override
167                 public void onPackageListChanged() {
168                     updateNotificationChannelList();
169                 }
170 
171                 @Override
172                 public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
173                     updateNotificationChannelList(apps);
174                 }
175 
176                 @Override
177                 public void onPackageIconChanged() {
178                     updateNotificationChannelList();
179                 }
180 
181                 @Override
182                 public void onPackageSizeChanged(String packageName) {
183                     updateNotificationChannelList();
184                 }
185 
186                 @Override
187                 public void onAllSizesComputed() { }
188 
189                 @Override
190                 public void onLauncherInfoChanged() {
191                     updateNotificationChannelList();
192                 }
193 
194                 @Override
195                 public void onLoadEntriesCompleted() {
196                     updateNotificationChannelList();
197                 }
198             };
199 }
200