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