• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import android.accessibilityservice.AccessibilityServiceInfo;
20 import android.app.Activity;
21 import android.app.Dialog;
22 import android.app.admin.DevicePolicyManager;
23 import android.app.settings.SettingsEnums;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.res.Resources;
28 import android.os.Bundle;
29 import android.util.Log;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.view.accessibility.AccessibilityManager;
34 import android.widget.TextView;
35 
36 import androidx.appcompat.app.AlertDialog;
37 
38 import com.android.settings.core.InstrumentedFragment;
39 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
40 import com.android.settings.password.ChooseLockSettingsHelper;
41 
42 import com.google.android.setupcompat.template.FooterBarMixin;
43 import com.google.android.setupcompat.template.FooterButton;
44 import com.google.android.setupdesign.GlifLayout;
45 
46 import java.util.List;
47 
48 public class EncryptionInterstitial extends SettingsActivity {
49     private static final String TAG = EncryptionInterstitial.class.getSimpleName();
50 
51     protected static final String EXTRA_PASSWORD_QUALITY = "extra_password_quality";
52     protected static final String EXTRA_UNLOCK_METHOD_INTENT = "extra_unlock_method_intent";
53     public static final String EXTRA_REQUIRE_PASSWORD = "extra_require_password";
54     private static final int CHOOSE_LOCK_REQUEST = 100;
55 
56     @Override
getIntent()57     public Intent getIntent() {
58         Intent modIntent = new Intent(super.getIntent());
59         modIntent.putExtra(EXTRA_SHOW_FRAGMENT, EncryptionInterstitialFragment.class.getName());
60         return modIntent;
61     }
62 
63     @Override
onApplyThemeResource(Resources.Theme theme, int resid, boolean first)64     protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
65         resid = SetupWizardUtils.getTheme(getIntent());
66         super.onApplyThemeResource(theme, resid, first);
67     }
68 
69     @Override
isValidFragment(String fragmentName)70     protected boolean isValidFragment(String fragmentName) {
71         return EncryptionInterstitialFragment.class.getName().equals(fragmentName);
72     }
73 
createStartIntent(Context ctx, int quality, boolean requirePasswordDefault, Intent unlockMethodIntent)74     public static Intent createStartIntent(Context ctx, int quality,
75             boolean requirePasswordDefault, Intent unlockMethodIntent) {
76         return new Intent(ctx, EncryptionInterstitial.class)
77                 .putExtra(EXTRA_PASSWORD_QUALITY, quality)
78                 .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.encryption_interstitial_header)
79                 .putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault)
80                 .putExtra(EXTRA_UNLOCK_METHOD_INTENT, unlockMethodIntent);
81     }
82 
83     @Override
onCreate(Bundle savedInstance)84     protected void onCreate(Bundle savedInstance) {
85         super.onCreate(savedInstance);
86         findViewById(R.id.content_parent).setFitsSystemWindows(false);
87     }
88 
89     public static class EncryptionInterstitialFragment extends InstrumentedFragment {
90 
91         private boolean mPasswordRequired;
92         private Intent mUnlockMethodIntent;
93         private int mRequestedPasswordQuality;
94 
95         @Override
getMetricsCategory()96         public int getMetricsCategory() {
97             return SettingsEnums.ENCRYPTION;
98         }
99 
100         @Override
onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)101         public View onCreateView(
102                 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
103             return inflater.inflate(R.layout.encryption_interstitial, container, false);
104         }
105 
106         @Override
onViewCreated(View view, Bundle savedInstanceState)107         public void onViewCreated(View view, Bundle savedInstanceState) {
108             super.onViewCreated(view, savedInstanceState);
109 
110             final boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
111                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
112             final boolean forFace = getActivity().getIntent()
113                     .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
114             Intent intent = getActivity().getIntent();
115             mRequestedPasswordQuality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
116             mUnlockMethodIntent = intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
117             final int msgId;
118             switch (mRequestedPasswordQuality) {
119                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
120                     msgId = forFingerprint ?
121                             R.string.encryption_interstitial_message_pattern_for_fingerprint :
122                             forFace ?
123                             R.string.encryption_interstitial_message_pattern_for_face :
124                             R.string.encryption_interstitial_message_pattern;
125                     break;
126                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
127                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
128                     msgId = forFingerprint ?
129                             R.string.encryption_interstitial_message_pin_for_fingerprint :
130                             forFace ?
131                             R.string.encryption_interstitial_message_pin_for_face :
132                             R.string.encryption_interstitial_message_pin;
133                     break;
134                 default:
135                     msgId = forFingerprint ?
136                             R.string.encryption_interstitial_message_password_for_fingerprint :
137                             forFace ?
138                             R.string.encryption_interstitial_message_password_for_face :
139                             R.string.encryption_interstitial_message_password;
140                     break;
141             }
142             TextView message = (TextView) getActivity().findViewById(R.id.sud_layout_description);
143             message.setText(msgId);
144 
145             setRequirePasswordState(getActivity().getIntent().getBooleanExtra(
146                     EXTRA_REQUIRE_PASSWORD, true));
147 
148             GlifLayout layout = (GlifLayout) view;
149             layout.setHeaderText(getActivity().getTitle());
150 
151             final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
152             mixin.setSecondaryButton(
153                     new FooterButton.Builder(getContext())
154                             .setText(R.string.encryption_interstitial_no)
155                             .setListener(this::onNoButtonClicked)
156                             .setButtonType(FooterButton.ButtonType.SKIP)
157                             .setTheme(R.style.SudGlifButton_Secondary)
158                             .build()
159             );
160 
161             mixin.setPrimaryButton(
162                     new FooterButton.Builder(getContext())
163                             .setText(R.string.encryption_interstitial_yes)
164                             .setListener(this::onYesButtonClicked)
165                             .setButtonType(FooterButton.ButtonType.NEXT)
166                             .setTheme(R.style.SudGlifButton_Primary)
167                             .build()
168             );
169         }
170 
startLockIntent()171         protected void startLockIntent() {
172             if (mUnlockMethodIntent != null) {
173                 mUnlockMethodIntent.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
174                 startActivityForResult(mUnlockMethodIntent, CHOOSE_LOCK_REQUEST);
175             } else {
176                 Log.wtf(TAG, "no unlock intent to start");
177                 finish();
178             }
179         }
180 
181         @Override
onActivityResult(int requestCode, int resultCode, Intent data)182         public void onActivityResult(int requestCode, int resultCode, Intent data) {
183             super.onActivityResult(requestCode, resultCode, data);
184             if (requestCode == CHOOSE_LOCK_REQUEST && resultCode != RESULT_CANCELED) {
185                 getActivity().setResult(resultCode, data);
186                 finish();
187             }
188         }
189 
onYesButtonClicked(View view)190         private void onYesButtonClicked(View view) {
191             final boolean accEn = AccessibilityManager.getInstance(getActivity()).isEnabled();
192             if (accEn && !mPasswordRequired) {
193                 setRequirePasswordState(false); // clear the UI state
194                 AccessibilityWarningDialogFragment.newInstance(mRequestedPasswordQuality)
195                         .show(
196                                 getChildFragmentManager(),
197                                 AccessibilityWarningDialogFragment.TAG);
198             } else {
199                 setRequirePasswordState(true);
200                 startLockIntent();
201             }
202         }
203 
onNoButtonClicked(View view)204         private void onNoButtonClicked(View view) {
205             setRequirePasswordState(false);
206             startLockIntent();
207         }
208 
setRequirePasswordState(boolean required)209         private void setRequirePasswordState(boolean required) {
210             mPasswordRequired = required;
211         }
212 
finish()213         public void finish() {
214             Activity activity = getActivity();
215             if (activity == null) return;
216             if (getFragmentManager().getBackStackEntryCount() > 0) {
217                 getFragmentManager().popBackStack();
218             } else {
219                 activity.finish();
220             }
221         }
222     }
223 
224     public static class AccessibilityWarningDialogFragment extends InstrumentedDialogFragment
225             implements DialogInterface.OnClickListener {
226 
227         public static final String TAG = "AccessibilityWarningDialog";
228 
newInstance(int passwordQuality)229         public static AccessibilityWarningDialogFragment newInstance(int passwordQuality) {
230             AccessibilityWarningDialogFragment fragment = new AccessibilityWarningDialogFragment();
231             Bundle args = new Bundle(1);
232             args.putInt(EXTRA_PASSWORD_QUALITY, passwordQuality);
233             fragment.setArguments(args);
234             return fragment;
235         }
236 
237         @Override
onCreateDialog(Bundle savedInstanceState)238         public Dialog onCreateDialog(Bundle savedInstanceState) {
239             final int titleId;
240             final int messageId;
241             switch (getArguments().getInt(EXTRA_PASSWORD_QUALITY)) {
242                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
243                     titleId = R.string.encrypt_talkback_dialog_require_pattern;
244                     messageId = R.string.encrypt_talkback_dialog_message_pattern;
245                     break;
246                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
247                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
248                     titleId = R.string.encrypt_talkback_dialog_require_pin;
249                     messageId = R.string.encrypt_talkback_dialog_message_pin;
250                     break;
251                 default:
252                     titleId = R.string.encrypt_talkback_dialog_require_password;
253                     messageId = R.string.encrypt_talkback_dialog_message_password;
254                     break;
255             }
256 
257 
258             final Activity activity = getActivity();
259             List<AccessibilityServiceInfo> list =
260                     AccessibilityManager.getInstance(activity)
261                             .getEnabledAccessibilityServiceList(
262                                     AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
263             final CharSequence exampleAccessibility;
264             if (list.isEmpty()) {
265                 // This should never happen.  But we shouldn't crash
266                 exampleAccessibility = "";
267             } else {
268                 exampleAccessibility = list.get(0).getResolveInfo()
269                         .loadLabel(activity.getPackageManager());
270             }
271             return new AlertDialog.Builder(activity)
272                     .setTitle(titleId)
273                     .setMessage(getString(messageId, exampleAccessibility))
274                     .setCancelable(true)
275                     .setPositiveButton(android.R.string.ok, this)
276                     .setNegativeButton(android.R.string.cancel, this)
277                     .create();
278         }
279 
280         @Override
getMetricsCategory()281         public int getMetricsCategory() {
282             return SettingsEnums.DIALOG_ENCRYPTION_INTERSTITIAL_ACCESSIBILITY;
283         }
284 
285         @Override
onClick(DialogInterface dialog, int which)286         public void onClick(DialogInterface dialog, int which) {
287             EncryptionInterstitialFragment fragment =
288                     (EncryptionInterstitialFragment) getParentFragment();
289             if (fragment != null) {
290                 if (which == DialogInterface.BUTTON_POSITIVE) {
291                     fragment.setRequirePasswordState(true);
292                     fragment.startLockIntent();
293                 } else if (which == DialogInterface.BUTTON_NEGATIVE) {
294                     fragment.setRequirePasswordState(false);
295                 }
296             }
297         }
298     }
299 }
300