Support default, pattern, pin and password encryption types

Use plumbing provided by dependant change to bring up correct dialog
at boot time.

Needs matching framework changes from
 https://googleplex-android-review.googlesource.com/#/c/412885/

Bug: 8769627
Change-Id: Ib04a2875e051a7cccca035fadb25978dfec22491
This commit is contained in:
Paul Lawrence
2014-02-04 10:22:19 -08:00
parent c94122a199
commit b05f39d186
6 changed files with 241 additions and 44 deletions

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include layout="@layout/crypt_keeper_status" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_marginStart="8dip"
android:layout_marginEnd="8dip"
android:orientation="horizontal"
>
<include layout="@layout/crypt_keeper_pattern_field" />
</LinearLayout>
<!-- Emergency call button.
Text and icon are set by CryptKeeper.updateEmergencyCallButtonState() -->
<Button android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="16dip"
style="@*android:style/Widget.Button.Transparent"
android:textSize="14sp"
android:drawablePadding="6dip"
/>
</LinearLayout>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<!-- Contents of the password entry field for CryptKeeper. Comes with an IME
switcher, if necessary. Assumed to be in a horizontal LinearLayout. -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView android:id="@+id/switch_ime_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_lockscreen_ime"
android:clickable="true"
android:contentDescription="@string/crypt_keeper_switch_input_method"
android:padding="8dip"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground"
android:visibility="gone"
/>
</merge>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include layout="@layout/crypt_keeper_status" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_marginStart="8dip"
android:layout_marginEnd="8dip"
android:orientation="horizontal"
>
<include layout="@layout/crypt_keeper_pin_field" />
</LinearLayout>
<!-- Emergency call button.
Text and icon are set by CryptKeeper.updateEmergencyCallButtonState() -->
<Button android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="16dip"
style="@*android:style/Widget.Button.Transparent"
android:textSize="14sp"
android:drawablePadding="6dip"
/>
</LinearLayout>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<!-- Contents of the password entry field for CryptKeeper. Comes with an IME
switcher, if necessary. Assumed to be in a horizontal LinearLayout. -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<EditText android:id="@+id/passwordEntry"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"
android:singleLine="true"
android:inputType="numberPassword"
android:imeOptions="flagForceAscii|actionDone"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<ImageView android:id="@+id/switch_ime_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_lockscreen_ime"
android:clickable="true"
android:contentDescription="@string/crypt_keeper_switch_input_method"
android:padding="8dip"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground"
android:visibility="gone"
/>
</merge>

View File

