• 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.AlertDialog;
21 import android.app.Dialog;
22 import android.app.admin.DevicePolicyManager;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.res.Resources;
27 import android.os.Bundle;
28 import android.support.v7.preference.Preference;
29 import android.support.v7.widget.RecyclerView;
30 import android.util.Log;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.view.accessibility.AccessibilityManager;
35 import android.widget.LinearLayout;
36 import android.widget.TextView;
37 
38 import com.android.internal.logging.MetricsProto.MetricsEvent;
39 import com.android.settings.utils.SettingsDividerItemDecoration;
40 import com.android.setupwizardlib.GlifPreferenceLayout;
41 
42 import java.util.List;
43 
44 public class EncryptionInterstitial extends SettingsActivity {
45     private static final String TAG = EncryptionInterstitial.class.getSimpleName();
46 
47     protected static final String EXTRA_PASSWORD_QUALITY = "extra_password_quality";
48     protected static final String EXTRA_UNLOCK_METHOD_INTENT = "extra_unlock_method_intent";
49     public static final String EXTRA_REQUIRE_PASSWORD = "extra_require_password";
50     private static final int CHOOSE_LOCK_REQUEST = 100;
51 
52     @Override
getIntent()53     public Intent getIntent() {
54         Intent modIntent = new Intent(super.getIntent());
55         modIntent.putExtra(EXTRA_SHOW_FRAGMENT, EncryptionInterstitialFragment.class.getName());
56         return modIntent;
57     }
58 
59     @Override
isValidFragment(String fragmentName)60     protected boolean isValidFragment(String fragmentName) {
61         return EncryptionInterstitialFragment.class.getName().equals(fragmentName);
62     }
63 
createStartIntent(Context ctx, int quality, boolean requirePasswordDefault, Intent unlockMethodIntent)64     public static Intent createStartIntent(Context ctx, int quality,
65             boolean requirePasswordDefault, Intent unlockMethodIntent) {
66         return new Intent(ctx, EncryptionInterstitial.class)
67                 .putExtra(EXTRA_PASSWORD_QUALITY, quality)
68                 .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.encryption_interstitial_header)
69                 .putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault)
70                 .putExtra(EXTRA_UNLOCK_METHOD_INTENT, unlockMethodIntent);
71     }
72 
73     @Override
onCreate(Bundle savedInstance)74     protected void onCreate(Bundle savedInstance) {
75         super.onCreate(savedInstance);
76         LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
77         layout.setFitsSystemWindows(false);
78     }
79 
80     public static class EncryptionInterstitialFragment extends SettingsPreferenceFragment
81             implements DialogInterface.OnClickListener {
82 
83         private static final int ACCESSIBILITY_WARNING_DIALOG = 1;
84         private static final String KEY_ENCRYPT_REQUIRE_PASSWORD = "encrypt_require_password";
85         private static final String KEY_ENCRYPT_DONT_REQUIRE_PASSWORD =
86                 "encrypt_dont_require_password";
87 
88         private Preference mRequirePasswordToDecrypt;
89         private Preference mDontRequirePasswordToDecrypt;
90         private boolean mPasswordRequired;
91         private Intent mUnlockMethodIntent;
92         private int mRequestedPasswordQuality;
93 
94         @Override
getMetricsCategory()95         protected int getMetricsCategory() {
96             return MetricsEvent.ENCRYPTION;
97         }
98 
99         @Override
onCreate(Bundle savedInstanceState)100         public void onCreate(Bundle savedInstanceState) {
101             super.onCreate(savedInstanceState);
102 
103             addPreferencesFromResource(R.xml.security_settings_encryption_interstitial);
104 
105             // Used for testing purposes
106             findPreference(KEY_ENCRYPT_DONT_REQUIRE_PASSWORD)
107                     .setViewId(R.id.encrypt_dont_require_password);
108 
109             mRequirePasswordToDecrypt = findPreference(KEY_ENCRYPT_REQUIRE_PASSWORD);
110             mDontRequirePasswordToDecrypt = findPreference(KEY_ENCRYPT_DONT_REQUIRE_PASSWORD);
111             boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
112                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
113             Intent intent = getActivity().getIntent();
114             mRequestedPasswordQuality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
115             mUnlockMethodIntent = intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
116             final int msgId;
117             final int enableId;
118             final int disableId;
119             switch (mRequestedPasswordQuality) {
120                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
121                     msgId = forFingerprint ?
122                             R.string.encryption_interstitial_message_pattern_for_fingerprint :
123                             R.string.encryption_interstitial_message_pattern;
124                     enableId = R.string.encrypt_require_pattern;
125                     disableId = R.string.encrypt_dont_require_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                             R.string.encryption_interstitial_message_pin;
132                     enableId = R.string.encrypt_require_pin;
133                     disableId = R.string.encrypt_dont_require_pin;
134                     break;
135                 default:
136                     msgId = forFingerprint ?
137                             R.string.encryption_interstitial_message_password_for_fingerprint :
138                             R.string.encryption_interstitial_message_password;
139                     enableId = R.string.encrypt_require_password;
140                     disableId = R.string.encrypt_dont_require_password;
141                     break;
142             }
143             TextView message = (TextView) LayoutInflater.from(getActivity()).inflate(
144                     R.layout.encryption_interstitial_header, null, false);
145             message.setText(msgId);
146             setHeaderView(message);
147 
148             mRequirePasswordToDecrypt.setTitle(enableId);
149 
150             mDontRequirePasswordToDecrypt.setTitle(disableId);
151 
152             setRequirePasswordState(getActivity().getIntent().getBooleanExtra(
153                     EXTRA_REQUIRE_PASSWORD, true));
154         }
155 
156         @Override
onViewCreated(View view, Bundle savedInstanceState)157         public void onViewCreated(View view, Bundle savedInstanceState) {
158             super.onViewCreated(view, savedInstanceState);
159             GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
160             layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext()));
161 
162             layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
163             layout.setHeaderText(getActivity().getTitle());
164 
165             // Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
166             // PreferenceFragment.
167             setDivider(null);
168         }
169 
170         @Override
onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)171         public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
172                 Bundle savedInstanceState) {
173             GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
174             return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
175         }
176 
startLockIntent()177         protected void startLockIntent() {
178             if (mUnlockMethodIntent != null) {
179                 mUnlockMethodIntent.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
180                 startActivityForResult(mUnlockMethodIntent, CHOOSE_LOCK_REQUEST);
181             } else {
182                 Log.wtf(TAG, "no unlock intent to start");
183                 finish();
184             }
185         }
186 
187         @Override
onActivityResult(int requestCode, int resultCode, Intent data)188         public void onActivityResult(int requestCode, int resultCode, Intent data) {
189             super.onActivityResult(requestCode, resultCode, data);
190             if (requestCode == CHOOSE_LOCK_REQUEST && resultCode != RESULT_CANCELED) {
191                 getActivity().setResult(resultCode, data);
192                 finish();
193             }
194         }
195 
196         @Override
onPreferenceTreeClick(Preference preference)197         public boolean onPreferenceTreeClick(Preference preference) {
198             final String key = preference.getKey();
199             if (key.equals(KEY_ENCRYPT_REQUIRE_PASSWORD)) {
200                 final boolean accEn = AccessibilityManager.getInstance(getActivity()).isEnabled();
201                 if (accEn && !mPasswordRequired) {
202                     setRequirePasswordState(false); // clear the UI state
203                     showDialog(ACCESSIBILITY_WARNING_DIALOG);
204                 } else {
205                     setRequirePasswordState(true);
206                     startLockIntent();
207                 }
208             } else {
209                 setRequirePasswordState(false);
210                 startLockIntent();
211             }
212             return true;
213         }
214 
215         @Override
onCreateDialog(int dialogId)216         public Dialog onCreateDialog(int dialogId) {
217             switch(dialogId) {
218                 case ACCESSIBILITY_WARNING_DIALOG: {
219                     final int titleId;
220                     final int messageId;
221                     switch (mRequestedPasswordQuality) {
222                         case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
223                             titleId = R.string.encrypt_talkback_dialog_require_pattern;
224                             messageId = R.string.encrypt_talkback_dialog_message_pattern;
225                             break;
226                         case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
227                         case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
228                             titleId = R.string.encrypt_talkback_dialog_require_pin;
229                             messageId = R.string.encrypt_talkback_dialog_message_pin;
230                             break;
231                         default:
232                             titleId = R.string.encrypt_talkback_dialog_require_password;
233                             messageId = R.string.encrypt_talkback_dialog_message_password;
234                             break;
235                     }
236 
237 
238                     List<AccessibilityServiceInfo> list =
239                             AccessibilityManager.getInstance(getActivity())
240                             .getEnabledAccessibilityServiceList(
241                                     AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
242                     final CharSequence exampleAccessibility;
243                     if (list.isEmpty()) {
244                         // This should never happen.  But we shouldn't crash
245                         exampleAccessibility = "";
246                     } else {
247                         exampleAccessibility = list.get(0).getResolveInfo()
248                                 .loadLabel(getPackageManager());
249                     }
250                     return new AlertDialog.Builder(getActivity())
251                         .setTitle(titleId)
252                         .setMessage(getString(messageId, exampleAccessibility))
253                         .setCancelable(true)
254                         .setPositiveButton(android.R.string.ok, this)
255                         .setNegativeButton(android.R.string.cancel, this)
256                         .create();
257                 }
258                 default: throw new IllegalArgumentException();
259             }
260         }
261 
setRequirePasswordState(boolean required)262         private void setRequirePasswordState(boolean required) {
263             mPasswordRequired = required;
264         }
265 
266         @Override
onClick(DialogInterface dialog, int which)267         public void onClick(DialogInterface dialog, int which) {
268             if (which == DialogInterface.BUTTON_POSITIVE) {
269                 setRequirePasswordState(true);
270                 startLockIntent();
271             } else if (which == DialogInterface.BUTTON_NEGATIVE) {
272                 setRequirePasswordState(false);
273             }
274         }
275     }
276 }
277