Use buttons for EncryptionInterstitial

Bug: 30742121
Test: Run EncryptionInterstitialTest via `am instrument`
Change-Id: I04d304da4153ebc7f8809ce9c640bccc5e1f5685
This commit is contained in:
Maurice Lam
2017-02-23 14:43:48 -08:00
parent 304d7f4455
commit 9be96e06bb
8 changed files with 159 additions and 209 deletions

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 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.
-->
<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_lock">
<LinearLayout
style="@style/SuwContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<TextView
android:id="@+id/encryption_message"
style="@style/SuwDescription.Glif"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal">
<Button
android:id="@+id/encrypt_dont_require_password"
style="@style/SetupWizardButton.Negative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/encryption_interstitial_no" />
<Space
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<Button
android:id="@+id/encrypt_require_password"
style="@style/SetupWizardButton.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/encryption_interstitial_yes" />
</LinearLayout>
</LinearLayout>
</com.android.setupwizardlib.GlifLayout>

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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.
-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/encryption_interstitial_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="56dp"
android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="@dimen/suw_description_glif_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="?android:attr/textAppearanceListItem" />

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="56dp"
android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="@dimen/suw_description_glif_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="?android:attr/textAppearanceListItem" />

View File

@@ -6830,39 +6830,30 @@
<!-- Message shown on encryption interstitial to ask the user whether or not they want to use a PIN to encrypt the device. [CHAR LIMIT=NONE] -->
<string name="encryption_interstitial_message_pin">
You can further protect this device by requiring your PIN before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.
\n\nThis helps protect data on lost or stolen devices.
\n\nThis helps protect data on lost or stolen devices. Require PIN to start your device?
</string>
<!-- Message shown on encryption interstitial to ask the user whether or not they want to use a pattern to encrypt the device. [CHAR LIMIT=NONE] -->
<string name="encryption_interstitial_message_pattern">
You can further protect this device by requiring your pattern before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.
\n\nThis helps protect data on lost or stolen devices.
\n\nThis helps protect data on lost or stolen devices. Require pattern to start your device?
</string>
<!-- Message shown on encryption interstitial to ask the user whether or not they want to use a password to encrypt the device. [CHAR LIMIT=NONE] -->
<string name="encryption_interstitial_message_password">
You can further protect this device by requiring your password before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.
\n\nThis helps protect data on lost or stolen devices.
\n\nThis helps protect data on lost or stolen devices. Require password to start your device?
</string>
<!-- Message shown on encryption interstitial to ask the user whether or not they want to use a PIN to encrypt the device while setting up fingerprint unlock. [CHAR LIMIT=NONE] -->
<string name="encryption_interstitial_message_pin_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your PIN before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices.</string>
<string name="encryption_interstitial_message_pin_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your PIN before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require PIN to start your device?</string>
<!-- Message shown on encryption interstitial to ask the user whether or not they want to use a pattern to encrypt the device while setting up fingerprint unlock. [CHAR LIMIT=NONE] -->
<string name="encryption_interstitial_message_pattern_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your pattern before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices.</string>
<string name="encryption_interstitial_message_pattern_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your pattern before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require pattern to start your device?</string>
<!-- Message shown on encryption interstitial to ask the user whether or not they want to use a password to encrypt the device while setting up fingerprint unlock. [CHAR LIMIT=NONE] -->
<string name="encryption_interstitial_message_password_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your password before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices.</string>
<string name="encryption_interstitial_message_password_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your password before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require password to start your device></string>
<!-- Radio button text that require a PIN to start device [CHAR LIMIT=NONE] -->
<string name="encrypt_require_pin">Require PIN to start device</string>
<!-- Radio button text that require a pattern to start device [CHAR LIMIT=NONE] -->
<string name="encrypt_require_pattern">Require pattern to start device</string>
<!-- Radio button text that require a password to start device [CHAR LIMIT=NONE] -->
<string name="encrypt_require_password">Require password to start device</string>
<!-- Radio button text that doesn't require a PIN to decrypt [CHAR LIMIT=NONE] -->
<string name="encrypt_dont_require_pin">No thanks</string>
<!-- Radio button text that doesn't require a pattern to decrypt [CHAR LIMIT=NONE] -->
<string name="encrypt_dont_require_pattern">No thanks</string>
<!-- Radio button text that doesn't require a password to decrypt [CHAR LIMIT=NONE] -->
<string name="encrypt_dont_require_password">No thanks</string>
<!-- Button label to say yes to the question of whether to require PIN/password/pattern to start your device. [CHAR LIMIT=20] -->
<string name="encryption_interstitial_yes">Yes</string>
<!-- Button label to say no to the question of whether to require PIN/password/pattern to start your device. [CHAR LIMIT=20] -->
<string name="encryption_interstitial_no">No</string>
<!-- Title for encryption dialog that disables TalkBack. [CHAR_LIMIT=25] -->
<string name="encrypt_talkback_dialog_require_pin">Require PIN?</string>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/lock_settings_picker_title"
android:key="lock_settings_picker">
<com.android.settings.MultiLinePreference
android:icon="@drawable/ic_lock_list_icon"
android:key="encrypt_require_password"
android:persistent="false"/>
<Preference
android:icon="@drawable/ic_skip"
android:key="encrypt_dont_require_password"
android:persistent="false"/>
</PreferenceScreen>