@@ -226,20 +226,7 @@ public class ChooseLockGeneric extends SettingsActivity {
private int upgradeQuality(int quality, MutableBoolean allowBiometric) { private int upgradeQuality(int quality, MutableBoolean allowBiometric) {
quality = upgradeQualityForDPM(quality); quality = upgradeQualityForDPM(quality);
quality = upgradeQualityForKeyStore(quality); quality = upgradeQualityForKeyStore(quality);
int encryptionQuality = upgradeQualityForEncryption(quality); return quality;
if (encryptionQuality > quality) {
//The first case checks whether biometric is allowed, prior to the user making
//their selection from the list
if (allowBiometric != null) {
allowBiometric.value = quality <=
DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
} else if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
//When the user has selected biometric we shouldn't change that due to
//encryption
return quality;
}
}
return encryptionQuality;
} }
private int upgradeQualityForDPM(int quality) { private int upgradeQualityForDPM(int quality) {
@@ -251,27 +238,6 @@ public class ChooseLockGeneric extends SettingsActivity {
return quality; return quality;
} }
/**
* Mix in "encryption minimums" to any given quality value. This prevents users
* from downgrading the pattern/pin/password to a level below the minimums.
*
* ASSUMPTION: Setting quality is sufficient (e.g. minimum lengths will be set
* appropriately.)
*/
private int upgradeQualityForEncryption(int quality) {
// Don't upgrade quality for secondary users. Encryption requirements don't apply.
if (!Process.myUserHandle().equals(UserHandle.OWNER)) return quality;
int encryptionStatus = mDPM.getStorageEncryptionStatus();
boolean encrypted = (encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE)
|| (encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING);
if (encrypted) {
if (quality < CryptKeeperSettings.MIN_PASSWORD_QUALITY) {
quality = CryptKeeperSettings.MIN_PASSWORD_QUALITY;
}
}
return quality;
}
private int upgradeQualityForKeyStore(int quality) { private int upgradeQualityForKeyStore(int quality) {
if (!mKeyStore.isEmpty()) { if (!mKeyStore.isEmpty()) {
if (quality < CredentialStorage.MIN_PASSWORD_QUALITY) { if (quality < CredentialStorage.MIN_PASSWORD_QUALITY) {

View File

@@ -34,6 +34,7 @@ import android.os.ServiceManager;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.storage.IMountService; import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.provider.Settings; import android.provider.Settings;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.Editable; import android.text.Editable;
@@ -60,6 +61,9 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneConstants;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell;
import java.util.List; import java.util.List;
@@ -113,6 +117,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
private int mCooldown; private int mCooldown;
PowerManager.WakeLock mWakeLock; PowerManager.WakeLock mWakeLock;
private EditText mPasswordEntry; private EditText mPasswordEntry;
private LockPatternView mLockPatternView;
/** Number of calls to {@link #notifyUser()} to ignore before notifying. */ /** Number of calls to {@link #notifyUser()} to ignore before notifying. */
private int mNotificationCountdown = 0; private int mNotificationCountdown = 0;
@@ -175,7 +180,9 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
final TextView status = (TextView) findViewById(R.id.status); final TextView status = (TextView) findViewById(R.id.status);
status.setText(R.string.try_again); status.setText(R.string.try_again);
// Reenable the password entry // Reenable the password entry
mPasswordEntry.setEnabled(true); if (mPasswordEntry != null) {
mPasswordEntry.setEnabled(true);
}
} }
} }
} }
@@ -354,7 +361,21 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
setContentView(R.layout.crypt_keeper_progress); setContentView(R.layout.crypt_keeper_progress);
encryptionProgressInit(); encryptionProgressInit();
} else if (mValidationComplete || isDebugView(FORCE_VIEW_PASSWORD)) { } else if (mValidationComplete || isDebugView(FORCE_VIEW_PASSWORD)) {
setContentView(R.layout.crypt_keeper_password_entry); final IMountService service = getMountService();
int type = StorageManager.CRYPT_TYPE_PASSWORD;
try {
type = service.getPasswordType();
} catch (Exception e) {
Log.e(TAG, "Error while getting type - showing default dialog" + e);
}
if(type == StorageManager.CRYPT_TYPE_PIN) {
setContentView(R.layout.crypt_keeper_pin_entry);
} else if (type == StorageManager.CRYPT_TYPE_PATTERN) {
setContentView(R.layout.crypt_keeper_pattern_entry);
} else {
setContentView(R.layout.crypt_keeper_password_entry);
}
passwordEntryInit(); passwordEntryInit();
} else if (!mValidationRequested) { } else if (!mValidationRequested) {
// We're supposed to be encrypted, but no validation has been done. // We're supposed to be encrypted, but no validation has been done.
@@ -503,14 +524,44 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
} }
} }
private void passwordEntryInit() { protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
new LockPatternView.OnPatternListener() {
@Override
public void onPatternStart() {
}
@Override
public void onPatternCleared() {
}
@Override
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
new DecryptTask().execute(LockPatternUtils.patternToString(pattern));
}
@Override
public void onPatternCellAdded(List<Cell> pattern) {
}
};
private void passwordEntryInit() {
// Password/pin case
mPasswordEntry = (EditText) findViewById(R.id.passwordEntry); mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
mPasswordEntry.setOnEditorActionListener(this); if (mPasswordEntry != null){
mPasswordEntry.requestFocus(); mPasswordEntry.setOnEditorActionListener(this);
// Become quiet when the user interacts with the Edit text screen. mPasswordEntry.requestFocus();
mPasswordEntry.setOnKeyListener(this); // Become quiet when the user interacts with the Edit text screen.
mPasswordEntry.setOnTouchListener(this); mPasswordEntry.setOnKeyListener(this);
mPasswordEntry.addTextChangedListener(this); mPasswordEntry.setOnTouchListener(this);
mPasswordEntry.addTextChangedListener(this);
}
// Pattern case
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
if (mLockPatternView != null) {
mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
}
// Disable the Emergency call button if the device has no voice telephone capability // Disable the Emergency call button if the device has no voice telephone capability
final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);