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