blob: e11bccd7cc047b1ee0778b6919e77b85286eb7db [file] [log] [blame]
Jason parksec5a45e2011-01-18 15:28:36 -06001/*
2 * Copyright (C) 2008 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
17package com.android.settings;
18
19import android.app.Activity;
Jason parks39f1e042011-01-20 23:29:28 -060020import android.app.AlertDialog;
Andy Stadler3da38a02011-01-21 13:38:45 -080021import android.app.admin.DevicePolicyManager;
Jason parks39f1e042011-01-20 23:29:28 -060022import android.content.BroadcastReceiver;
23import android.content.Context;
Jason parksec5a45e2011-01-18 15:28:36 -060024import android.content.Intent;
Jason parks39f1e042011-01-20 23:29:28 -060025import android.content.IntentFilter;
Jason parksec5a45e2011-01-18 15:28:36 -060026import android.content.res.Resources;
Jason parks39f1e042011-01-20 23:29:28 -060027import android.os.BatteryManager;
Jason parksec5a45e2011-01-18 15:28:36 -060028import android.os.Bundle;
Adrian Roos54375882015-04-16 17:11:22 -070029import android.os.UserHandle;
Paul Lawrenced71c31e2014-04-03 09:18:45 -070030import android.os.storage.StorageManager;
Jason Monk39b46742015-09-10 15:52:51 -040031import android.support.v7.preference.Preference;
Andy Stadler95ef5572011-02-01 16:22:41 -080032import android.text.TextUtils;
Jason parksec5a45e2011-01-18 15:28:36 -060033import android.view.LayoutInflater;
34import android.view.View;
35import android.view.ViewGroup;
36import android.widget.Button;
Jason Monk39b46742015-09-10 15:52:51 -040037
Tamas Berghammer265d3c22016-06-22 15:34:45 +010038import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Fan Zhang2d0b3442016-12-05 17:02:33 -080039import com.android.settings.core.InstrumentedPreferenceFragment;
Maurice Lam2eb170c2017-04-28 16:18:47 -070040import com.android.settings.password.ChooseLockSettingsHelper;
41import com.android.settings.password.ConfirmLockPattern;
Jason parksec5a45e2011-01-18 15:28:36 -060042
Fan Zhang2d0b3442016-12-05 17:02:33 -080043public class CryptKeeperSettings extends InstrumentedPreferenceFragment {
Jason parksec5a45e2011-01-18 15:28:36 -060044 private static final String TAG = "CryptKeeper";
Andrei Kapishnikov146fc112015-04-09 11:08:16 -040045 private static final String TYPE = "type";
46 private static final String PASSWORD = "password";
Jason parksec5a45e2011-01-18 15:28:36 -060047
48 private static final int KEYGUARD_REQUEST = 55;
49
Andy Stadler8dbcb882011-01-30 16:25:38 -080050 // Minimum battery charge level (in percent) to launch encryption. If the battery charge is
51 // lower than this, encryption should not be activated.
52 private static final int MIN_BATTERY_LEVEL = 80;
53
Jason parksec5a45e2011-01-18 15:28:36 -060054 private View mContentView;
55 private Button mInitiateButton;
Andy Stadler8dbcb882011-01-30 16:25:38 -080056 private View mPowerWarning;
57 private View mBatteryWarning;
Jason parks39f1e042011-01-20 23:29:28 -060058 private IntentFilter mIntentFilter;
59
60 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
61 @Override
62 public void onReceive(Context context, Intent intent) {
63 String action = intent.getAction();
64 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
Vikram Aggarwal8d028a82012-10-29 11:00:01 -070065 final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
66 final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
67 final int invalidCharger = intent.getIntExtra(
68 BatteryManager.EXTRA_INVALID_CHARGER, 0);
Jason parks4548cdf2011-06-24 14:05:12 -050069
Vikram Aggarwal8d028a82012-10-29 11:00:01 -070070 final boolean levelOk = level >= MIN_BATTERY_LEVEL;
71 final boolean pluggedOk =
72 ((plugged & BatteryManager.BATTERY_PLUGGED_ANY) != 0) &&
Jason parks4548cdf2011-06-24 14:05:12 -050073 invalidCharger == 0;
74
Andy Stadler8dbcb882011-01-30 16:25:38 -080075 // Update UI elements based on power/battery status
76 mInitiateButton.setEnabled(levelOk && pluggedOk);
77 mPowerWarning.setVisibility(pluggedOk ? View.GONE : View.VISIBLE );
78 mBatteryWarning.setVisibility(levelOk ? View.GONE : View.VISIBLE);
Jason parks39f1e042011-01-20 23:29:28 -060079 }
80 }
81 };
82
83 /**
84 * If the user clicks to begin the reset sequence, we next require a
85 * keyguard confirmation if the user has currently enabled one. If there
86 * is no keyguard available, we prompt the user to set a password.
87 */
88 private Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
Paul Crowley01fbd9f2014-11-04 22:51:36 +000089 @Override
Jason parks39f1e042011-01-20 23:29:28 -060090 public void onClick(View v) {
91 if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
Andy Stadler17141202011-01-31 10:15:53 -080092 // TODO replace (or follow) this dialog with an explicit launch into password UI
Jason parks39f1e042011-01-20 23:29:28 -060093 new AlertDialog.Builder(getActivity())
Andy Stadler17141202011-01-31 10:15:53 -080094 .setTitle(R.string.crypt_keeper_dialog_need_password_title)
Andy Stadler17141202011-01-31 10:15:53 -080095 .setMessage(R.string.crypt_keeper_dialog_need_password_message)
Jason parks39f1e042011-01-20 23:29:28 -060096 .setPositiveButton(android.R.string.ok, null)
97 .create()
98 .show();
99 }
100 }
101 };
102
Jason parks39f1e042011-01-20 23:29:28 -0600103 @Override
104 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
105 mContentView = inflater.inflate(R.layout.crypt_keeper_settings, null);
106
107 mIntentFilter = new IntentFilter();
108 mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
109
110 mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_encrypt);
111 mInitiateButton.setOnClickListener(mInitiateListener);
112 mInitiateButton.setEnabled(false);
113
Andy Stadler8dbcb882011-01-30 16:25:38 -0800114 mPowerWarning = mContentView.findViewById(R.id.warning_unplugged);
115 mBatteryWarning = mContentView.findViewById(R.id.warning_low_charge);
116
Jason parks39f1e042011-01-20 23:29:28 -0600117 return mContentView;
118 }
119
120 @Override
Fan Zhang65076132016-08-08 10:25:13 -0700121 public int getMetricsCategory() {
Chris Wren9d1bfd12016-01-26 18:04:01 -0500122 return MetricsEvent.CRYPT_KEEPER;
Chris Wren8a963ba2015-03-20 10:29:14 -0400123 }
124
125 @Override
Jason parks39f1e042011-01-20 23:29:28 -0600126 public void onResume() {
127 super.onResume();
128 getActivity().registerReceiver(mIntentReceiver, mIntentFilter);
129 }
130
131 @Override
132 public void onPause() {
133 super.onPause();
134 getActivity().unregisterReceiver(mIntentReceiver);
135 }
Jason parksec5a45e2011-01-18 15:28:36 -0600136
137 /**
Andy Stadler3da38a02011-01-21 13:38:45 -0800138 * If encryption is already started, and this launched via a "start encryption" intent,
139 * then exit immediately - it's already up and running, so there's no point in "starting" it.
140 */
141 @Override
142 public void onActivityCreated(Bundle savedInstanceState) {
143 super.onActivityCreated(savedInstanceState);
144 Activity activity = getActivity();
145 Intent intent = activity.getIntent();
146 if (DevicePolicyManager.ACTION_START_ENCRYPTION.equals(intent.getAction())) {
147 DevicePolicyManager dpm = (DevicePolicyManager)
148 activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
149 if (dpm != null) {
150 int status = dpm.getStorageEncryptionStatus();
151 if (status != DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE) {
152 // There is nothing to do here, so simply finish() (which returns to caller)
153 activity.finish();
154 }
155 }
156 }
157 }
158
159 /**
Jason parksec5a45e2011-01-18 15:28:36 -0600160 * Keyguard validation is run using the standard {@link ConfirmLockPattern}
161 * component as a subactivity
162 * @param request the request code to be returned once confirmation finishes
163 * @return true if confirmation launched
164 */
165 private boolean runKeyguardConfirmation(int request) {
166 Resources res = getActivity().getResources();
Paul Lawrenced71c31e2014-04-03 09:18:45 -0700167 ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
168
Adrian Roos54375882015-04-16 17:11:22 -0700169 if (helper.utils().getKeyguardStoredPasswordQuality(UserHandle.myUserId())
Paul Lawrenced71c31e2014-04-03 09:18:45 -0700170 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
171 showFinalConfirmation(StorageManager.CRYPT_TYPE_DEFAULT, "");
172 return true;
173 }
174
Jorim Jaggi8a09b612015-04-06 17:47:18 -0700175 return helper.launchConfirmationActivity(request,
176 res.getText(R.string.crypt_keeper_encrypt_title), true);
Jason parksec5a45e2011-01-18 15:28:36 -0600177 }
178
179 @Override
180 public void onActivityResult(int requestCode, int resultCode, Intent data) {
181 super.onActivityResult(requestCode, resultCode, data);
182
183 if (requestCode != KEYGUARD_REQUEST) {
184 return;
185 }
Jason parks39f1e042011-01-20 23:29:28 -0600186
Jason parksec5a45e2011-01-18 15:28:36 -0600187 // If the user entered a valid keyguard trace, present the final
188 // confirmation prompt; otherwise, go back to the initial state.
Andy Stadler95ef5572011-02-01 16:22:41 -0800189 if (resultCode == Activity.RESULT_OK && data != null) {
Paul Lawrenced71c31e2014-04-03 09:18:45 -0700190 int type = data.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, -1);
Brian Carlstrom0e88f4d2011-06-02 16:47:15 -0700191 String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
Andy Stadler95ef5572011-02-01 16:22:41 -0800192 if (!TextUtils.isEmpty(password)) {
Paul Lawrenced71c31e2014-04-03 09:18:45 -0700193 showFinalConfirmation(type, password);
Andy Stadler95ef5572011-02-01 16:22:41 -0800194 }
Jason parksec5a45e2011-01-18 15:28:36 -0600195 }
196 }
197
Paul Lawrenced71c31e2014-04-03 09:18:45 -0700198 private void showFinalConfirmation(int type, String password) {
Jason Monk39b46742015-09-10 15:52:51 -0400199 Preference preference = new Preference(getPreferenceManager().getContext());
Jason parksf8217302011-01-26 13:11:42 -0600200 preference.setFragment(CryptKeeperConfirm.class.getName());
Jason parksec5a45e2011-01-18 15:28:36 -0600201 preference.setTitle(R.string.crypt_keeper_confirm_title);
Andrei Kapishnikov146fc112015-04-09 11:08:16 -0400202 addEncryptionInfoToPreference(preference, type, password);
Fabrice Di Meglio263bcc82014-01-17 19:17:58 -0800203 ((SettingsActivity) getActivity()).onPreferenceStartFragment(null, preference);
Jason parksec5a45e2011-01-18 15:28:36 -0600204 }
Andrei Kapishnikov146fc112015-04-09 11:08:16 -0400205
206 private void addEncryptionInfoToPreference(Preference preference, int type, String password) {
207 Activity activity = getActivity();
208 DevicePolicyManager dpm = (DevicePolicyManager)
209 activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
210 if (dpm.getDoNotAskCredentialsOnBoot()) {
211 preference.getExtras().putInt(TYPE, StorageManager.CRYPT_TYPE_DEFAULT);
212 preference.getExtras().putString(PASSWORD, "");
213 } else {
214 preference.getExtras().putInt(TYPE, type);
215 preference.getExtras().putString(PASSWORD, password);
216 }
217 }
Jason parksec5a45e2011-01-18 15:28:36 -0600218}