• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 com.android.settings.R;
20 import com.android.settings.SettingsPreferenceFragment;
21 import com.android.settings.applications.AppInfoBase;
22 import com.android.settingslib.RestrictedLockUtils;
23 import com.android.settingslib.RestrictedSwitchPreference;
24 
25 import android.app.Notification;
26 import android.app.admin.DevicePolicyManager;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.pm.PackageInfo;
30 import android.content.pm.PackageManager;
31 import android.content.pm.PackageManager.NameNotFoundException;
32 import android.os.Bundle;
33 import android.os.UserHandle;
34 import android.os.UserManager;
35 import android.provider.Settings;
36 import android.service.notification.NotificationListenerService.Ranking;
37 import android.support.v7.preference.Preference;
38 import android.text.TextUtils;
39 import android.util.Log;
40 import android.widget.Toast;
41 
42 import java.util.ArrayList;
43 
44 import static com.android.settings.notification.RestrictedDropDownPreference.RestrictedItem;
45 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
46 
47 abstract public class NotificationSettingsBase extends SettingsPreferenceFragment {
48     private static final String TAG = "NotifiSettingsBase";
49     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
50     private static final String TUNER_SETTING = "show_importance_slider";
51 
52     protected static final String KEY_BYPASS_DND = "bypass_dnd";
53     protected static final String KEY_VISIBILITY_OVERRIDE = "visibility_override";
54     protected static final String KEY_IMPORTANCE = "importance";
55     protected static final String KEY_BLOCK = "block";
56     protected static final String KEY_SILENT = "silent";
57 
58     protected PackageManager mPm;
59     protected UserManager mUm;
60     protected final NotificationBackend mBackend = new NotificationBackend();
61     protected Context mContext;
62     protected boolean mCreated;
63     protected int mUid;
64     protected int mUserId;
65     protected String mPkg;
66     protected PackageInfo mPkgInfo;
67     protected ImportanceSeekBarPreference mImportance;
68     protected RestrictedSwitchPreference mPriority;
69     protected RestrictedDropDownPreference mVisibilityOverride;
70     protected RestrictedSwitchPreference mBlock;
71     protected RestrictedSwitchPreference mSilent;
72     protected EnforcedAdmin mSuspendedAppsAdmin;
73     protected boolean mShowSlider = false;
74 
75     @Override
onActivityCreated(Bundle savedInstanceState)76     public void onActivityCreated(Bundle savedInstanceState) {
77         super.onActivityCreated(savedInstanceState);
78         if (DEBUG) Log.d(TAG, "onActivityCreated mCreated=" + mCreated);
79         if (mCreated) {
80             Log.w(TAG, "onActivityCreated: ignoring duplicate call");
81             return;
82         }
83         mCreated = true;
84     }
85 
86     @Override
onCreate(Bundle savedInstanceState)87     public void onCreate(Bundle savedInstanceState) {
88         super.onCreate(savedInstanceState);
89         mContext = getActivity();
90         Intent intent = getActivity().getIntent();
91         Bundle args = getArguments();
92         if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
93         if (intent == null && args == null) {
94             Log.w(TAG, "No intent");
95             toastAndFinish();
96             return;
97         }
98 
99         mPm = getPackageManager();
100         mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
101 
102         mPkg = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_NAME)
103                 ? args.getString(AppInfoBase.ARG_PACKAGE_NAME)
104                 : intent.getStringExtra(Settings.EXTRA_APP_PACKAGE);
105         mUid = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_UID)
106                 ? args.getInt(AppInfoBase.ARG_PACKAGE_UID)
107                 : intent.getIntExtra(Settings.EXTRA_APP_UID, -1);
108         if (mUid == -1 || TextUtils.isEmpty(mPkg)) {
109             Log.w(TAG, "Missing extras: " + Settings.EXTRA_APP_PACKAGE + " was " + mPkg + ", "
110                     + Settings.EXTRA_APP_UID + " was " + mUid);
111             toastAndFinish();
112             return;
113         }
114         mUserId = UserHandle.getUserId(mUid);
115 
116         if (DEBUG) Log.d(TAG, "Load details for pkg=" + mPkg + " uid=" + mUid);
117         mPkgInfo = findPackageInfo(mPkg, mUid);
118         if (mPkgInfo == null) {
119             Log.w(TAG, "Failed to find package info: " + Settings.EXTRA_APP_PACKAGE + " was " + mPkg
120                     + ", " + Settings.EXTRA_APP_UID + " was " + mUid);
121             toastAndFinish();
122             return;
123         }
124 
125         mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
126                 mContext, mPkg, mUserId);
127         mShowSlider = Settings.Secure.getInt(getContentResolver(), TUNER_SETTING, 0) == 1;
128     }
129 
130     @Override
onResume()131     public void onResume() {
132         super.onResume();
133         if ((mUid != -1 && getPackageManager().getPackagesForUid(mUid) == null)) {
134             // App isn't around anymore, must have been removed.
135             finish();
136             return;
137         }
138         mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
139                 mContext, mPkg, mUserId);
140         if (mImportance != null) {
141             mImportance.setDisabledByAdmin(mSuspendedAppsAdmin);
142         }
143         if (mPriority != null) {
144             mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
145         }
146         if (mBlock != null) {
147             mBlock.setDisabledByAdmin(mSuspendedAppsAdmin);
148         }
149         if (mSilent != null) {
150             mSilent.setDisabledByAdmin(mSuspendedAppsAdmin);
151         }
152         if (mVisibilityOverride != null) {
153             mVisibilityOverride.setDisabledByAdmin(mSuspendedAppsAdmin);
154         }
155     }
156 
setupImportancePrefs(boolean notBlockable, boolean notSilenceable, int importance, boolean banned)157     protected void setupImportancePrefs(boolean notBlockable, boolean notSilenceable,
158             int importance, boolean banned) {
159         if (mShowSlider && !notSilenceable) {
160             setVisible(mBlock, false);
161             setVisible(mSilent, false);
162             mImportance.setDisabledByAdmin(mSuspendedAppsAdmin);
163             mImportance.setMinimumProgress(
164                     notBlockable ? Ranking.IMPORTANCE_MIN : Ranking.IMPORTANCE_NONE);
165             mImportance.setMax(Ranking.IMPORTANCE_MAX);
166             mImportance.setProgress(importance);
167             mImportance.setAutoOn(importance == Ranking.IMPORTANCE_UNSPECIFIED);
168             mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
169                 @Override
170                 public void onImportanceChanged(int progress, boolean fromUser) {
171                     if (fromUser) {
172                         mBackend.setImportance(mPkg, mUid, progress);
173                     }
174                     updateDependents(progress);
175                 }
176             });
177         } else {
178             setVisible(mImportance, false);
179             // Hide controls that are not settable, unless they are already switched on.
180             final boolean blocked = (importance == Ranking.IMPORTANCE_NONE || banned);
181             if (notBlockable && !blocked) {
182                 setVisible(mBlock, false);
183             } else {
184                 mBlock.setChecked(blocked);
185                 mBlock.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
186                     @Override
187                     public boolean onPreferenceChange(Preference preference, Object newValue) {
188                         final boolean blocked = (Boolean) newValue;
189                         final int importance =
190                                 blocked ? Ranking.IMPORTANCE_NONE : Ranking.IMPORTANCE_UNSPECIFIED;
191                         mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
192                         updateDependents(importance);
193                         return true;
194                     }
195                 });
196             }
197             final boolean silenced = (importance == Ranking.IMPORTANCE_LOW);
198             if (notSilenceable && !silenced) {
199                 setVisible(mSilent, false);
200             } else {
201                 mSilent.setChecked(silenced);
202                 mSilent.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
203                     @Override
204                     public boolean onPreferenceChange(Preference preference, Object newValue) {
205                         final boolean silenced = (Boolean) newValue;
206                         final int importance =
207                                 silenced ? Ranking.IMPORTANCE_LOW : Ranking.IMPORTANCE_UNSPECIFIED;
208                         mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
209                         updateDependents(importance);
210                         return true;
211                     }
212                 });
213             }
214             updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance);
215         }
216     }
217 
setupPriorityPref(boolean priority)218     protected void setupPriorityPref(boolean priority) {
219         mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
220         mPriority.setChecked(priority);
221         mPriority.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
222             @Override
223             public boolean onPreferenceChange(Preference preference, Object newValue) {
224                 final boolean bypassZenMode = (Boolean) newValue;
225                 return mBackend.setBypassZenMode(mPkgInfo.packageName, mUid, bypassZenMode);
226             }
227         });
228     }
229 
setupVisOverridePref(int sensitive)230     protected void setupVisOverridePref(int sensitive) {
231         ArrayList<CharSequence> entries = new ArrayList<>();
232         ArrayList<CharSequence> values = new ArrayList<>();
233 
234         mVisibilityOverride.clearRestrictedItems();
235         if (getLockscreenNotificationsEnabled() && getLockscreenAllowPrivateNotifications()) {
236             final String summaryShowEntry =
237                     getString(R.string.lock_screen_notifications_summary_show);
238             final String summaryShowEntryValue = Integer.toString(Ranking.VISIBILITY_NO_OVERRIDE);
239             entries.add(summaryShowEntry);
240             values.add(summaryShowEntryValue);
241             setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
242                     DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS
243                             | DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
244         }
245 
246         final String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
247         final String summaryHideEntryValue = Integer.toString(Notification.VISIBILITY_PRIVATE);
248         entries.add(summaryHideEntry);
249         values.add(summaryHideEntryValue);
250         setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
251                 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
252         entries.add(getString(R.string.lock_screen_notifications_summary_disable));
253         values.add(Integer.toString(Notification.VISIBILITY_SECRET));
254         mVisibilityOverride.setEntries(entries.toArray(new CharSequence[entries.size()]));
255         mVisibilityOverride.setEntryValues(values.toArray(new CharSequence[values.size()]));
256 
257         if (sensitive == Ranking.VISIBILITY_NO_OVERRIDE) {
258             mVisibilityOverride.setValue(Integer.toString(getGlobalVisibility()));
259         } else {
260             mVisibilityOverride.setValue(Integer.toString(sensitive));
261         }
262         mVisibilityOverride.setSummary("%s");
263 
264         mVisibilityOverride.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
265             @Override
266             public boolean onPreferenceChange(Preference preference, Object newValue) {
267                 int sensitive = Integer.parseInt((String) newValue);
268                 if (sensitive == getGlobalVisibility()) {
269                     sensitive = Ranking.VISIBILITY_NO_OVERRIDE;
270                 }
271                 mBackend.setVisibilityOverride(mPkgInfo.packageName, mUid, sensitive);
272                 return true;
273             }
274         });
275     }
276 
setRestrictedIfNotificationFeaturesDisabled(CharSequence entry, CharSequence entryValue, int keyguardNotificationFeatures)277     private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
278             CharSequence entryValue, int keyguardNotificationFeatures) {
279         EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
280                 mContext, keyguardNotificationFeatures, mUserId);
281         if (admin != null) {
282             RestrictedItem item = new RestrictedItem(entry, entryValue, admin);
283             mVisibilityOverride.addRestrictedItem(item);
284         }
285     }
286 
getGlobalVisibility()287     private int getGlobalVisibility() {
288         int globalVis = Ranking.VISIBILITY_NO_OVERRIDE;
289         if (!getLockscreenNotificationsEnabled()) {
290             globalVis = Notification.VISIBILITY_SECRET;
291         } else if (!getLockscreenAllowPrivateNotifications()) {
292             globalVis = Notification.VISIBILITY_PRIVATE;
293         }
294         return globalVis;
295     }
296 
getLockscreenNotificationsEnabled()297     protected boolean getLockscreenNotificationsEnabled() {
298         return Settings.Secure.getInt(getContentResolver(),
299                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
300     }
301 
getLockscreenAllowPrivateNotifications()302     protected boolean getLockscreenAllowPrivateNotifications() {
303         return Settings.Secure.getInt(getContentResolver(),
304                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
305     }
306 
updateDependents(int progress)307     abstract void updateDependents(int progress);
308 
setVisible(Preference p, boolean visible)309     protected void setVisible(Preference p, boolean visible) {
310         final boolean isVisible = getPreferenceScreen().findPreference(p.getKey()) != null;
311         if (isVisible == visible) return;
312         if (visible) {
313             getPreferenceScreen().addPreference(p);
314         } else {
315             getPreferenceScreen().removePreference(p);
316         }
317     }
318 
toastAndFinish()319     protected void toastAndFinish() {
320         Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
321         getActivity().finish();
322     }
323 
findPackageInfo(String pkg, int uid)324     private PackageInfo findPackageInfo(String pkg, int uid) {
325         final String[] packages = mPm.getPackagesForUid(uid);
326         if (packages != null && pkg != null) {
327             final int N = packages.length;
328             for (int i = 0; i < N; i++) {
329                 final String p = packages[i];
330                 if (pkg.equals(p)) {
331                     try {
332                         return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
333                     } catch (NameNotFoundException e) {
334                         Log.w(TAG, "Failed to load package " + pkg, e);
335                     }
336                 }
337             }
338         }
339         return null;
340     }
341 }
342