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 static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
     20 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
     21 
     22 import android.app.admin.DevicePolicyManager;
     23 import android.content.ContentResolver;
     24 import android.content.Context;
     25 import android.database.ContentObserver;
     26 import android.net.Uri;
     27 import android.os.Handler;
     28 import android.os.UserHandle;
     29 import android.os.UserManager;
     30 import android.provider.Settings;
     31 import android.support.v7.preference.Preference;
     32 import android.support.v7.preference.PreferenceScreen;
     33 import android.text.TextUtils;
     34 import android.util.Log;
     35 
     36 import com.android.internal.widget.LockPatternUtils;
     37 import com.android.settings.R;
     38 import com.android.settings.RestrictedListPreference;
     39 import com.android.settings.Utils;
     40 import com.android.settings.core.PreferenceControllerMixin;
     41 import com.android.settings.overlay.FeatureFactory;
     42 import com.android.settingslib.RestrictedLockUtils;
     43 import com.android.settingslib.core.AbstractPreferenceController;
     44 import com.android.settingslib.core.lifecycle.LifecycleObserver;
     45 import com.android.settingslib.core.lifecycle.events.OnPause;
     46 import com.android.settingslib.core.lifecycle.events.OnResume;
     47 
     48 import java.util.ArrayList;
     49 
     50 public class LockScreenNotificationPreferenceController extends AbstractPreferenceController
     51         implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
     52         LifecycleObserver, OnResume, OnPause {
     53 
     54     private static final String TAG = "LockScreenNotifPref";
     55 
     56     private final String mSettingKey;
     57     private final String mWorkSettingCategoryKey;
     58     private final String mWorkSettingKey;
     59 
     60     private RestrictedListPreference mLockscreen;
     61     private RestrictedListPreference mLockscreenProfile;
     62 
     63     private final int mProfileUserId;
     64     private final boolean mSecure;
     65     private final boolean mSecureProfile;
     66 
     67     private SettingObserver mSettingObserver;
     68     private int mLockscreenSelectedValue;
     69     private int mLockscreenSelectedValueProfile;
     70 
     71     public LockScreenNotificationPreferenceController(Context context) {
     72         this(context, null, null, null);
     73     }
     74 
     75     public LockScreenNotificationPreferenceController(Context context,
     76             String settingKey, String workSettingCategoryKey, String workSettingKey) {
     77         super(context);
     78         mSettingKey = settingKey;
     79         mWorkSettingCategoryKey = workSettingCategoryKey;
     80         mWorkSettingKey = workSettingKey;
     81 
     82         mProfileUserId = Utils.getManagedProfileId(UserManager.get(context), UserHandle.myUserId());
     83         final LockPatternUtils utils = FeatureFactory.getFactory(context)
     84                 .getSecurityFeatureProvider()
     85                 .getLockPatternUtils(context);
     86         mSecure = utils.isSecure(UserHandle.myUserId());
     87         mSecureProfile = (mProfileUserId != UserHandle.USER_NULL) && utils.isSecure(mProfileUserId);
     88     }
     89 
     90     @Override
     91     public void displayPreference(PreferenceScreen screen) {
     92         super.displayPreference(screen);
     93         mLockscreen = (RestrictedListPreference) screen.findPreference(mSettingKey);
     94         if (mLockscreen == null) {
     95             Log.i(TAG, "Preference not found: " + mSettingKey);
     96             return;
     97         }
     98         if (mProfileUserId != UserHandle.USER_NULL) {
     99             mLockscreenProfile = (RestrictedListPreference) screen.findPreference(mWorkSettingKey);
    100             mLockscreenProfile.setRequiresActiveUnlockedProfile(true);
    101             mLockscreenProfile.setProfileUserId(mProfileUserId);
    102         } else {
    103             setVisible(screen, mWorkSettingKey, false /* visible */);
    104             setVisible(screen, mWorkSettingCategoryKey, false /* visible */);
    105         }
    106         mSettingObserver = new SettingObserver();
    107         initLockScreenNotificationPrefDisplay();
    108         initLockscreenNotificationPrefForProfile();
    109     }
    110 
    111     private void initLockScreenNotificationPrefDisplay() {
    112         ArrayList<CharSequence> entries = new ArrayList<>();
    113         ArrayList<CharSequence> values = new ArrayList<>();
    114 
    115         String summaryShowEntry =
    116                 mContext.getString(R.string.lock_screen_notifications_summary_show);
    117         String summaryShowEntryValue =
    118                 Integer.toString(R.string.lock_screen_notifications_summary_show);
    119         entries.add(summaryShowEntry);
    120         values.add(summaryShowEntryValue);
    121         setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
    122                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
    123 
    124         if (mSecure) {
    125             String summaryHideEntry =
    126                     mContext.getString(R.string.lock_screen_notifications_summary_hide);
    127             String summaryHideEntryValue =
    128                     Integer.toString(R.string.lock_screen_notifications_summary_hide);
    129             entries.add(summaryHideEntry);
    130             values.add(summaryHideEntryValue);
    131             setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
    132                     KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
    133         }
    134 
    135         entries.add(mContext.getString(R.string.lock_screen_notifications_summary_disable));
    136         values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable));
    137 
    138 
    139         mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()]));
    140         mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()]));
    141         updateLockscreenNotifications();
    142 
    143         if (mLockscreen.getEntries().length > 1) {
    144             mLockscreen.setOnPreferenceChangeListener(this);
    145         } else {
    146             // There is one or less option for the user, disable the drop down.
    147             mLockscreen.setEnabled(false);
    148         }
    149     }
    150 
    151     private void initLockscreenNotificationPrefForProfile() {
    152         if (mLockscreenProfile == null) {
    153             Log.i(TAG, "Preference not found: " + mWorkSettingKey);
    154             return;
    155         }
    156         ArrayList<CharSequence> entries = new ArrayList<>();
    157         ArrayList<CharSequence> values = new ArrayList<>();
    158 
    159         String summaryShowEntry = mContext.getString(
    160                 R.string.lock_screen_notifications_summary_show_profile);
    161         String summaryShowEntryValue = Integer.toString(
    162                 R.string.lock_screen_notifications_summary_show_profile);
    163         entries.add(summaryShowEntry);
    164         values.add(summaryShowEntryValue);
    165         setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
    166                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
    167 
    168         if (mSecureProfile) {
    169             String summaryHideEntry = mContext.getString(
    170                     R.string.lock_screen_notifications_summary_hide_profile);
    171             String summaryHideEntryValue = Integer.toString(
    172                     R.string.lock_screen_notifications_summary_hide_profile);
    173             entries.add(summaryHideEntry);
    174             values.add(summaryHideEntryValue);
    175             setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
    176                     KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
    177         }
    178 
    179         mLockscreenProfile.setEntries(entries.toArray(new CharSequence[entries.size()]));
    180         mLockscreenProfile.setEntryValues(values.toArray(new CharSequence[values.size()]));
    181         updateLockscreenNotificationsForProfile();
    182         if (mLockscreenProfile.getEntries().length > 1) {
    183             mLockscreenProfile.setOnPreferenceChangeListener(this);
    184         } else {
    185             // There is one or less option for the user, disable the drop down.
    186             mLockscreenProfile.setEnabled(false);
    187         }
    188     }
    189 
    190     @Override
    191     public String getPreferenceKey() {
    192         return null;
    193     }
    194 
    195     @Override
    196     public boolean isAvailable() {
    197         return false;
    198     }
    199 
    200     @Override
    201     public void onResume() {
    202         if (mSettingObserver != null) {
    203             mSettingObserver.register(mContext.getContentResolver(), true /* register */);
    204         }
    205     }
    206 
    207     @Override
    208     public void onPause() {
    209         if (mSettingObserver != null) {
    210             mSettingObserver.register(mContext.getContentResolver(), false /* register */);
    211         }
    212     }
    213 
    214     @Override
    215     public boolean onPreferenceChange(Preference preference, Object newValue) {
    216         final String key = preference.getKey();
    217         if (TextUtils.equals(mWorkSettingKey, key)) {
    218             final int val = Integer.parseInt((String) newValue);
    219             if (val == mLockscreenSelectedValueProfile) {
    220                 return false;
    221             }
    222             final boolean show = val == R.string.lock_screen_notifications_summary_show_profile;
    223             Settings.Secure.putIntForUser(mContext.getContentResolver(),
    224                     Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
    225                     show ? 1 : 0, mProfileUserId);
    226             mLockscreenSelectedValueProfile = val;
    227             return true;
    228         } else if (TextUtils.equals(mSettingKey, key)) {
    229             final int val = Integer.parseInt((String) newValue);
    230             if (val == mLockscreenSelectedValue) {
    231                 return false;
    232             }
    233             final boolean enabled = val != R.string.lock_screen_notifications_summary_disable;
    234             final boolean show = val == R.string.lock_screen_notifications_summary_show;
    235             Settings.Secure.putInt(mContext.getContentResolver(),
    236                     Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
    237             Settings.Secure.putInt(mContext.getContentResolver(),
    238                     Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
    239             mLockscreenSelectedValue = val;
    240             return true;
    241         }
    242         return false;
    243     }
    244 
    245     private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
    246             CharSequence entryValue, int keyguardNotificationFeatures) {
    247         RestrictedLockUtils.EnforcedAdmin admin =
    248                 RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
    249                         mContext, keyguardNotificationFeatures, UserHandle.myUserId());
    250         if (admin != null && mLockscreen != null) {
    251             RestrictedListPreference.RestrictedItem item =
    252                     new RestrictedListPreference.RestrictedItem(entry, entryValue, admin);
    253             mLockscreen.addRestrictedItem(item);
    254         }
    255         if (mProfileUserId != UserHandle.USER_NULL) {
    256             RestrictedLockUtils.EnforcedAdmin profileAdmin =
    257                     RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
    258                             mContext, keyguardNotificationFeatures, mProfileUserId);
    259             if (profileAdmin != null && mLockscreenProfile != null) {
    260                 RestrictedListPreference.RestrictedItem item =
    261                         new RestrictedListPreference.RestrictedItem(
    262                                 entry, entryValue, profileAdmin);
    263                 mLockscreenProfile.addRestrictedItem(item);
    264             }
    265         }
    266     }
    267 
    268     public static int getSummaryResource(Context context) {
    269         final boolean enabled = getLockscreenNotificationsEnabled(context);
    270         final boolean secure = FeatureFactory.getFactory(context)
    271                 .getSecurityFeatureProvider()
    272                 .getLockPatternUtils(context)
    273                 .isSecure(UserHandle.myUserId());
    274         final boolean allowPrivate = !secure
    275             || getAllowPrivateNotifications(context, UserHandle.myUserId());
    276         return !enabled ? R.string.lock_screen_notifications_summary_disable :
    277             allowPrivate ? R.string.lock_screen_notifications_summary_show :
    278                 R.string.lock_screen_notifications_summary_hide;
    279     }
    280 
    281     private void updateLockscreenNotifications() {
    282         if (mLockscreen == null) {
    283             return;
    284         }
    285         mLockscreenSelectedValue = getSummaryResource(mContext);
    286         mLockscreen.setSummary("%s");
    287         mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue));
    288     }
    289 
    290     private boolean adminAllowsUnredactedNotifications(int userId) {
    291         final int dpmFlags = mContext.getSystemService(DevicePolicyManager.class)
    292                 .getKeyguardDisabledFeatures(null/* admin */, userId);
    293         return (dpmFlags & KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
    294     }
    295 
    296     private void updateLockscreenNotificationsForProfile() {
    297         if (mProfileUserId == UserHandle.USER_NULL) {
    298             return;
    299         }
    300         if (mLockscreenProfile == null) {
    301             return;
    302         }
    303         final boolean allowPrivate = adminAllowsUnredactedNotifications(mProfileUserId) &&
    304                 (!mSecureProfile || getAllowPrivateNotifications(mContext, mProfileUserId));
    305         mLockscreenProfile.setSummary("%s");
    306         mLockscreenSelectedValueProfile = allowPrivate
    307                         ? R.string.lock_screen_notifications_summary_show_profile
    308                         : R.string.lock_screen_notifications_summary_hide_profile;
    309         mLockscreenProfile.setValue(Integer.toString(mLockscreenSelectedValueProfile));
    310     }
    311 
    312     private static boolean getLockscreenNotificationsEnabled(Context context) {
    313         return Settings.Secure.getInt(context.getContentResolver(),
    314                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
    315     }
    316 
    317     private static boolean getAllowPrivateNotifications(Context context, int userId) {
    318         return Settings.Secure.getIntForUser(context.getContentResolver(),
    319                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userId) != 0;
    320     }
    321 
    322     class SettingObserver extends ContentObserver {
    323 
    324         private final Uri LOCK_SCREEN_PRIVATE_URI =
    325                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
    326         private final Uri LOCK_SCREEN_SHOW_URI =
    327                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
    328 
    329         public SettingObserver() {
    330             super(new Handler());
    331         }
    332 
    333         public void register(ContentResolver cr, boolean register) {
    334             if (register) {
    335                 cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this);
    336                 cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this);
    337             } else {
    338                 cr.unregisterContentObserver(this);
    339             }
    340         }
    341 
    342         @Override
    343         public void onChange(boolean selfChange, Uri uri) {
    344             super.onChange(selfChange, uri);
    345             if (LOCK_SCREEN_PRIVATE_URI.equals(uri) || LOCK_SCREEN_SHOW_URI.equals(uri)) {
    346                 updateLockscreenNotifications();
    347                 if (mProfileUserId != UserHandle.USER_NULL) {
    348                     updateLockscreenNotificationsForProfile();
    349                 }
    350             }
    351         }
    352     }
    353 }
    354