Home | History | Annotate | Download | only in notification
      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
     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
     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
    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 
    157     protected void setupImportancePrefs(boolean isSystemApp, int importance, boolean banned) {
    158         if (mShowSlider) {
    159             setVisible(mBlock, false);
    160             setVisible(mSilent, false);
    161             mImportance.setDisabledByAdmin(mSuspendedAppsAdmin);
    162             mImportance.setMinimumProgress(
    163                     isSystemApp ? Ranking.IMPORTANCE_MIN : Ranking.IMPORTANCE_NONE);
    164             mImportance.setMax(Ranking.IMPORTANCE_MAX);
    165             mImportance.setProgress(importance);
    166             mImportance.setAutoOn(importance == Ranking.IMPORTANCE_UNSPECIFIED);
    167             mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
    168                 @Override
    169                 public void onImportanceChanged(int progress, boolean fromUser) {
    170                     if (fromUser) {
    171                         mBackend.setImportance(mPkg, mUid, progress);
    172                     }
    173                     updateDependents(progress);
    174                 }
    175             });
    176         } else {
    177             setVisible(mImportance, false);
    178             if (isSystemApp) {
    179                 setVisible(mBlock, false);
    180             } else {
    181                 boolean blocked = importance == Ranking.IMPORTANCE_NONE || banned;
    182                 mBlock.setChecked(blocked);
    183                 mBlock.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
    184                     @Override
    185                     public boolean onPreferenceChange(Preference preference, Object newValue) {
    186                         final boolean blocked = (Boolean) newValue;
    187                         final int importance =
    188                                 blocked ? Ranking.IMPORTANCE_NONE : Ranking.IMPORTANCE_UNSPECIFIED;
    189                         mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
    190                         updateDependents(importance);
    191                         return true;
    192                     }
    193                 });
    194 
    195                 mSilent.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
    196                     @Override
    197                     public boolean onPreferenceChange(Preference preference, Object newValue) {
    198                         final boolean silenced = (Boolean) newValue;
    199                         final int importance =
    200                                 silenced ? Ranking.IMPORTANCE_LOW : Ranking.IMPORTANCE_UNSPECIFIED;
    201                         mBackend.setImportance(mPkgInfo.packageName, mUid, importance);
    202                         updateDependents(importance);
    203                         return true;
    204                     }
    205                 });
    206                 updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance);
    207             }
    208         }
    209     }
    210 
    211     protected void setupPriorityPref(boolean priority) {
    212         mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
    213         mPriority.setChecked(priority);
    214         mPriority.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
    215             @Override
    216             public boolean onPreferenceChange(Preference preference, Object newValue) {
    217                 final boolean bypassZenMode = (Boolean) newValue;
    218                 return mBackend.setBypassZenMode(mPkgInfo.packageName, mUid, bypassZenMode);
    219             }
    220         });
    221     }
    222 
    223     protected void setupVisOverridePref(int sensitive) {
    224         ArrayList<CharSequence> entries = new ArrayList<>();
    225         ArrayList<CharSequence> values = new ArrayList<>();
    226 
    227         mVisibilityOverride.clearRestrictedItems();
    228         if (getLockscreenNotificationsEnabled() && getLockscreenAllowPrivateNotifications()) {
    229             final String summaryShowEntry =
    230                     getString(R.string.lock_screen_notifications_summary_show);
    231             final String summaryShowEntryValue = Integer.toString(Ranking.VISIBILITY_NO_OVERRIDE);
    232             entries.add(summaryShowEntry);
    233             values.add(summaryShowEntryValue);
    234             setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
    235                     DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS
    236                             | DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
    237         }
    238 
    239         final String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
    240         final String summaryHideEntryValue = Integer.toString(Notification.VISIBILITY_PRIVATE);
    241         entries.add(summaryHideEntry);
    242         values.add(summaryHideEntryValue);
    243         setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
    244                 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
    245         entries.add(getString(R.string.lock_screen_notifications_summary_disable));
    246         values.add(Integer.toString(Notification.VISIBILITY_SECRET));
    247         mVisibilityOverride.setEntries(entries.toArray(new CharSequence[entries.size()]));
    248         mVisibilityOverride.setEntryValues(values.toArray(new CharSequence[values.size()]));
    249 
    250         if (sensitive == Ranking.VISIBILITY_NO_OVERRIDE) {
    251             mVisibilityOverride.setValue(Integer.toString(getGlobalVisibility()));
    252         } else {
    253             mVisibilityOverride.setValue(Integer.toString(sensitive));
    254         }
    255         mVisibilityOverride.setSummary("%s");
    256 
    257         mVisibilityOverride.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
    258             @Override
    259             public boolean onPreferenceChange(Preference preference, Object newValue) {
    260                 int sensitive = Integer.parseInt((String) newValue);
    261                 if (sensitive == getGlobalVisibility()) {
    262                     sensitive = Ranking.VISIBILITY_NO_OVERRIDE;
    263                 }
    264                 mBackend.setVisibilityOverride(mPkgInfo.packageName, mUid, sensitive);
    265                 return true;
    266             }
    267         });
    268     }
    269 
    270     private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
    271             CharSequence entryValue, int keyguardNotificationFeatures) {
    272         EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
    273                 mContext, keyguardNotificationFeatures, mUserId);
    274         if (admin != null) {
    275             RestrictedItem item = new RestrictedItem(entry, entryValue, admin);
    276             mVisibilityOverride.addRestrictedItem(item);
    277         }
    278     }
    279 
    280     private int getGlobalVisibility() {
    281         int globalVis = Ranking.VISIBILITY_NO_OVERRIDE;
    282         if (!getLockscreenNotificationsEnabled()) {
    283             globalVis = Notification.VISIBILITY_SECRET;
    284         } else if (!getLockscreenAllowPrivateNotifications()) {
    285             globalVis = Notification.VISIBILITY_PRIVATE;
    286         }
    287         return globalVis;
    288     }
    289 
    290     protected boolean getLockscreenNotificationsEnabled() {
    291         return Settings.Secure.getInt(getContentResolver(),
    292                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
    293     }
    294 
    295     protected boolean getLockscreenAllowPrivateNotifications() {
    296         return Settings.Secure.getInt(getContentResolver(),
    297                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
    298     }
    299 
    300     abstract void updateDependents(int progress);
    301 
    302     protected void setVisible(Preference p, boolean visible) {
    303         final boolean isVisible = getPreferenceScreen().findPreference(p.getKey()) != null;
    304         if (isVisible == visible) return;
    305         if (visible) {
    306             getPreferenceScreen().addPreference(p);
    307         } else {
    308             getPreferenceScreen().removePreference(p);
    309         }
    310     }
    311 
    312     protected void toastAndFinish() {
    313         Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
    314         getActivity().finish();
    315     }
    316 
    317     private PackageInfo findPackageInfo(String pkg, int uid) {
    318         final String[] packages = mPm.getPackagesForUid(uid);
    319         if (packages != null && pkg != null) {
    320             final int N = packages.length;
    321             for (int i = 0; i < N; i++) {
    322                 final String p = packages[i];
    323                 if (pkg.equals(p)) {
    324                     try {
    325                         return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
    326                     } catch (NameNotFoundException e) {
    327                         Log.w(TAG, "Failed to load package " + pkg, e);
    328                     }
    329                 }
    330             }
    331         }
    332         return null;
    333     }
    334 }
    335