Home | History | Annotate | Download | only in settings
      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
     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
     60     protected boolean isValidFragment(String fragmentName) {
     61         return EncryptionInterstitialFragment.class.getName().equals(fragmentName);
     62     }
     63 
     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
     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
     95         protected int getMetricsCategory() {
     96             return MetricsEvent.ENCRYPTION;
     97         }
     98 
     99         @Override
    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
    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
    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 
    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
    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
    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
    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 
    262         private void setRequirePasswordState(boolean required) {
    263             mPasswordRequired = required;
    264         }
    265 
    266         @Override
    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