1 /* 2 * Copyright (C) 2014 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 import static android.app.admin.DevicePolicyResources.Strings.Settings.LOCK_SCREEN_HIDE_WORK_NOTIFICATION_CONTENT; 22 import static android.app.admin.DevicePolicyResources.Strings.Settings.LOCK_SCREEN_SHOW_WORK_NOTIFICATION_CONTENT; 23 import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS; 24 import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS; 25 26 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 27 28 import android.app.admin.DevicePolicyManager; 29 import android.app.settings.SettingsEnums; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.os.Bundle; 33 import android.os.UserManager; 34 import android.provider.Settings; 35 import android.view.LayoutInflater; 36 import android.view.View; 37 import android.view.ViewGroup; 38 import android.widget.RadioButton; 39 import android.widget.RadioGroup; 40 import android.widget.TextView; 41 42 import com.android.settings.R; 43 import com.android.settings.RestrictedRadioButton; 44 import com.android.settings.SettingsActivity; 45 import com.android.settings.SettingsPreferenceFragment; 46 import com.android.settings.SetupRedactionInterstitial; 47 import com.android.settings.SetupWizardUtils; 48 import com.android.settings.Utils; 49 import com.android.settingslib.RestrictedLockUtilsInternal; 50 51 import com.google.android.setupcompat.template.FooterBarMixin; 52 import com.google.android.setupcompat.template.FooterButton; 53 import com.google.android.setupcompat.util.WizardManagerHelper; 54 import com.google.android.setupdesign.GlifLayout; 55 import com.google.android.setupdesign.util.ThemeHelper; 56 57 public class RedactionInterstitial extends SettingsActivity { 58 59 @Override getIntent()60 public Intent getIntent() { 61 Intent modIntent = new Intent(super.getIntent()); 62 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, RedactionInterstitialFragment.class.getName()); 63 return modIntent; 64 } 65 66 @Override isValidFragment(String fragmentName)67 protected boolean isValidFragment(String fragmentName) { 68 return RedactionInterstitialFragment.class.getName().equals(fragmentName); 69 } 70 71 @Override onCreate(Bundle savedInstance)72 protected void onCreate(Bundle savedInstance) { 73 setTheme(SetupWizardUtils.getTheme(this, getIntent())); 74 ThemeHelper.trySetDynamicColor(this); 75 super.onCreate(savedInstance); 76 findViewById(R.id.content_parent).setFitsSystemWindows(false); 77 } 78 79 @Override isToolbarEnabled()80 protected boolean isToolbarEnabled() { 81 return false; 82 } 83 84 /** 85 * Create an intent for launching RedactionInterstitial. 86 * 87 * @return An intent to launch the activity is if is available, @null if the activity is not 88 * available to be launched. 89 */ createStartIntent(Context ctx, int userId)90 public static Intent createStartIntent(Context ctx, int userId) { 91 return new Intent(ctx, RedactionInterstitial.class) 92 .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, 93 UserManager.get(ctx).isManagedProfile(userId) 94 ? R.string.lock_screen_notifications_interstitial_title_profile 95 : R.string.lock_screen_notifications_interstitial_title) 96 .putExtra(Intent.EXTRA_USER_ID, userId); 97 } 98 99 public static class RedactionInterstitialFragment extends SettingsPreferenceFragment 100 implements RadioGroup.OnCheckedChangeListener { 101 102 private RadioGroup mRadioGroup; 103 private RestrictedRadioButton mShowAllButton; 104 private RestrictedRadioButton mRedactSensitiveButton; 105 private int mUserId; 106 107 @Override getMetricsCategory()108 public int getMetricsCategory() { 109 return SettingsEnums.NOTIFICATION_REDACTION; 110 } 111 112 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)113 public View onCreateView(LayoutInflater inflater, ViewGroup container, 114 Bundle savedInstanceState) { 115 return inflater.inflate(R.layout.redaction_interstitial, container, false); 116 } 117 118 @Override onViewCreated(View view, Bundle savedInstanceState)119 public void onViewCreated(View view, Bundle savedInstanceState) { 120 super.onViewCreated(view, savedInstanceState); 121 DevicePolicyManager devicePolicyManager = getSystemService(DevicePolicyManager.class); 122 mRadioGroup = (RadioGroup) view.findViewById(R.id.radio_group); 123 mShowAllButton = (RestrictedRadioButton) view.findViewById(R.id.show_all); 124 mRedactSensitiveButton = 125 (RestrictedRadioButton) view.findViewById(R.id.redact_sensitive); 126 127 mRadioGroup.setOnCheckedChangeListener(this); 128 mUserId = Utils.getUserIdFromBundle( 129 getContext(), getActivity().getIntent().getExtras()); 130 if (UserManager.get(getContext()).isManagedProfile(mUserId)) { 131 ((TextView) view.findViewById(R.id.sud_layout_description)) 132 .setText(R.string.lock_screen_notifications_interstitial_message_profile); 133 mShowAllButton.setText(devicePolicyManager 134 .getResources().getString(LOCK_SCREEN_SHOW_WORK_NOTIFICATION_CONTENT, 135 () -> getString( 136 R.string.lock_screen_notifications_summary_show_profile))); 137 mRedactSensitiveButton 138 .setText(devicePolicyManager.getResources().getString( 139 LOCK_SCREEN_HIDE_WORK_NOTIFICATION_CONTENT, 140 () -> getString( 141 R.string.lock_screen_notifications_summary_hide_profile))); 142 143 ((RadioButton) view.findViewById(R.id.hide_all)).setVisibility(View.GONE); 144 } 145 146 final GlifLayout layout = view.findViewById(R.id.setup_wizard_layout); 147 final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); 148 mixin.setPrimaryButton( 149 new FooterButton.Builder(getContext()) 150 .setText(R.string.app_notifications_dialog_done) 151 .setListener(this::onDoneButtonClicked) 152 .setButtonType(FooterButton.ButtonType.NEXT) 153 .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary) 154 .build() 155 ); 156 } 157 onDoneButtonClicked(View view)158 private void onDoneButtonClicked(View view) { 159 // If the activity starts by Setup Wizard, then skip disable component which avoids the 160 // framework force closing all activities on the same task when the system is busy. 161 if (!WizardManagerHelper.isAnySetupWizard(getIntent())) { 162 SetupRedactionInterstitial.setEnabled(getContext(), false); 163 } 164 final RedactionInterstitial activity = (RedactionInterstitial) getActivity(); 165 if (activity != null) { 166 activity.setResult(RESULT_CANCELED, null); 167 finish(); 168 } 169 } 170 171 @Override onResume()172 public void onResume() { 173 super.onResume(); 174 // Disable buttons according to policy. 175 176 checkNotificationFeaturesAndSetDisabled(mShowAllButton, 177 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | 178 KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS); 179 checkNotificationFeaturesAndSetDisabled(mRedactSensitiveButton, 180 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS); 181 loadFromSettings(); 182 } 183 checkNotificationFeaturesAndSetDisabled(RestrictedRadioButton button, int keyguardNotifications)184 private void checkNotificationFeaturesAndSetDisabled(RestrictedRadioButton button, 185 int keyguardNotifications) { 186 EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled( 187 getActivity(), keyguardNotifications, mUserId); 188 button.setDisabledByAdmin(admin); 189 } 190 loadFromSettings()191 private void loadFromSettings() { 192 final boolean showUnRedactedDefault = getContext().getResources().getBoolean( 193 R.bool.default_allow_sensitive_lockscreen_content); 194 final boolean managedProfile = UserManager.get(getContext()).isManagedProfile(mUserId); 195 // Hiding all notifications is device-wide setting, managed profiles can only set 196 // whether their notifications are show in full or redacted. 197 final boolean showNotifications = managedProfile || Settings.Secure.getIntForUser( 198 getContentResolver(), LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mUserId) != 0; 199 final boolean showUnredacted = Settings.Secure.getIntForUser( 200 getContentResolver(), LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 201 showUnRedactedDefault ? 1 : 0, mUserId) != 0; 202 203 int checkedButtonId = R.id.hide_all; 204 if (showNotifications) { 205 if (showUnredacted && !mShowAllButton.isDisabledByAdmin()) { 206 checkedButtonId = R.id.show_all; 207 } else if (!mRedactSensitiveButton.isDisabledByAdmin()) { 208 checkedButtonId = R.id.redact_sensitive; 209 } 210 } 211 212 mRadioGroup.check(checkedButtonId); 213 } 214 215 @Override onCheckedChanged(RadioGroup group, int checkedId)216 public void onCheckedChanged(RadioGroup group, int checkedId) { 217 final boolean show = (checkedId == R.id.show_all); 218 final boolean enabled = (checkedId != R.id.hide_all); 219 220 Settings.Secure.putIntForUser(getContentResolver(), 221 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0, mUserId); 222 Settings.Secure.putIntForUser(getContentResolver(), 223 LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0, mUserId); 224 225 } 226 } 227 } 228