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