View File

@@ -23,21 +23,18 @@ import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.utils.SettingsDividerItemDecoration;
import com.android.setupwizardlib.GlifPreferenceLayout;
import com.android.setupwizardlib.GlifLayout;
import java.util.List;
@@ -78,15 +75,12 @@ public class EncryptionInterstitial extends SettingsActivity {
}
public static class EncryptionInterstitialFragment extends SettingsPreferenceFragment
implements DialogInterface.OnClickListener {
implements View.OnClickListener, DialogInterface.OnClickListener {
private static final int ACCESSIBILITY_WARNING_DIALOG = 1;
private static final String KEY_ENCRYPT_REQUIRE_PASSWORD = "encrypt_require_password";
private static final String KEY_ENCRYPT_DONT_REQUIRE_PASSWORD =
"encrypt_dont_require_password";
private Preference mRequirePasswordToDecrypt;
private Preference mDontRequirePasswordToDecrypt;
private View mRequirePasswordToDecrypt;
private View mDontRequirePasswordToDecrypt;
private boolean mPasswordRequired;
private Intent mUnlockMethodIntent;
private int mRequestedPasswordQuality;
@@ -97,81 +91,52 @@ public class EncryptionInterstitial extends SettingsActivity {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.encryption_interstitial, container, false);
}
addPreferencesFromResource(R.xml.security_settings_encryption_interstitial);
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Used for testing purposes
findPreference(KEY_ENCRYPT_DONT_REQUIRE_PASSWORD)
.setViewId(R.id.encrypt_dont_require_password);
mRequirePasswordToDecrypt = findPreference(KEY_ENCRYPT_REQUIRE_PASSWORD);
mDontRequirePasswordToDecrypt = findPreference(KEY_ENCRYPT_DONT_REQUIRE_PASSWORD);
mRequirePasswordToDecrypt = view.findViewById(R.id.encrypt_require_password);
mDontRequirePasswordToDecrypt = view.findViewById(R.id.encrypt_dont_require_password);
boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
Intent intent = getActivity().getIntent();
mRequestedPasswordQuality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
mUnlockMethodIntent = intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
final int msgId;
final int enableId;
final int disableId;
switch (mRequestedPasswordQuality) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
msgId = forFingerprint ?
R.string.encryption_interstitial_message_pattern_for_fingerprint :
R.string.encryption_interstitial_message_pattern;
enableId = R.string.encrypt_require_pattern;
disableId = R.string.encrypt_dont_require_pattern;
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
msgId = forFingerprint ?
R.string.encryption_interstitial_message_pin_for_fingerprint :
R.string.encryption_interstitial_message_pin;
enableId = R.string.encrypt_require_pin;
disableId = R.string.encrypt_dont_require_pin;
break;
default:
msgId = forFingerprint ?
R.string.encryption_interstitial_message_password_for_fingerprint :
R.string.encryption_interstitial_message_password;
enableId = R.string.encrypt_require_password;
disableId = R.string.encrypt_dont_require_password;
break;
}
TextView message = (TextView) LayoutInflater.from(getActivity()).inflate(
R.layout.encryption_interstitial_header, null, false);
TextView message = (TextView) getActivity().findViewById(R.id.encryption_message);
message.setText(msgId);
setHeaderView(message);
mRequirePasswordToDecrypt.setTitle(enableId);
mDontRequirePasswordToDecrypt.setTitle(disableId);
mRequirePasswordToDecrypt.setOnClickListener(this);
mDontRequirePasswordToDecrypt.setOnClickListener(this);
setRequirePasswordState(getActivity().getIntent().getBooleanExtra(
EXTRA_REQUIRE_PASSWORD, true));
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext()));
layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
GlifLayout layout = (GlifLayout) view;
layout.setHeaderText(getActivity().getTitle());
// Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
// PreferenceFragment.
setDivider(null);
}
@Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
protected void startLockIntent() {
@@ -194,12 +159,8 @@ public class EncryptionInterstitial extends SettingsActivity {
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
final String key = preference.getKey();
if (key == null) {
return super.onPreferenceTreeClick(preference);
}
if (key.equals(KEY_ENCRYPT_REQUIRE_PASSWORD)) {
public void onClick(View view) {
if (view == mRequirePasswordToDecrypt) {
final boolean accEn = AccessibilityManager.getInstance(getActivity()).isEnabled();
if (accEn && !mPasswordRequired) {
setRequirePasswordState(false); // clear the UI state
@@ -212,7 +173,6 @@ public class EncryptionInterstitial extends SettingsActivity {
setRequirePasswordState(false);
startLockIntent();
}
return true;
}
@Override

View File

@@ -20,15 +20,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.android.settings.utils.SettingsDividerItemDecoration;
import com.android.setupwizardlib.GlifPreferenceLayout;
/**
* Setup Wizard's version of EncryptionInterstitial screen. It inherits the logic and basic
* structure from EncryptionInterstitial class, and should remain similar to that behaviorally. This
@@ -75,29 +68,5 @@ public class SetupEncryptionInterstitial extends EncryptionInterstitial {
}
public static class SetupEncryptionInterstitialFragment extends EncryptionInterstitialFragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
layout.setDividerItemDecoration(new SettingsDividerItemDecoration(getContext()));
layout.setDividerInset(getContext().getResources().getDimensionPixelSize(
R.dimen.suw_items_glif_icon_divider_inset));
layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
layout.setHeaderText(R.string.encryption_interstitial_header);
// Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
// PreferenceFragment.
setDivider(null);
}
@Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
}
}

View File

@@ -16,38 +16,89 @@
package com.android.settings;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.app.Instrumentation.ActivityResult;
import android.content.Context;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
@RunWith(AndroidJUnit4.class)
@SmallTest
@MediumTest
public class EncryptionInterstitialTest {
private Instrumentation mInstrumentation;
private Context mContext;
private TestActivityMonitor mActivityMonitor;
@Before
public void setUp() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getTargetContext();
mActivityMonitor = new TestActivityMonitor();
mInstrumentation.addMonitor(mActivityMonitor);
}
@After
public void tearDown() {
mInstrumentation.removeMonitor(mActivityMonitor);
}
@Test
public void clickHeader_shouldNotCrash() {
public void clickYes_shouldRequirePassword() {
mInstrumentation.startActivitySync(
new Intent().setClassName(mContext, EncryptionInterstitial.class.getName()));
onView(withId(R.id.encryption_interstitial_header));
// Nothing should happen
new Intent(mContext, EncryptionInterstitial.class)
.putExtra("extra_unlock_method_intent", new Intent("test.unlock.intent")));
onView(withId(R.id.encrypt_require_password)).perform(click());
mActivityMonitor.waitForActivityWithTimeout(1000);
assertEquals(1, mActivityMonitor.getHits());
assertTrue(mActivityMonitor.mMatchedIntent.getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false));
}
@Test
public void clickNo_shouldNotRequirePassword() {
mInstrumentation.startActivitySync(
new Intent(mContext, EncryptionInterstitial.class)
.putExtra("extra_unlock_method_intent", new Intent("test.unlock.intent")));
onView(withId(R.id.encrypt_dont_require_password)).perform(click());
mActivityMonitor.waitForActivityWithTimeout(1000);
assertEquals(1, mActivityMonitor.getHits());
assertFalse(mActivityMonitor.mMatchedIntent.getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true));
}
private static class TestActivityMonitor extends ActivityMonitor {
Intent mMatchedIntent = null;
@Override
public ActivityResult onMatchIntent(Intent intent) {
if ("test.unlock.intent".equals(intent.getAction())) {
mMatchedIntent = intent;
return new ActivityResult(Activity.RESULT_OK, null);
}
return null;
}
}
}