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