Enforce Keyguard policy in Notification Settings

- Applied getKeyguardDisabledFeatures for notification settings and
    notification setup page (after settings a screenlock)
- If a notification settings is disabled, the next least secure setting
    will be chosen
- Although KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS can be set be
    profile, it will not be reflected in both settings page. This is
    because it does not affect the owner (user 0), as mentioned in
    DevicePolicyManagerService.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER
- Skip RedactionInterstitial if there is <= 1 options for the user
- Tested with both Setup wizard and settings case, both pattern and
    password, as well as toggling the policy on and off

Bug: 19307118
Bug: 17099898

Change-Id: If640d5576caa0163e9942569f7b4643a30bbfe0a
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 576cee5..64aaaca 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -559,7 +559,10 @@
             getActivity().finish();
             mDone = true;
             if (!wasSecureBefore) {
-                startActivity(getRedactionInterstitialIntent(getActivity()));
+                Intent intent = getRedactionInterstitialIntent(getActivity());
+                if (intent != null) {
+                    startActivity(intent);
+                }
             }
         }
 
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index baee599..481cf0f 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -641,7 +641,10 @@
                 startVerifyPattern(utils, wasSecureBefore);
             } else {
                 if (!wasSecureBefore) {
-                    startActivity(getRedactionInterstitialIntent(getActivity()));
+                    Intent intent = getRedactionInterstitialIntent(getActivity());
+                    if (intent != null) {
+                        startActivity(intent);
+                    }
                 }
                 getActivity().setResult(RESULT_FINISHED);
                 doFinish();
@@ -670,7 +673,10 @@
                             mPendingLockCheck = null;
 
                             if (!wasSecureBefore) {
-                                startActivity(getRedactionInterstitialIntent(getActivity()));
+                                Intent intent = getRedactionInterstitialIntent(getActivity());
+                                if (intent != null) {
+                                    startActivity(intent);
+                                }
                             }
 
                             Intent intent = new Intent();
diff --git a/src/com/android/settings/DropDownPreference.java b/src/com/android/settings/DropDownPreference.java
index ce4bb2f..0f5b06a 100644
--- a/src/com/android/settings/DropDownPreference.java
+++ b/src/com/android/settings/DropDownPreference.java
@@ -126,6 +126,10 @@
         mValues.add(value);
     }
 
+    public int getItemCount() {
+        return mAdapter.getCount();
+    }
+
     public void clearItems(){
         mAdapter.clear();
         mValues.clear();
diff --git a/src/com/android/settings/SetupChooseLockPassword.java b/src/com/android/settings/SetupChooseLockPassword.java
index 080e470..9837562 100644
--- a/src/com/android/settings/SetupChooseLockPassword.java
+++ b/src/com/android/settings/SetupChooseLockPassword.java
@@ -110,7 +110,9 @@
         @Override
         protected Intent getRedactionInterstitialIntent(Context context) {
             Intent intent = SetupRedactionInterstitial.createStartIntent(context);
-            SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
+            if (intent != null) {
+                SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
+            }
             return intent;
         }
 
diff --git a/src/com/android/settings/SetupChooseLockPattern.java b/src/com/android/settings/SetupChooseLockPattern.java
index 2ea8d4a..bdf7af8 100644
--- a/src/com/android/settings/SetupChooseLockPattern.java
+++ b/src/com/android/settings/SetupChooseLockPattern.java
@@ -103,7 +103,9 @@
         @Override
         protected Intent getRedactionInterstitialIntent(Context context) {
             Intent intent = SetupRedactionInterstitial.createStartIntent(context);
-            SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
+            if (intent != null) {
+                SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
+            }
             return intent;
         }
 
diff --git a/src/com/android/settings/SetupRedactionInterstitial.java b/src/com/android/settings/SetupRedactionInterstitial.java
index 590788b..4939aea 100644
--- a/src/com/android/settings/SetupRedactionInterstitial.java
+++ b/src/com/android/settings/SetupRedactionInterstitial.java
@@ -40,9 +40,11 @@
 
     public static Intent createStartIntent(Context ctx) {
         Intent startIntent = RedactionInterstitial.createStartIntent(ctx);
-        startIntent.setClass(ctx, SetupRedactionInterstitial.class);
-        startIntent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)
-                .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
+        if (startIntent != null) {
+            startIntent.setClass(ctx, SetupRedactionInterstitial.class);
+            startIntent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)
+                    .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
+        }
         return startIntent;
     }
 
diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java
index 98f2517..2a56c90 100644
--- a/src/com/android/settings/notification/NotificationSettings.java
+++ b/src/com/android/settings/notification/NotificationSettings.java
@@ -17,6 +17,7 @@
 package com.android.settings.notification;
 
 import android.app.NotificationManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -427,32 +428,56 @@
             return;
         }
 
-        mLockscreen.addItem(R.string.lock_screen_notifications_summary_show,
-                R.string.lock_screen_notifications_summary_show);
-        if (mSecure) {
+        boolean isSecureNotificationsDisabled = isSecureNotificationsDisabled();
+        boolean isUnredactedNotificationsDisabled = isUnredactedNotificationsDisabled();
+        if (!isSecureNotificationsDisabled && !isUnredactedNotificationsDisabled) {
+            mLockscreen.addItem(R.string.lock_screen_notifications_summary_show,
+                    R.string.lock_screen_notifications_summary_show);
+        }
+        if (mSecure && !isSecureNotificationsDisabled) {
             mLockscreen.addItem(R.string.lock_screen_notifications_summary_hide,
                     R.string.lock_screen_notifications_summary_hide);
         }
         mLockscreen.addItem(R.string.lock_screen_notifications_summary_disable,
                 R.string.lock_screen_notifications_summary_disable);
         updateLockscreenNotifications();
-        mLockscreen.setCallback(new DropDownPreference.Callback() {
-            @Override
-            public boolean onItemSelected(int pos, Object value) {
-                final int val = (Integer) value;
-                if (val == mLockscreenSelectedValue) {
+        if (mLockscreen.getItemCount() > 1) {
+            mLockscreen.setCallback(new DropDownPreference.Callback() {
+                @Override
+                public boolean onItemSelected(int pos, Object value) {
+                    final int val = (Integer) value;
+                    if (val == mLockscreenSelectedValue) {
+                        return true;
+                    }
+                    final boolean enabled =
+                            val != R.string.lock_screen_notifications_summary_disable;
+                    final boolean show = val == R.string.lock_screen_notifications_summary_show;
+                    Settings.Secure.putInt(getContentResolver(),
+                            Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
+                    Settings.Secure.putInt(getContentResolver(),
+                            Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
+                    mLockscreenSelectedValue = val;
                     return true;
                 }
-                final boolean enabled = val != R.string.lock_screen_notifications_summary_disable;
-                final boolean show = val == R.string.lock_screen_notifications_summary_show;
-                Settings.Secure.putInt(getContentResolver(),
-                        Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
-                Settings.Secure.putInt(getContentResolver(),
-                        Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
-                mLockscreenSelectedValue = val;
-                return true;
-            }
-        });
+            });
+        } else {
+            // There is one or less option for the user, disable the drop down.
+            mLockscreen.setEnabled(false);
+        }
+    }
+
+    private boolean isSecureNotificationsDisabled() {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
+                & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0;
+    }
+
+    private boolean isUnredactedNotificationsDisabled() {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
+                & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0;
     }
 
     private void updateLockscreenNotifications() {
diff --git a/src/com/android/settings/notification/RedactionInterstitial.java b/src/com/android/settings/notification/RedactionInterstitial.java
index 16ee3b5..a0d1219 100644
--- a/src/com/android/settings/notification/RedactionInterstitial.java
+++ b/src/com/android/settings/notification/RedactionInterstitial.java
@@ -21,6 +21,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
@@ -29,6 +30,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.RadioButton;
+import android.widget.RadioGroup;
 
 public class RedactionInterstitial extends SettingsActivity {
 
@@ -44,20 +46,44 @@
         return RedactionInterstitialFragment.class.getName().equals(fragmentName);
     }
 
+    /**
+     * Create an intent for launching RedactionInterstitial.
+     * @return An intent to launch the activity is if is available, @null if the activity is not
+     * available to be launched.
+     */
     public static Intent createStartIntent(Context ctx) {
-        return new Intent(ctx, RedactionInterstitial.class)
-                .putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, true)
-                .putExtra(EXTRA_PREFS_SET_BACK_TEXT, (String) null)
-                .putExtra(EXTRA_PREFS_SET_NEXT_TEXT, ctx.getString(
-                        R.string.app_notifications_dialog_done));
+        if (isSecureNotificationsDisabled(ctx)) {
+            // If there is no choices for the user, we should not start the activity.
+            return null;
+        } else {
+            return new Intent(ctx, RedactionInterstitial.class)
+                    .putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, true)
+                    .putExtra(EXTRA_PREFS_SET_BACK_TEXT, (String) null)
+                    .putExtra(EXTRA_PREFS_SET_NEXT_TEXT, ctx.getString(
+                            R.string.app_notifications_dialog_done));
+        }
+    }
+
+    private static boolean isSecureNotificationsDisabled(Context context) {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
+                & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0;
+    }
+
+    private static boolean isUnredactedNotificationsDisabled(Context context) {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
+                & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0;
     }
 
     public static class RedactionInterstitialFragment extends SettingsPreferenceFragment
-            implements View.OnClickListener {
+            implements RadioGroup.OnCheckedChangeListener {
 
+        private RadioGroup mRadioGroup;
         private RadioButton mShowAllButton;
         private RadioButton mRedactSensitiveButton;
-        private RadioButton mHideAllButton;
 
         @Override
         protected int getMetricsCategory() {
@@ -73,13 +99,19 @@
         @Override
         public void onViewCreated(View view, Bundle savedInstanceState) {
             super.onViewCreated(view, savedInstanceState);
+            mRadioGroup = (RadioGroup) view.findViewById(R.id.radio_group);
             mShowAllButton = (RadioButton) view.findViewById(R.id.show_all);
             mRedactSensitiveButton = (RadioButton) view.findViewById(R.id.redact_sensitive);
-            mHideAllButton = (RadioButton) view.findViewById(R.id.hide_all);
 
-            mShowAllButton.setOnClickListener(this);
-            mRedactSensitiveButton.setOnClickListener(this);
-            mHideAllButton.setOnClickListener(this);
+            mRadioGroup.setOnCheckedChangeListener(this);
+
+            // Disable buttons according to policy.
+            if (isSecureNotificationsDisabled(getActivity())) {
+                mShowAllButton.setEnabled(false);
+                mRedactSensitiveButton.setEnabled(false);
+            } else if (isUnredactedNotificationsDisabled(getActivity())) {
+                mShowAllButton.setEnabled(false);
+            }
         }
 
         @Override
@@ -93,15 +125,23 @@
                         Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
             final boolean show = Settings.Secure.getInt(getContentResolver(),
                         Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1) != 0;
-            mShowAllButton.setChecked(enabled && show);
-            mRedactSensitiveButton.setChecked(enabled && !show);
-            mHideAllButton.setChecked(!enabled);
+
+            int checkedButtonId = R.id.hide_all;
+            if (enabled) {
+                if (show && mShowAllButton.isEnabled()) {
+                    checkedButtonId = R.id.show_all;
+                } else if (mRedactSensitiveButton.isEnabled()) {
+                    checkedButtonId = R.id.redact_sensitive;
+                }
+            }
+
+            mRadioGroup.check(checkedButtonId);
         }
 
         @Override
-        public void onClick(View v) {
-            final boolean show = (v == mShowAllButton);
-            final boolean enabled = (v != mHideAllButton);
+        public void onCheckedChanged(RadioGroup group, int checkedId) {
+            final boolean show = (checkedId == R.id.show_all);
+            final boolean enabled = (checkedId != R.id.hide_all);
 
             Settings.Secure.putInt(getContentResolver(),
                     Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);