2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.notification;
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;
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;
42 import java.util.ArrayList;
44 import static com.android.settings.notification.RestrictedDropDownPreference.RestrictedItem;
45 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
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";
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";
58 protected PackageManager mPm;
59 protected UserManager mUm;
60 protected final NotificationBackend mBackend = new NotificationBackend();
61 protected Context mContext;
62 protected boolean mCreated;
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;
76 public void onActivityCreated(Bundle savedInstanceState) {
77 super.onActivityCreated(savedInstanceState);
78 if (DEBUG) Log.d(TAG, "onActivityCreated mCreated=" + mCreated);
80 Log.w(TAG, "onActivityCreated: ignoring duplicate call");
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");
99 mPm = getPackageManager();
100 mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
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);
114 mUserId = UserHandle.getUserId(mUid);
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);
125 mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
126 mContext, mPkg, mUserId);
127 mShowSlider = Settings.Secure.getInt(getContentResolver(), TUNER_SETTING, 0) == 1;
131 public void onResume() {
133 if ((mUid != -1 && getPackageManager().getPackagesForUid(mUid) == null)) {
134 // App isn't around anymore, must have been removed.
138 mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
139 mContext, mPkg, mUserId);
140 if (mImportance != null) {
141 mImportance.setDisabledByAdmin(mSuspendedAppsAdmin);
143 if (mPriority != null) {
144 mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
146 if (mBlock != null) {
147 mBlock.setDisabledByAdmin(mSuspendedAppsAdmin);
149 if (mSilent != null) {
150 mSilent.setDisabledByAdmin(mSuspendedAppsAdmin);
152 if (mVisibilityOverride != null) {
153 mVisibilityOverride.setDisabledByAdmin(mSuspendedAppsAdmin);
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() {
170 public void onImportanceChanged(int progress, boolean fromUser) {
172 mBackend.setImportance(mPkg, mUid, progress);
174 updateDependents(progress);
178 setVisible(mImportance, false);
180 setVisible(mBlock, false);
182 boolean blocked = importance == Ranking.IMPORTANCE_NONE || banned;
183 mBlock.setChecked(blocked);
184 mBlock.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
186 public boolean onPreferenceChange(Preference preference, Object newValue) {
187 final boolean blocked = (Boolean) newValue;
188 final int importance =
189 blocked ? Ranking.IMPORTANCE_NONE : Ranking.IMPORTANCE_UNSPECIFIED;
190 mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
191 updateDependents(importance);
196 if (notSilenceable) {
197 setVisible(mSilent, false);
199 mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW);
200 mSilent.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
202 public boolean onPreferenceChange(Preference preference, Object newValue) {
203 final boolean silenced = (Boolean) newValue;
204 final int importance =
205 silenced ? Ranking.IMPORTANCE_LOW : Ranking.IMPORTANCE_UNSPECIFIED;
206 mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
207 updateDependents(importance);
212 updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance);
216 protected void setupPriorityPref(boolean priority) {
217 mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
218 mPriority.setChecked(priority);
219 mPriority.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
221 public boolean onPreferenceChange(Preference preference, Object newValue) {
222 final boolean bypassZenMode = (Boolean) newValue;
223 return mBackend.setBypassZenMode(mPkgInfo.packageName, mUid, bypassZenMode);
228 protected void setupVisOverridePref(int sensitive) {
229 ArrayList<CharSequence> entries = new ArrayList<>();
230 ArrayList<CharSequence> values = new ArrayList<>();
232 mVisibilityOverride.clearRestrictedItems();
233 if (getLockscreenNotificationsEnabled() && getLockscreenAllowPrivateNotifications()) {
234 final String summaryShowEntry =
235 getString(R.string.lock_screen_notifications_summary_show);
236 final String summaryShowEntryValue = Integer.toString(Ranking.VISIBILITY_NO_OVERRIDE);
237 entries.add(summaryShowEntry);
238 values.add(summaryShowEntryValue);
239 setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
240 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS
241 | DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
244 final String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
245 final String summaryHideEntryValue = Integer.toString(Notification.VISIBILITY_PRIVATE);
246 entries.add(summaryHideEntry);
247 values.add(summaryHideEntryValue);
248 setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
249 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
250 entries.add(getString(R.string.lock_screen_notifications_summary_disable));
251 values.add(Integer.toString(Notification.VISIBILITY_SECRET));
252 mVisibilityOverride.setEntries(entries.toArray(new CharSequence[entries.size()]));
253 mVisibilityOverride.setEntryValues(values.toArray(new CharSequence[values.size()]));
255 if (sensitive == Ranking.VISIBILITY_NO_OVERRIDE) {
256 mVisibilityOverride.setValue(Integer.toString(getGlobalVisibility()));
258 mVisibilityOverride.setValue(Integer.toString(sensitive));
260 mVisibilityOverride.setSummary("%s");
262 mVisibilityOverride.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
264 public boolean onPreferenceChange(Preference preference, Object newValue) {
265 int sensitive = Integer.parseInt((String) newValue);
266 if (sensitive == getGlobalVisibility()) {
267 sensitive = Ranking.VISIBILITY_NO_OVERRIDE;
269 mBackend.setVisibilityOverride(mPkgInfo.packageName, mUid, sensitive);
275 private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
276 CharSequence entryValue, int keyguardNotificationFeatures) {
277 EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
278 mContext, keyguardNotificationFeatures, mUserId);
280 RestrictedItem item = new RestrictedItem(entry, entryValue, admin);
281 mVisibilityOverride.addRestrictedItem(item);
285 private int getGlobalVisibility() {
286 int globalVis = Ranking.VISIBILITY_NO_OVERRIDE;
287 if (!getLockscreenNotificationsEnabled()) {
288 globalVis = Notification.VISIBILITY_SECRET;
289 } else if (!getLockscreenAllowPrivateNotifications()) {
290 globalVis = Notification.VISIBILITY_PRIVATE;
295 protected boolean getLockscreenNotificationsEnabled() {
296 return Settings.Secure.getInt(getContentResolver(),
297 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
300 protected boolean getLockscreenAllowPrivateNotifications() {
301 return Settings.Secure.getInt(getContentResolver(),
302 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
305 abstract void updateDependents(int progress);
307 protected void setVisible(Preference p, boolean visible) {
308 final boolean isVisible = getPreferenceScreen().findPreference(p.getKey()) != null;
309 if (isVisible == visible) return;
311 getPreferenceScreen().addPreference(p);
313 getPreferenceScreen().removePreference(p);
317 protected void toastAndFinish() {
318 Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
319 getActivity().finish();
322 private PackageInfo findPackageInfo(String pkg, int uid) {
323 final String[] packages = mPm.getPackagesForUid(uid);
324 if (packages != null && pkg != null) {
325 final int N = packages.length;
326 for (int i = 0; i < N; i++) {
327 final String p = packages[i];
330 return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
331 } catch (NameNotFoundException e) {
332 Log.w(TAG, "Failed to load package " + pkg, e);