Fix 3148496: Initial pass at fragmentizing lockscreen settings.
This converts most of the existing activities to fragments and wraps
them in PreferenceActivities so they can be launched as before
(e.g. by a DevicePolicyManager)
Upload after sync/rebase.
Change-Id: I4f351b75d9fca0498bcb04b4e11ff3b70765a4ba
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3de32cc..926f6f8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -651,9 +651,8 @@
<!-- Second and third-level settings -->
<activity android:name="ConfirmLockPattern"/>
- <activity android:name="ConfirmLockPassword"
- android:theme="@android:style/Theme.NoTitleBar">
- </activity>
+
+ <activity android:name="ConfirmLockPassword"/>>
<activity android:name="ChooseLockGeneric">
<intent-filter>
@@ -669,7 +668,6 @@
<activity android:name="ChooseLockPassword"
android:label="@string/lockpattern_change_lock_pin_label"
- android:theme="@android:style/Theme.NoTitleBar"
android:exported="false">
</activity>
diff --git a/res/layout-xlarge-land/choose_lock_password.xml b/res/layout-xlarge-land/choose_lock_password.xml
new file mode 100644
index 0000000..1276681
--- /dev/null
+++ b/res/layout-xlarge-land/choose_lock_password.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2008, 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="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:gravity="center_horizontal">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <!-- "Enter PIN(Password) to unlock" -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:layout_marginRight="6dip"
+ android:layout_marginLeft="6dip"
+ android:layout_marginTop="10dip"
+ android:layout_marginBottom="10dip"
+ android:gravity="left"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+
+ <!-- Password entry field -->
+ <EditText android:id="@+id/password_entry"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="true"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:textSize="24sp"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:background="@drawable/password_field_default"
+ android:textColor="#ffffffff"
+ />
+ </LinearLayout>
+
+ <!-- Spacer between password entry and keyboard -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ <!-- Alphanumeric keyboard -->
+ <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+ android:layout_alignParentBottom="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#00000000"
+ android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
+ android:visibility="gone"
+ />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1">
+
+ <Button android:id="@+id/cancel_button"
+ android:layout_height="wrap_content"
+ android:layout_width="140dip"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:layout_alignParentBottom="true"
+ android:layout_toLeftOf="@id/next_button"
+ android:text="@string/lockpassword_cancel_label"
+ />
+
+ <Button android:id="@+id/next_button"
+ android:layout_width="140dip"
+ android:layout_height="wrap_content"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentBottom="true"
+ android:text="@string/lockpassword_continue_label"
+ />
+
+ </RelativeLayout>
+
+</LinearLayout>
+
+
diff --git a/res/layout-xlarge-land/choose_lock_pattern.xml b/res/layout-xlarge-land/choose_lock_pattern.xml
new file mode 100644
index 0000000..fa2498f
--- /dev/null
+++ b/res/layout-xlarge-land/choose_lock_pattern.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.internal.widget.LinearLayoutWithDefaultTouchRecepient
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/topLayout"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- left side: lock pattern -->
+ <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <!-- right side: pattern and messages -->
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0">
+
+ <!-- header message -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="22sp"
+ android:gravity="left"/>
+
+ <!-- footer message -->
+ <TextView android:id="@+id/footerText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="22sp"
+ android:layout_marginTop="40dip"
+ android:visibility="gone"/>
+
+ <!-- confirm / restart buttons -->
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1">
+
+ <!-- right / bottom button: confirm or ok -->
+ <Button android:id="@+id/footerRightButton"
+ android:layout_height="wrap_content"
+ android:layout_width="140dip"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentBottom="true"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:text="@string/lockpattern_confirm_button_text"/>
+
+ <!-- left / top button: skip, or re-try -->
+ <Button android:id="@+id/footerLeftButton"
+ android:layout_height="wrap_content"
+ android:layout_width="140dip"
+ android:layout_toLeftOf="@id/footerRightButton"
+ android:layout_alignParentBottom="true"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:text="@string/lockpattern_restart_button_text"/>
+
+ </RelativeLayout>
+
+ </LinearLayout>
+
+</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
+
diff --git a/res/layout-xlarge-land/confirm_lock_password.xml b/res/layout-xlarge-land/confirm_lock_password.xml
new file mode 100644
index 0000000..cbfe88c
--- /dev/null
+++ b/res/layout-xlarge-land/confirm_lock_password.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<!-- This is the same layout as choose_lock_password. TODO: find out why merge fails -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:gravity="center_horizontal">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <!-- "Enter PIN(Password) to unlock" -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:layout_marginRight="6dip"
+ android:layout_marginLeft="6dip"
+ android:layout_marginTop="10dip"
+ android:layout_marginBottom="10dip"
+ android:gravity="left"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+
+ <!-- Password entry field -->
+ <EditText android:id="@+id/password_entry"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="true"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:textSize="24sp"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:background="@drawable/password_field_default"
+ android:textColor="#ffffffff"
+ />
+ </LinearLayout>
+
+ <!-- Spacer between password entry and keyboard -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ <!-- Alphanumeric keyboard -->
+ <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+ android:layout_alignParentBottom="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#00000000"
+ android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
+ android:visibility="gone"
+ />
+
+ <RelativeLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:visibility="visible">
+
+ <Button android:id="@+id/cancel_button"
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dip"
+ android:layout_toLeftOf="@id/next_button"
+ android:text="@string/lockpassword_cancel_label"
+ />
+
+ <Button android:id="@+id/next_button"
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dip"
+ android:layout_alignParentRight="true"
+ android:drawableRight="@drawable/ic_btn_next"
+ android:drawablePadding="10dip"
+ android:text="@string/lockpassword_continue_label"
+ />
+
+ </RelativeLayout>
+
+</LinearLayout>
+
diff --git a/res/layout-xlarge-land/confirm_lock_pattern.xml b/res/layout-xlarge-land/confirm_lock_pattern.xml
new file mode 100644
index 0000000..29fc93e
--- /dev/null
+++ b/res/layout-xlarge-land/confirm_lock_pattern.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.internal.widget.LinearLayoutWithDefaultTouchRecepient
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/topLayout"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- left side: lock pattern -->
+ <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- right side: instructions and buttons -->
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0">
+
+ <!-- header message -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="left"
+ android:textSize="22sp"/>
+
+ <!-- footer message -->
+ <TextView android:id="@+id/footerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="40dip"
+ android:gravity="left"
+ android:textSize="22sp"/>
+ </LinearLayout>
+
+</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
+
diff --git a/res/layout-xlarge/choose_lock_password.xml b/res/layout-xlarge/choose_lock_password.xml
new file mode 100644
index 0000000..051229e
--- /dev/null
+++ b/res/layout-xlarge/choose_lock_password.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2008, 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="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:background="@android:color/background_dark"
+ android:gravity="center_horizontal">
+
+ <!-- header text ('Enter Pin') -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:lines="2"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+ <!-- spacer above text entry field -->
+ <View
+ android:id="@+id/spacerBottom"
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:layout_marginTop="6dip"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+
+ <!-- Password entry field -->
+ <EditText android:id="@+id/password_entry"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:textSize="32sp"
+ android:layout_marginTop="15dip"
+ android:layout_marginLeft="30dip"
+ android:layout_marginRight="30dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:background="@drawable/password_field_default"
+ android:textColor="#ffffffff"
+ />
+
+ <!-- Spacer between password entry and keyboard -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ <!-- Alphanumeric keyboard -->
+ <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+ android:layout_alignParentBottom="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#00000000"
+ android:layout_marginBottom="30dip"
+ android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
+ />
+
+ <RelativeLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent">
+
+ <Button android:id="@+id/cancel_button"
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dip"
+ android:layout_alignParentLeft="true"
+ android:text="@string/lockpassword_cancel_label"
+ />
+
+ <Button android:id="@+id/next_button"
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dip"
+ android:layout_alignParentRight="true"
+ android:drawableRight="@drawable/ic_btn_next"
+ android:drawablePadding="10dip"
+ android:text="@string/lockpassword_continue_label"
+ />
+
+ </RelativeLayout>
+
+</LinearLayout>
diff --git a/res/layout-xlarge/choose_lock_pattern.xml b/res/layout-xlarge/choose_lock_pattern.xml
new file mode 100644
index 0000000..97c647f
--- /dev/null
+++ b/res/layout-xlarge/choose_lock_pattern.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.internal.widget.LinearLayoutWithDefaultTouchRecepient
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/topLayout"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="@color/black">
+
+ <!-- takes up all space above button bar at bottom -->
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1">
+
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:textSize="18sp"/>
+
+ <View
+ android:background="@*android:drawable/code_lock_top"
+ android:layout_width="match_parent"
+ android:layout_height="2dip" />
+ <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- bottom line looks bad when button bar is their too, omit in this case -->
+ <!--View
+ android:background="@*android:drawable/code_lock_bottom"
+ android:layout_width="match_parent"
+ android:layout_height="8dip" /-->
+
+ <TextView android:id="@+id/footerText"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:textSize="14sp"/>
+
+ </LinearLayout>
+
+
+ <LinearLayout style="@android:style/ButtonBar"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/footerLeftButton"
+ android:layout_height="wrap_content"
+ android:layout_width="140dip"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:text="@string/lockpattern_restart_button_text"/>
+
+ <View
+ android:visibility="invisible"
+ android:layout_height="0dip"
+ android:layout_width="1dip"
+ android:layout_weight="1" />
+
+ <Button android:id="@+id/footerRightButton"
+ android:layout_height="wrap_content"
+ android:layout_width="140dip"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:drawableRight="@drawable/ic_btn_next"
+ android:drawablePadding="3dip"
+ android:text="@string/lockpattern_confirm_button_text"/>
+
+ </LinearLayout>
+
+</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
diff --git a/res/layout-xlarge/confirm_lock_password.xml b/res/layout-xlarge/confirm_lock_password.xml
new file mode 100644
index 0000000..7f563b1
--- /dev/null
+++ b/res/layout-xlarge/confirm_lock_password.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<!-- This is the same layout as choose_lock_password -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:background="@android:color/background_dark"
+ android:gravity="center_horizontal">
+
+ <!-- header text ('Enter Pin') -->
+ <TextView android:id="@+id/headerText"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:lines="2"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+ <!-- spacer above text entry field -->
+ <View
+ android:id="@+id/spacerBottom"
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:layout_marginTop="6dip"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+
+ <!-- Password entry field -->
+ <EditText android:id="@+id/password_entry"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:textSize="32sp"
+ android:layout_marginTop="15dip"
+ android:layout_marginLeft="30dip"
+ android:layout_marginRight="30dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:background="@drawable/password_field_default"
+ android:textColor="#ffffffff"
+ />
+
+ <!-- Spacer between password entry and keyboard -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ <!-- Alphanumeric keyboard -->
+ <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+ android:layout_alignParentBottom="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#00000000"
+ android:layout_marginBottom="30dip"
+ android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
+ />
+
+ <RelativeLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent">
+
+ <Button android:id="@+id/cancel_button"
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dip"
+ android:layout_alignParentLeft="true"
+ android:text="@string/lockpassword_cancel_label"
+ />
+
+ <Button android:id="@+id/next_button"
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dip"
+ android:layout_alignParentRight="true"
+ android:drawableRight="@drawable/ic_btn_next"
+ android:drawablePadding="10dip"
+ android:text="@string/lockpassword_continue_label"
+ />
+
+ </RelativeLayout>
+
+</LinearLayout>
+
diff --git a/res/layout-xlarge/confirm_lock_pattern.xml b/res/layout-xlarge/confirm_lock_pattern.xml
new file mode 100644
index 0000000..01ef5b1
--- /dev/null
+++ b/res/layout-xlarge/confirm_lock_pattern.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.internal.widget.LinearLayoutWithDefaultTouchRecepient
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/topLayout"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="@color/black">
+
+ <TextView android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0"
+ android:gravity="center"
+ android:textSize="18sp"/>
+
+ <View
+ android:background="@*android:drawable/code_lock_top"
+ android:layout_width="match_parent"
+ android:layout_height="2dip" />
+ <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <View
+ android:background="@*android:drawable/code_lock_bottom"
+ android:layout_width="match_parent"
+ android:layout_height="8dip" />
+
+ <TextView android:id="@+id/footerText"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0"
+ android:gravity="center"
+ android:textSize="14sp"/>
+
+
+</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index f87ee5a..264db5f 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -18,6 +18,7 @@
import com.android.internal.widget.LockPatternUtils;
+import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
@@ -28,179 +29,190 @@
import android.preference.PreferenceScreen;
public class ChooseLockGeneric extends PreferenceActivity {
- private static final int MIN_PASSWORD_LENGTH = 4;
- private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off";
- private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
- private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
- private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
- private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
- private static final int CONFIRM_EXISTING_REQUEST = 100;
- private static final String PASSWORD_CONFIRMED = "password_confirmed";
- private static final String CONFIRM_CREDENTIALS = "confirm_credentials";
-
- private ChooseLockSettingsHelper mChooseLockSettingsHelper;
- private DevicePolicyManager mDPM;
- private boolean mPasswordConfirmed = false;
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ChooseLockGenericFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
+ }
- mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
- mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
+ public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
+ private static final int MIN_PASSWORD_LENGTH = 4;
+ private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off";
+ private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
+ private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
+ private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
+ private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
+ private static final int CONFIRM_EXISTING_REQUEST = 100;
+ private static final String PASSWORD_CONFIRMED = "password_confirmed";
+ private static final String CONFIRM_CREDENTIALS = "confirm_credentials";
- if (savedInstanceState != null) {
- mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
- }
+ private ChooseLockSettingsHelper mChooseLockSettingsHelper;
+ private DevicePolicyManager mDPM;
+ private boolean mPasswordConfirmed = false;
- if (!mPasswordConfirmed) {
- ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
- if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null)) {
- mPasswordConfirmed = true; // no password set, so no need to confirm
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity());
+
+ if (savedInstanceState != null) {
+ mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
+ }
+
+ if (!mPasswordConfirmed) {
+ ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this.getActivity(), this);
+ if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null)) {
+ mPasswordConfirmed = true; // no password set, so no need to confirm
+ updatePreferencesOrFinish();
+ }
+ } else {
updatePreferencesOrFinish();
}
- } else {
- updatePreferencesOrFinish();
}
- }
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
- Preference preference) {
- final String key = preference.getKey();
- boolean handled = true;
- if (KEY_UNLOCK_SET_OFF.equals(key)) {
- updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true);
- } else if (KEY_UNLOCK_SET_NONE.equals(key)) {
- updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false);
- } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
- updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false);
- } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
- updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false);
- } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
- updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false);
- } else {
- handled = false;
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
+ Preference preference) {
+ final String key = preference.getKey();
+ boolean handled = true;
+ if (KEY_UNLOCK_SET_OFF.equals(key)) {
+ updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true);
+ } else if (KEY_UNLOCK_SET_NONE.equals(key)) {
+ updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false);
+ } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
+ updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false);
+ } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
+ updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false);
+ } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
+ updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false);
+ } else {
+ handled = false;
+ }
+ return handled;
}
- return handled;
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == RESULT_OK) {
- mPasswordConfirmed = true;
- updatePreferencesOrFinish();
- } else {
- setResult(RESULT_CANCELED);
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
+ mPasswordConfirmed = true;
+ updatePreferencesOrFinish();
+ } else {
+ getActivity().setResult(Activity.RESULT_CANCELED);
+ finish();
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ // Saved so we don't force user to re-enter their password if configuration changes
+ outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed);
+ }
+
+ private void updatePreferencesOrFinish() {
+ int quality = getActivity().getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
+ if (quality == -1) {
+ // If caller didn't specify password quality, show the UI and allow the user to choose.
+ quality = mChooseLockSettingsHelper.utils().getKeyguardStoredPasswordQuality();
+ final PreferenceScreen prefScreen = getPreferenceScreen();
+ if (prefScreen != null) {
+ prefScreen.removeAll();
+ }
+ addPreferencesFromResource(R.xml.security_settings_picker);
+ disableUnusablePreferences(mDPM.getPasswordQuality(null));
+ } else {
+ updateUnlockMethodAndFinish(quality, false);
+ }
+ }
+
+ /***
+ * Disables preferences that are less secure than required quality.
+ *
+ * @param quality the requested quality.
+ */
+ private void disableUnusablePreferences(final int quality) {
+ final Preference picker = getPreferenceScreen().findPreference("security_picker_category");
+ final PreferenceCategory cat = (PreferenceCategory) picker;
+ final int preferenceCount = cat.getPreferenceCount();
+ for (int i = 0; i < preferenceCount; i++) {
+ Preference pref = cat.getPreference(i);
+ if (pref instanceof PreferenceScreen) {
+ final String key = ((PreferenceScreen) pref).getKey();
+ boolean enabled = true;
+ if (KEY_UNLOCK_SET_OFF.equals(key)) {
+ enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ } else if (KEY_UNLOCK_SET_NONE.equals(key)) {
+ enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
+ enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+ } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
+ enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
+ enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+ }
+ if (!enabled) {
+ pref.setSummary(R.string.unlock_set_unlock_disabled_summary);
+ pref.setEnabled(false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Invokes an activity to change the user's pattern, password or PIN based on given quality
+ * and minimum quality specified by DevicePolicyManager. If quality is
+ * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared.
+ *
+ * @param quality the desired quality. Ignored if DevicePolicyManager requires more security.
+ * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is
+ * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}
+ */
+ void updateUnlockMethodAndFinish(int quality, boolean disabled) {
+ // Sanity check. We should never get here without confirming user's existing password first.
+ if (!mPasswordConfirmed) {
+ throw new IllegalStateException("Tried to update password without confirming first");
+ }
+
+ // Compare minimum allowed password quality and launch appropriate security setting method
+ int minQuality = mDPM.getPasswordQuality(null);
+ if (quality < minQuality) {
+ quality = minQuality;
+ }
+ if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
+ int minLength = mDPM.getPasswordMinimumLength(null);
+ if (minLength < MIN_PASSWORD_LENGTH) {
+ minLength = MIN_PASSWORD_LENGTH;
+ }
+ final int maxLength = mDPM.getPasswordMaximumLength(quality);
+ Intent intent = new Intent().setClass(getActivity(), ChooseLockPassword.class);
+ intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);
+ intent.putExtra(ChooseLockPassword.PASSWORD_MIN_KEY, minLength);
+ intent.putExtra(ChooseLockPassword.PASSWORD_MAX_KEY, maxLength);
+ intent.putExtra(CONFIRM_CREDENTIALS, false);
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ startActivity(intent);
+ } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
+ boolean showTutorial = !mChooseLockSettingsHelper.utils().isPatternEverChosen();
+ Intent intent = new Intent();
+ intent.setClass(getActivity(), showTutorial
+ ? ChooseLockPatternTutorial.class
+ : ChooseLockPattern.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ intent.putExtra("key_lock_method", "pattern");
+ intent.putExtra(CONFIRM_CREDENTIALS, false);
+ startActivity(intent);
+ } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ mChooseLockSettingsHelper.utils().clearLock();
+ mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled);
+ getActivity().setResult(Activity.RESULT_OK);
+ }
finish();
}
}
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- // Saved so we don't force user to re-enter their password if configuration changes
- outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed);
- }
-
- private void updatePreferencesOrFinish() {
- int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
- if (quality == -1) {
- // If caller didn't specify password quality, show the UI and allow the user to choose.
- quality = mChooseLockSettingsHelper.utils().getKeyguardStoredPasswordQuality();
- final PreferenceScreen prefScreen = getPreferenceScreen();
- if (prefScreen != null) {
- prefScreen.removeAll();
- }
- addPreferencesFromResource(R.xml.security_settings_picker);
- disableUnusablePreferences(mDPM.getPasswordQuality(null));
- } else {
- updateUnlockMethodAndFinish(quality, false);
- }
- }
-
- /***
- * Disables preferences that are less secure than required quality.
- *
- * @param quality the requested quality.
- */
- private void disableUnusablePreferences(final int quality) {
- final Preference picker = getPreferenceScreen().findPreference("security_picker_category");
- final PreferenceCategory cat = (PreferenceCategory) picker;
- final int preferenceCount = cat.getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- Preference pref = cat.getPreference(i);
- if (pref instanceof PreferenceScreen) {
- final String key = ((PreferenceScreen) pref).getKey();
- boolean enabled = true;
- if (KEY_UNLOCK_SET_OFF.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- } else if (KEY_UNLOCK_SET_NONE.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
- } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
- } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
- }
- if (!enabled) {
- pref.setSummary(R.string.unlock_set_unlock_disabled_summary);
- pref.setEnabled(false);
- }
- }
- }
- }
-
- /**
- * Invokes an activity to change the user's pattern, password or PIN based on given quality
- * and minimum quality specified by DevicePolicyManager. If quality is
- * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared.
- *
- * @param quality the desired quality. Ignored if DevicePolicyManager requires more security.
- * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is
- * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}
- */
- void updateUnlockMethodAndFinish(int quality, boolean disabled) {
- // Sanity check. We should never get here without confirming user's existing password first.
- if (!mPasswordConfirmed) {
- throw new IllegalStateException("Tried to update password without confirming first");
- }
-
- // Compare minimum allowed password quality and launch appropriate security setting method
- int minQuality = mDPM.getPasswordQuality(null);
- if (quality < minQuality) {
- quality = minQuality;
- }
- if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
- int minLength = mDPM.getPasswordMinimumLength(null);
- if (minLength < MIN_PASSWORD_LENGTH) {
- minLength = MIN_PASSWORD_LENGTH;
- }
- final int maxLength = mDPM.getPasswordMaximumLength(quality);
- Intent intent = new Intent().setClass(this, ChooseLockPassword.class);
- intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);
- intent.putExtra(ChooseLockPassword.PASSWORD_MIN_KEY, minLength);
- intent.putExtra(ChooseLockPassword.PASSWORD_MAX_KEY, maxLength);
- intent.putExtra(CONFIRM_CREDENTIALS, false);
- intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- startActivity(intent);
- } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
- boolean showTutorial = !mChooseLockSettingsHelper.utils().isPatternEverChosen();
- Intent intent = new Intent();
- intent.setClass(this, showTutorial
- ? ChooseLockPatternTutorial.class
- : ChooseLockPattern.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- intent.putExtra("key_lock_method", "pattern");
- intent.putExtra(CONFIRM_CREDENTIALS, false);
- startActivity(intent);
- } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- mChooseLockSettingsHelper.utils().clearLock();
- mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled);
- setResult(RESULT_OK);
- }
- finish();
- }
}
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 4d447f4..08e382c 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -21,19 +21,22 @@
import com.android.internal.widget.PasswordEntryKeyboardView;
import android.app.Activity;
+import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.inputmethodservice.KeyboardView;
import android.os.Bundle;
import android.os.Handler;
+import android.preference.PreferenceActivity;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
-import android.view.WindowManager;
+import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
@@ -41,30 +44,7 @@
import android.widget.TextView.OnEditorActionListener;
-public class ChooseLockPassword extends Activity implements OnClickListener, OnEditorActionListener,
- TextWatcher {
- private static final String KEY_FIRST_PIN = "first_pin";
- private static final String KEY_UI_STAGE = "ui_stage";
- private TextView mPasswordEntry;
- private int mPasswordMinLength = 4;
- private int mPasswordMaxLength = 16;
- private int mPasswordMinLetters = 0;
- private int mPasswordMinUpperCase = 0;
- private int mPasswordMinLowerCase = 0;
- private int mPasswordMinSymbols = 0;
- private int mPasswordMinNumeric = 0;
- private int mPasswordMinNonLetter = 0;
- private LockPatternUtils mLockPatternUtils;
- private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
- private ChooseLockSettingsHelper mChooseLockSettingsHelper;
- private com.android.settings.ChooseLockPassword.Stage mUiStage = Stage.Introduction;
- private TextView mHeaderText;
- private String mFirstPin;
- private KeyboardView mKeyboardView;
- private PasswordEntryKeyboardHelper mKeyboardHelper;
- private boolean mIsAlphaMode;
- private Button mCancelButton;
- private Button mNextButton;
+public class ChooseLockPassword extends PreferenceActivity {
public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
public static final String PASSWORD_MIN_LETTERS_KEY = "lockscreen.password_min_letters";
@@ -73,345 +53,393 @@
public static final String PASSWORD_MIN_NUMERIC_KEY = "lockscreen.password_min_numeric";
public static final String PASSWORD_MIN_SYMBOLS_KEY = "lockscreen.password_min_symbols";
public static final String PASSWORD_MIN_NONLETTER_KEY = "lockscreen.password_min_nonletter";
- private static Handler mHandler = new Handler();
- private static final int CONFIRM_EXISTING_REQUEST = 58;
- static final int RESULT_FINISHED = RESULT_FIRST_USER;
- private static final long ERROR_MESSAGE_TIMEOUT = 3000;
- /**
- * Keep track internally of where the user is in choosing a pattern.
- */
- protected enum Stage {
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ChooseLockPasswordFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
+ }
- Introduction(R.string.lockpassword_choose_your_password_header,
- R.string.lockpassword_choose_your_pin_header,
- R.string.lockpassword_continue_label),
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ // TODO: Fix on phones
+ // Disable IME on our window since we provide our own keyboard
+ //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ super.onCreate(savedInstanceState);
+ }
- NeedToConfirm(R.string.lockpassword_confirm_your_password_header,
- R.string.lockpassword_confirm_your_pin_header,
- R.string.lockpassword_ok_label),
-
- ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match,
- R.string.lockpassword_confirm_pins_dont_match,
- R.string.lockpassword_continue_label);
+ public static class ChooseLockPasswordFragment extends Fragment
+ implements OnClickListener, OnEditorActionListener, TextWatcher {
+ private static final String KEY_FIRST_PIN = "first_pin";
+ private static final String KEY_UI_STAGE = "ui_stage";
+ private TextView mPasswordEntry;
+ private int mPasswordMinLength = 4;
+ private int mPasswordMaxLength = 16;
+ private int mPasswordMinLetters = 0;
+ private int mPasswordMinUpperCase = 0;
+ private int mPasswordMinLowerCase = 0;
+ private int mPasswordMinSymbols = 0;
+ private int mPasswordMinNumeric = 0;
+ private int mPasswordMinNonLetter = 0;
+ private LockPatternUtils mLockPatternUtils;
+ private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ private ChooseLockSettingsHelper mChooseLockSettingsHelper;
+ private Stage mUiStage = Stage.Introduction;
+ private TextView mHeaderText;
+ private String mFirstPin;
+ private KeyboardView mKeyboardView;
+ private PasswordEntryKeyboardHelper mKeyboardHelper;
+ private boolean mIsAlphaMode;
+ private Button mCancelButton;
+ private Button mNextButton;
+ private static Handler mHandler = new Handler();
+ private static final int CONFIRM_EXISTING_REQUEST = 58;
+ static final int RESULT_FINISHED = RESULT_FIRST_USER;
+ private static final long ERROR_MESSAGE_TIMEOUT = 3000;
/**
- * @param headerMessage The message displayed at the top.
+ * Keep track internally of where the user is in choosing a pattern.
*/
- Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) {
- this.alphaHint = hintInAlpha;
- this.numericHint = hintInNumeric;
- this.buttonText = nextButtonText;
- }
+ protected enum Stage {
- public final int alphaHint;
- public final int numericHint;
- public final int buttonText;
- }
+ Introduction(R.string.lockpassword_choose_your_password_header,
+ R.string.lockpassword_choose_your_pin_header,
+ R.string.lockpassword_continue_label),
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mLockPatternUtils = new LockPatternUtils(this);
- mRequestedQuality = Math.max(getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
- mRequestedQuality), mLockPatternUtils.getRequestedPasswordQuality());
- mPasswordMinLength = Math.max(
- getIntent().getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength), mLockPatternUtils
- .getRequestedMinimumPasswordLength());
- mPasswordMaxLength = getIntent().getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
- mPasswordMinLetters = Math.max(getIntent().getIntExtra(PASSWORD_MIN_LETTERS_KEY,
- mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters());
- mPasswordMinUpperCase = Math.max(getIntent().getIntExtra(PASSWORD_MIN_UPPERCASE_KEY,
- mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase());
- mPasswordMinLowerCase = Math.max(getIntent().getIntExtra(PASSWORD_MIN_LOWERCASE_KEY,
- mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase());
- mPasswordMinNumeric = Math.max(getIntent().getIntExtra(PASSWORD_MIN_NUMERIC_KEY,
- mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric());
- mPasswordMinSymbols = Math.max(getIntent().getIntExtra(PASSWORD_MIN_SYMBOLS_KEY,
- mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols());
- mPasswordMinNonLetter = Math.max(getIntent().getIntExtra(PASSWORD_MIN_NONLETTER_KEY,
- mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter());
- final boolean confirmCredentials = getIntent().getBooleanExtra("confirm_credentials", true);
+ NeedToConfirm(R.string.lockpassword_confirm_your_password_header,
+ R.string.lockpassword_confirm_your_pin_header,
+ R.string.lockpassword_ok_label),
+ ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match,
+ R.string.lockpassword_confirm_pins_dont_match,
+ R.string.lockpassword_continue_label);
- initViews();
- mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
- if (savedInstanceState == null) {
- updateStage(Stage.Introduction);
- if (confirmCredentials) {
- mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
- null, null);
+ /**
+ * @param headerMessage The message displayed at the top.
+ */
+ Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) {
+ this.alphaHint = hintInAlpha;
+ this.numericHint = hintInNumeric;
+ this.buttonText = nextButtonText;
}
+
+ public final int alphaHint;
+ public final int numericHint;
+ public final int buttonText;
}
- }
- private void initViews() {
- setContentView(R.layout.choose_lock_password);
- // Disable IME on our window since we provide our own keyboard
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ // required constructor for fragments
+ public ChooseLockPasswordFragment() {
- mCancelButton = (Button) findViewById(R.id.cancel_button);
- mCancelButton.setOnClickListener(this);
- mNextButton = (Button) findViewById(R.id.next_button);
- mNextButton.setOnClickListener(this);
+ }
- mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
- mPasswordEntry = (TextView) findViewById(R.id.password_entry);
- mPasswordEntry.setOnEditorActionListener(this);
- mPasswordEntry.addTextChangedListener(this);
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLockPatternUtils = new LockPatternUtils(getActivity());
+ Intent intent = getActivity().getIntent();
+ mRequestedQuality = Math.max(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
+ mRequestedQuality), mLockPatternUtils.getRequestedPasswordQuality());
+ mPasswordMinLength = Math.max(
+ intent.getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength), mLockPatternUtils
+ .getRequestedMinimumPasswordLength());
+ mPasswordMaxLength = intent.getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
+ mPasswordMinLetters = Math.max(intent.getIntExtra(PASSWORD_MIN_LETTERS_KEY,
+ mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters());
+ mPasswordMinUpperCase = Math.max(intent.getIntExtra(PASSWORD_MIN_UPPERCASE_KEY,
+ mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase());
+ mPasswordMinLowerCase = Math.max(intent.getIntExtra(PASSWORD_MIN_LOWERCASE_KEY,
+ mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase());
+ mPasswordMinNumeric = Math.max(intent.getIntExtra(PASSWORD_MIN_NUMERIC_KEY,
+ mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric());
+ mPasswordMinSymbols = Math.max(intent.getIntExtra(PASSWORD_MIN_SYMBOLS_KEY,
+ mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols());
+ mPasswordMinNonLetter = Math.max(intent.getIntExtra(PASSWORD_MIN_NONLETTER_KEY,
+ mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter());
- mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
- || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality
- || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality;
- mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
- mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
- PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
- : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
+ }
- mHeaderText = (TextView) findViewById(R.id.headerText);
- mKeyboardView.requestFocus();
- }
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
- @Override
- protected void onResume() {
- super.onResume();
- updateStage(mUiStage);
- mKeyboardView.requestFocus();
- }
+ View view = inflater.inflate(R.layout.choose_lock_password, null);
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putString(KEY_UI_STAGE, mUiStage.name());
- outState.putString(KEY_FIRST_PIN, mFirstPin);
- }
+ mCancelButton = (Button) view.findViewById(R.id.cancel_button);
+ mCancelButton.setOnClickListener(this);
+ mNextButton = (Button) view.findViewById(R.id.next_button);
+ mNextButton.setOnClickListener(this);
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- String state = savedInstanceState.getString(KEY_UI_STAGE);
- mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
- if (state != null) {
- mUiStage = Stage.valueOf(state);
+ mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
+ || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality
+ || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality;
+ mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
+ mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
+ mPasswordEntry.setOnEditorActionListener(this);
+ mPasswordEntry.addTextChangedListener(this);
+
+ mKeyboardHelper = new PasswordEntryKeyboardHelper(getActivity(),
+ mKeyboardView, mPasswordEntry);
+ mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
+ PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
+ : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+
+ mHeaderText = (TextView) view.findViewById(R.id.headerText);
+ mKeyboardView.requestFocus();
+
+ Intent intent = getActivity().getIntent();
+ final boolean confirmCredentials = intent.getBooleanExtra("confirm_credentials", true);
+ if (savedInstanceState == null) {
+ updateStage(Stage.Introduction);
+ if (confirmCredentials) {
+ mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
+ null, null);
+ }
+ } else {
+ mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
+ final String state = savedInstanceState.getString(KEY_UI_STAGE);
+ if (state != null) {
+ mUiStage = Stage.valueOf(state);
+ updateStage(mUiStage);
+ }
+ }
+
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
updateStage(mUiStage);
+ mKeyboardView.requestFocus();
}
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode,
- Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- switch (requestCode) {
- case CONFIRM_EXISTING_REQUEST:
- if (resultCode != Activity.RESULT_OK) {
- setResult(RESULT_FINISHED);
- finish();
- }
- break;
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString(KEY_UI_STAGE, mUiStage.name());
+ outState.putString(KEY_FIRST_PIN, mFirstPin);
}
- }
- protected void updateStage(Stage stage) {
- mUiStage = stage;
- updateUi();
- }
-
- /**
- * Validates PIN and returns a message to display if PIN fails test.
- * @param password the raw password the user typed in
- * @return error message to show to user or null if password is OK
- */
- private String validatePassword(String password) {
- if (password.length() < mPasswordMinLength) {
- return getString(mIsAlphaMode ?
- R.string.lockpassword_password_too_short
- : R.string.lockpassword_pin_too_short, mPasswordMinLength);
- }
- if (password.length() > mPasswordMaxLength) {
- return getString(mIsAlphaMode ?
- R.string.lockpassword_password_too_long
- : R.string.lockpassword_pin_too_long, mPasswordMaxLength);
- }
- int letters = 0;
- int numbers = 0;
- int lowercase = 0;
- int symbols = 0;
- int uppercase = 0;
- int nonletter = 0;
- for (int i = 0; i < password.length(); i++) {
- char c = password.charAt(i);
- // allow non white space Latin-1 characters only
- if (c <= 32 || c > 127) {
- return getString(R.string.lockpassword_illegal_character);
- }
- if (c >= '0' && c <= '9') {
- numbers++;
- nonletter++;
- } else if (c >= 'A' && c <= 'Z') {
- letters++;
- uppercase++;
- } else if (c >= 'a' && c <= 'z') {
- letters++;
- lowercase++;
- } else {
- symbols++;
- nonletter++;
+ @Override
+ public void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ switch (requestCode) {
+ case CONFIRM_EXISTING_REQUEST:
+ if (resultCode != Activity.RESULT_OK) {
+ getActivity().setResult(RESULT_FINISHED);
+ getActivity().finish();
+ }
+ break;
}
}
- if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
- && (letters > 0 || symbols > 0)) {
- // This shouldn't be possible unless user finds some way to bring up
- // soft keyboard
- return getString(R.string.lockpassword_pin_contains_non_digits);
- } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) {
- if (letters < mPasswordMinLetters) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters),
- mPasswordMinLetters);
- } else if (numbers < mPasswordMinNumeric) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric),
- mPasswordMinNumeric);
- } else if (lowercase < mPasswordMinLowerCase) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase),
- mPasswordMinLowerCase);
- } else if (uppercase < mPasswordMinUpperCase) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase),
- mPasswordMinUpperCase);
- } else if (symbols < mPasswordMinSymbols) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols),
- mPasswordMinSymbols);
- } else if (nonletter < mPasswordMinNonLetter) {
- return String.format(getResources().getQuantityString(
- R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter),
- mPasswordMinNonLetter);
- }
- } else {
- final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
- == mRequestedQuality;
- final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
- == mRequestedQuality;
- if ((alphabetic || alphanumeric) && letters == 0) {
- return getString(R.string.lockpassword_password_requires_alpha);
- }
- if (alphanumeric && numbers == 0) {
- return getString(R.string.lockpassword_password_requires_digit);
- }
- }
- if(mLockPatternUtils.checkPasswordHistory(password)) {
- return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used
- : R.string.lockpassword_pin_recently_used);
- }
- return null;
- }
- private void handleNext() {
- final String pin = mPasswordEntry.getText().toString();
- if (TextUtils.isEmpty(pin)) {
- return;
+ protected void updateStage(Stage stage) {
+ mUiStage = stage;
+ updateUi();
}
- String errorMsg = null;
- if (mUiStage == Stage.Introduction) {
- errorMsg = validatePassword(pin);
- if (errorMsg == null) {
- mFirstPin = pin;
- updateStage(Stage.NeedToConfirm);
- mPasswordEntry.setText("");
- }
- } else if (mUiStage == Stage.NeedToConfirm) {
- if (mFirstPin.equals(pin)) {
- mLockPatternUtils.clearLock();
- mLockPatternUtils.saveLockPassword(pin, mRequestedQuality);
- finish();
- } else {
- updateStage(Stage.ConfirmWrong);
- CharSequence tmp = mPasswordEntry.getText();
- if (tmp != null) {
- Selection.setSelection((Spannable) tmp, 0, tmp.length());
- }
- }
- }
- if (errorMsg != null) {
- showError(errorMsg, mUiStage);
- }
- }
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.next_button:
- handleNext();
- break;
-
- case R.id.cancel_button:
- finish();
- break;
- }
- }
-
- private void showError(String msg, final Stage next) {
- mHeaderText.setText(msg);
- mHandler.postDelayed(new Runnable() {
- public void run() {
- updateStage(next);
- }
- }, ERROR_MESSAGE_TIMEOUT);
- }
-
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- // Check if this was the result of hitting the enter key
- if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN) {
- handleNext();
- return true;
- }
- return false;
- }
-
- /**
- * Update the hint based on current Stage and length of password entry
- */
- private void updateUi() {
- String password = mPasswordEntry.getText().toString();
- final int length = password.length();
- if (mUiStage == Stage.Introduction && length > 0) {
- if (length < mPasswordMinLength) {
- String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
+ /**
+ * Validates PIN and returns a message to display if PIN fails test.
+ * @param password the raw password the user typed in
+ * @return error message to show to user or null if password is OK
+ */
+ private String validatePassword(String password) {
+ if (password.length() < mPasswordMinLength) {
+ return getString(mIsAlphaMode ?
+ R.string.lockpassword_password_too_short
: R.string.lockpassword_pin_too_short, mPasswordMinLength);
- mHeaderText.setText(msg);
- mNextButton.setEnabled(false);
+ }
+ if (password.length() > mPasswordMaxLength) {
+ return getString(mIsAlphaMode ?
+ R.string.lockpassword_password_too_long
+ : R.string.lockpassword_pin_too_long, mPasswordMaxLength);
+ }
+ int letters = 0;
+ int numbers = 0;
+ int lowercase = 0;
+ int symbols = 0;
+ int uppercase = 0;
+ int nonletter = 0;
+ for (int i = 0; i < password.length(); i++) {
+ char c = password.charAt(i);
+ // allow non white space Latin-1 characters only
+ if (c <= 32 || c > 127) {
+ return getString(R.string.lockpassword_illegal_character);
+ }
+ if (c >= '0' && c <= '9') {
+ numbers++;
+ nonletter++;
+ } else if (c >= 'A' && c <= 'Z') {
+ letters++;
+ uppercase++;
+ } else if (c >= 'a' && c <= 'z') {
+ letters++;
+ lowercase++;
+ } else {
+ symbols++;
+ nonletter++;
+ }
+ }
+ if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
+ && (letters > 0 || symbols > 0)) {
+ // This shouldn't be possible unless user finds some way to bring up
+ // soft keyboard
+ return getString(R.string.lockpassword_pin_contains_non_digits);
+ } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) {
+ if (letters < mPasswordMinLetters) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters),
+ mPasswordMinLetters);
+ } else if (numbers < mPasswordMinNumeric) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric),
+ mPasswordMinNumeric);
+ } else if (lowercase < mPasswordMinLowerCase) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase),
+ mPasswordMinLowerCase);
+ } else if (uppercase < mPasswordMinUpperCase) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase),
+ mPasswordMinUpperCase);
+ } else if (symbols < mPasswordMinSymbols) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols),
+ mPasswordMinSymbols);
+ } else if (nonletter < mPasswordMinNonLetter) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter),
+ mPasswordMinNonLetter);
+ }
} else {
- String error = validatePassword(password);
- if (error != null) {
- mHeaderText.setText(error);
+ final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
+ == mRequestedQuality;
+ final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
+ == mRequestedQuality;
+ if ((alphabetic || alphanumeric) && letters == 0) {
+ return getString(R.string.lockpassword_password_requires_alpha);
+ }
+ if (alphanumeric && numbers == 0) {
+ return getString(R.string.lockpassword_password_requires_digit);
+ }
+ }
+ if(mLockPatternUtils.checkPasswordHistory(password)) {
+ return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used
+ : R.string.lockpassword_pin_recently_used);
+ }
+ return null;
+ }
+
+ private void handleNext() {
+ final String pin = mPasswordEntry.getText().toString();
+ if (TextUtils.isEmpty(pin)) {
+ return;
+ }
+ String errorMsg = null;
+ if (mUiStage == Stage.Introduction) {
+ errorMsg = validatePassword(pin);
+ if (errorMsg == null) {
+ mFirstPin = pin;
+ updateStage(Stage.NeedToConfirm);
+ mPasswordEntry.setText("");
+ }
+ } else if (mUiStage == Stage.NeedToConfirm) {
+ if (mFirstPin.equals(pin)) {
+ mLockPatternUtils.clearLock();
+ mLockPatternUtils.saveLockPassword(pin, mRequestedQuality);
+ getActivity().finish();
+ } else {
+ updateStage(Stage.ConfirmWrong);
+ CharSequence tmp = mPasswordEntry.getText();
+ if (tmp != null) {
+ Selection.setSelection((Spannable) tmp, 0, tmp.length());
+ }
+ }
+ }
+ if (errorMsg != null) {
+ showError(errorMsg, mUiStage);
+ }
+ }
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.next_button:
+ handleNext();
+ break;
+
+ case R.id.cancel_button:
+ getActivity().finish();
+ break;
+ }
+ }
+
+ private void showError(String msg, final Stage next) {
+ mHeaderText.setText(msg);
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ updateStage(next);
+ }
+ }, ERROR_MESSAGE_TIMEOUT);
+ }
+
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ // Check if this was the result of hitting the enter key
+ if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN) {
+ handleNext();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Update the hint based on current Stage and length of password entry
+ */
+ private void updateUi() {
+ String password = mPasswordEntry.getText().toString();
+ final int length = password.length();
+ if (mUiStage == Stage.Introduction && length > 0) {
+ if (length < mPasswordMinLength) {
+ String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
+ : R.string.lockpassword_pin_too_short, mPasswordMinLength);
+ mHeaderText.setText(msg);
mNextButton.setEnabled(false);
} else {
- mHeaderText.setText(R.string.lockpassword_press_continue);
- mNextButton.setEnabled(true);
+ String error = validatePassword(password);
+ if (error != null) {
+ mHeaderText.setText(error);
+ mNextButton.setEnabled(false);
+ } else {
+ mHeaderText.setText(R.string.lockpassword_press_continue);
+ mNextButton.setEnabled(true);
+ }
}
+ } else {
+ mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
+ mNextButton.setEnabled(length > 0);
}
- } else {
- mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
- mNextButton.setEnabled(length > 0);
+ mNextButton.setText(mUiStage.buttonText);
}
- mNextButton.setText(mUiStage.buttonText);
- }
- public void afterTextChanged(Editable s) {
- // Changing the text while error displayed resets to NeedToConfirm state
- if (mUiStage == Stage.ConfirmWrong) {
- mUiStage = Stage.NeedToConfirm;
+ public void afterTextChanged(Editable s) {
+ // Changing the text while error displayed resets to NeedToConfirm state
+ if (mUiStage == Stage.ConfirmWrong) {
+ mUiStage = Stage.NeedToConfirm;
+ }
+ updateUi();
}
- updateUi();
- }
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
+ }
- public void onTextChanged(CharSequence s, int start, int before, int count) {
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
}
}
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index b5c0e80..70c625a 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -22,14 +22,18 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell;
+
import static com.android.internal.widget.LockPatternView.DisplayMode;
import android.app.Activity;
+import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
+import android.preference.PreferenceActivity;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
-import android.view.Window;
+import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
@@ -44,7 +48,7 @@
* - asks for confirmation / restart
* - saves chosen password when confirmed
*/
-public class ChooseLockPattern extends Activity implements View.OnClickListener{
+public class ChooseLockPattern extends PreferenceActivity {
/**
* Used by the choose lock pattern wizard to indicate the wizard is
* finished, and each activity in the wizard should finish.
@@ -56,440 +60,461 @@
*/
static final int RESULT_FINISHED = RESULT_FIRST_USER;
- public static final int CONFIRM_EXISTING_REQUEST = 55;
-
- // how long after a confirmation message is shown before moving on
- static final int INFORMATION_MSG_TIMEOUT_MS = 3000;
-
- // how long we wait to clear a wrong pattern
- private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
-
- private static final int ID_EMPTY_MESSAGE = -1;
-
- protected TextView mHeaderText;
- protected LockPatternView mLockPatternView;
- protected TextView mFooterText;
- private TextView mFooterLeftButton;
- private TextView mFooterRightButton;
- protected List<LockPatternView.Cell> mChosenPattern = null;
-
- /**
- * The patten used during the help screen to show how to draw a pattern.
- */
- private final List<LockPatternView.Cell> mAnimatePattern =
- Collections.unmodifiableList(Lists.newArrayList(
- LockPatternView.Cell.of(0, 0),
- LockPatternView.Cell.of(0, 1),
- LockPatternView.Cell.of(1, 1),
- LockPatternView.Cell.of(2, 1)
- ));
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ChooseLockPatternFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
+ }
@Override
- protected void onActivityResult(int requestCode, int resultCode,
- Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- switch (requestCode) {
- case CONFIRM_EXISTING_REQUEST:
- if (resultCode != Activity.RESULT_OK) {
- setResult(RESULT_FINISHED);
- finish();
- }
- updateStage(Stage.Introduction);
- break;
- }
- }
-
- /**
- * The pattern listener that responds according to a user choosing a new
- * lock pattern.
- */
- protected LockPatternView.OnPatternListener mChooseNewLockPatternListener = new LockPatternView.OnPatternListener() {
-
- public void onPatternStart() {
- mLockPatternView.removeCallbacks(mClearPatternRunnable);
- patternInProgress();
- }
-
- public void onPatternCleared() {
- mLockPatternView.removeCallbacks(mClearPatternRunnable);
- }
-
- public void onPatternDetected(List<LockPatternView.Cell> pattern) {
- if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
- if (mChosenPattern == null) throw new IllegalStateException("null chosen pattern in stage 'need to confirm");
- if (mChosenPattern.equals(pattern)) {
- updateStage(Stage.ChoiceConfirmed);
- } else {
- updateStage(Stage.ConfirmWrong);
- }
- } else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
- if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
- updateStage(Stage.ChoiceTooShort);
- } else {
- mChosenPattern = new ArrayList<LockPatternView.Cell>(pattern);
- updateStage(Stage.FirstChoiceValid);
- }
- } else {
- throw new IllegalStateException("Unexpected stage " + mUiStage + " when "
- + "entering the pattern.");
- }
- }
-
- public void onPatternCellAdded(List<Cell> pattern) {
-
- }
-
- private void patternInProgress() {
- mHeaderText.setText(R.string.lockpattern_recording_inprogress);
- mFooterText.setText("");
- mFooterLeftButton.setEnabled(false);
- mFooterRightButton.setEnabled(false);
- }
- };
-
-
- /**
- * The states of the left footer button.
- */
- enum LeftButtonMode {
- Cancel(R.string.cancel, true),
- CancelDisabled(R.string.cancel, false),
- Retry(R.string.lockpattern_retry_button_text, true),
- RetryDisabled(R.string.lockpattern_retry_button_text, false),
- Gone(ID_EMPTY_MESSAGE, false);
-
-
- /**
- * @param text The displayed text for this mode.
- * @param enabled Whether the button should be enabled.
- */
- LeftButtonMode(int text, boolean enabled) {
- this.text = text;
- this.enabled = enabled;
- }
-
- final int text;
- final boolean enabled;
- }
-
- /**
- * The states of the right button.
- */
- enum RightButtonMode {
- Continue(R.string.lockpattern_continue_button_text, true),
- ContinueDisabled(R.string.lockpattern_continue_button_text, false),
- Confirm(R.string.lockpattern_confirm_button_text, true),
- ConfirmDisabled(R.string.lockpattern_confirm_button_text, false),
- Ok(android.R.string.ok, true);
-
- /**
- * @param text The displayed text for this mode.
- * @param enabled Whether the button should be enabled.
- */
- RightButtonMode(int text, boolean enabled) {
- this.text = text;
- this.enabled = enabled;
- }
-
- final int text;
- final boolean enabled;
- }
-
- /**
- * Keep track internally of where the user is in choosing a pattern.
- */
- protected enum Stage {
-
- Introduction(
- R.string.lockpattern_recording_intro_header,
- LeftButtonMode.Cancel, RightButtonMode.ContinueDisabled,
- R.string.lockpattern_recording_intro_footer, true),
- HelpScreen(
- R.string.lockpattern_settings_help_how_to_record,
- LeftButtonMode.Gone, RightButtonMode.Ok, ID_EMPTY_MESSAGE, false),
- ChoiceTooShort(
- R.string.lockpattern_recording_incorrect_too_short,
- LeftButtonMode.Retry, RightButtonMode.ContinueDisabled,
- ID_EMPTY_MESSAGE, true),
- FirstChoiceValid(
- R.string.lockpattern_pattern_entered_header,
- LeftButtonMode.Retry, RightButtonMode.Continue, ID_EMPTY_MESSAGE, false),
- NeedToConfirm(
- R.string.lockpattern_need_to_confirm,
- LeftButtonMode.CancelDisabled, RightButtonMode.ConfirmDisabled,
- ID_EMPTY_MESSAGE, true),
- ConfirmWrong(
- R.string.lockpattern_need_to_unlock_wrong,
- LeftButtonMode.Cancel, RightButtonMode.ConfirmDisabled,
- ID_EMPTY_MESSAGE, true),
- ChoiceConfirmed(
- R.string.lockpattern_pattern_confirmed_header,
- LeftButtonMode.Cancel, RightButtonMode.Confirm, ID_EMPTY_MESSAGE, false);
-
-
- /**
- * @param headerMessage The message displayed at the top.
- * @param leftMode The mode of the left button.
- * @param rightMode The mode of the right button.
- * @param footerMessage The footer message.
- * @param patternEnabled Whether the pattern widget is enabled.
- */
- Stage(int headerMessage,
- LeftButtonMode leftMode,
- RightButtonMode rightMode,
- int footerMessage, boolean patternEnabled) {
- this.headerMessage = headerMessage;
- this.leftMode = leftMode;
- this.rightMode = rightMode;
- this.footerMessage = footerMessage;
- this.patternEnabled = patternEnabled;
- }
-
- final int headerMessage;
- final LeftButtonMode leftMode;
- final RightButtonMode rightMode;
- final int footerMessage;
- final boolean patternEnabled;
- }
-
- private Stage mUiStage = Stage.Introduction;
-
- private Runnable mClearPatternRunnable = new Runnable() {
- public void run() {
- mLockPatternView.clearPattern();
- }
- };
-
- private ChooseLockSettingsHelper mChooseLockSettingsHelper;
-
- private static final String KEY_UI_STAGE = "uiStage";
- private static final String KEY_PATTERN_CHOICE = "chosenPattern";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
+ // requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
- mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
-
- setupViews();
-
- // make it so unhandled touch events within the unlock screen go to the
- // lock pattern view.
- final LinearLayoutWithDefaultTouchRecepient topLayout
- = (LinearLayoutWithDefaultTouchRecepient) findViewById(
- R.id.topLayout);
- topLayout.setDefaultTouchRecepient(mLockPatternView);
-
- final boolean confirmCredentials = getIntent().getBooleanExtra("confirm_credentials", true);
-
- if (savedInstanceState == null) {
- if (confirmCredentials) {
- // first launch. As a security measure, we're in NeedToConfirm mode until we know
- // there isn't an existing password or the user confirms their password.
- updateStage(Stage.NeedToConfirm);
- boolean launchedConfirmationActivity =
- mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
- null, null);
- if (!launchedConfirmationActivity) {
- updateStage(Stage.Introduction);
- }
- } else {
- updateStage(Stage.Introduction);
- }
- } else {
- // restore from previous state
- final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE);
- if (patternString != null) {
- mChosenPattern = LockPatternUtils.stringToPattern(patternString);
- }
- updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
- }
- }
-
- /**
- * Keep all "find view" related stuff confined to this function since in
- * case someone needs to subclass and customize.
- */
- protected void setupViews() {
- setContentView(R.layout.choose_lock_pattern);
-
- mHeaderText = (TextView) findViewById(R.id.headerText);
-
- mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
- mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
- mLockPatternView.setTactileFeedbackEnabled(
- mChooseLockSettingsHelper.utils().isTactileFeedbackEnabled());
-
- mFooterText = (TextView) findViewById(R.id.footerText);
-
- mFooterLeftButton = (TextView) findViewById(R.id.footerLeftButton);
- mFooterRightButton = (TextView) findViewById(R.id.footerRightButton);
-
- mFooterLeftButton.setOnClickListener(this);
- mFooterRightButton.setOnClickListener(this);
- }
-
- public void onClick(View v) {
- if (v == mFooterLeftButton) {
- if (mUiStage.leftMode == LeftButtonMode.Retry) {
- mChosenPattern = null;
- mLockPatternView.clearPattern();
- updateStage(Stage.Introduction);
- } else if (mUiStage.leftMode == LeftButtonMode.Cancel) {
- // They are canceling the entire wizard
- setResult(RESULT_FINISHED);
- finish();
- } else {
- throw new IllegalStateException("left footer button pressed, but stage of " +
- mUiStage + " doesn't make sense");
- }
- } else if (v == mFooterRightButton) {
-
- if (mUiStage.rightMode == RightButtonMode.Continue) {
- if (mUiStage != Stage.FirstChoiceValid) {
- throw new IllegalStateException("expected ui stage " + Stage.FirstChoiceValid
- + " when button is " + RightButtonMode.Continue);
- }
- updateStage(Stage.NeedToConfirm);
- } else if (mUiStage.rightMode == RightButtonMode.Confirm) {
- if (mUiStage != Stage.ChoiceConfirmed) {
- throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
- + " when button is " + RightButtonMode.Confirm);
- }
- saveChosenPatternAndFinish();
- } else if (mUiStage.rightMode == RightButtonMode.Ok) {
- if (mUiStage != Stage.HelpScreen) {
- throw new IllegalStateException("Help screen is only mode with ok button, but " +
- "stage is " + mUiStage);
- }
- mLockPatternView.clearPattern();
- mLockPatternView.setDisplayMode(DisplayMode.Correct);
- updateStage(Stage.Introduction);
- }
- }
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
- if (mUiStage == Stage.HelpScreen) {
- updateStage(Stage.Introduction);
- return true;
- }
- }
- if (keyCode == KeyEvent.KEYCODE_MENU && mUiStage == Stage.Introduction) {
- updateStage(Stage.HelpScreen);
- return true;
- }
-
+ // *** TODO ***
+ // chooseLockPatternFragment.onKeyDown(keyCode, event);
return super.onKeyDown(keyCode, event);
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
+ public static class ChooseLockPatternFragment extends Fragment
+ implements View.OnClickListener {
- outState.putInt(KEY_UI_STAGE, mUiStage.ordinal());
- if (mChosenPattern != null) {
- outState.putString(KEY_PATTERN_CHOICE, LockPatternUtils.patternToString(mChosenPattern));
- }
- }
+ public static final int CONFIRM_EXISTING_REQUEST = 55;
+ // how long after a confirmation message is shown before moving on
+ static final int INFORMATION_MSG_TIMEOUT_MS = 3000;
- /**
- * Updates the messages and buttons appropriate to what stage the user
- * is at in choosing a view. This doesn't handle clearing out the pattern;
- * the pattern is expected to be in the right state.
- * @param stage
- */
- protected void updateStage(Stage stage) {
+ // how long we wait to clear a wrong pattern
+ private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
- mUiStage = stage;
+ private static final int ID_EMPTY_MESSAGE = -1;
- // header text, footer text, visibility and
- // enabled state all known from the stage
- if (stage == Stage.ChoiceTooShort) {
- mHeaderText.setText(
- getResources().getString(
- stage.headerMessage,
- LockPatternUtils.MIN_LOCK_PATTERN_SIZE));
- } else {
- mHeaderText.setText(stage.headerMessage);
- }
- if (stage.footerMessage == ID_EMPTY_MESSAGE) {
- mFooterText.setText("");
- } else {
- mFooterText.setText(stage.footerMessage);
+ protected TextView mHeaderText;
+ protected LockPatternView mLockPatternView;
+ protected TextView mFooterText;
+ private TextView mFooterLeftButton;
+ private TextView mFooterRightButton;
+ protected List<LockPatternView.Cell> mChosenPattern = null;
+
+ /**
+ * The patten used during the help screen to show how to draw a pattern.
+ */
+ private final List<LockPatternView.Cell> mAnimatePattern =
+ Collections.unmodifiableList(Lists.newArrayList(
+ LockPatternView.Cell.of(0, 0),
+ LockPatternView.Cell.of(0, 1),
+ LockPatternView.Cell.of(1, 1),
+ LockPatternView.Cell.of(2, 1)
+ ));
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ switch (requestCode) {
+ case CONFIRM_EXISTING_REQUEST:
+ if (resultCode != Activity.RESULT_OK) {
+ getActivity().setResult(RESULT_FINISHED);
+ getActivity().finish();
+ }
+ updateStage(Stage.Introduction);
+ break;
+ }
}
- if (stage.leftMode == LeftButtonMode.Gone) {
- mFooterLeftButton.setVisibility(View.GONE);
- } else {
- mFooterLeftButton.setVisibility(View.VISIBLE);
- mFooterLeftButton.setText(stage.leftMode.text);
- mFooterLeftButton.setEnabled(stage.leftMode.enabled);
+ /**
+ * The pattern listener that responds according to a user choosing a new
+ * lock pattern.
+ */
+ protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
+ new LockPatternView.OnPatternListener() {
+
+ public void onPatternStart() {
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ patternInProgress();
+ }
+
+ public void onPatternCleared() {
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ }
+
+ public void onPatternDetected(List<LockPatternView.Cell> pattern) {
+ if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
+ if (mChosenPattern == null) throw new IllegalStateException(
+ "null chosen pattern in stage 'need to confirm");
+ if (mChosenPattern.equals(pattern)) {
+ updateStage(Stage.ChoiceConfirmed);
+ } else {
+ updateStage(Stage.ConfirmWrong);
+ }
+ } else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
+ if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
+ updateStage(Stage.ChoiceTooShort);
+ } else {
+ mChosenPattern = new ArrayList<LockPatternView.Cell>(pattern);
+ updateStage(Stage.FirstChoiceValid);
+ }
+ } else {
+ throw new IllegalStateException("Unexpected stage " + mUiStage + " when "
+ + "entering the pattern.");
+ }
+ }
+
+ public void onPatternCellAdded(List<Cell> pattern) {
+
+ }
+
+ private void patternInProgress() {
+ mHeaderText.setText(R.string.lockpattern_recording_inprogress);
+ mFooterText.setText("");
+ mFooterLeftButton.setEnabled(false);
+ mFooterRightButton.setEnabled(false);
+ }
+ };
+
+
+ /**
+ * The states of the left footer button.
+ */
+ enum LeftButtonMode {
+ Cancel(R.string.cancel, true),
+ CancelDisabled(R.string.cancel, false),
+ Retry(R.string.lockpattern_retry_button_text, true),
+ RetryDisabled(R.string.lockpattern_retry_button_text, false),
+ Gone(ID_EMPTY_MESSAGE, false);
+
+
+ /**
+ * @param text The displayed text for this mode.
+ * @param enabled Whether the button should be enabled.
+ */
+ LeftButtonMode(int text, boolean enabled) {
+ this.text = text;
+ this.enabled = enabled;
+ }
+
+ final int text;
+ final boolean enabled;
}
- mFooterRightButton.setText(stage.rightMode.text);
- mFooterRightButton.setEnabled(stage.rightMode.enabled);
+ /**
+ * The states of the right button.
+ */
+ enum RightButtonMode {
+ Continue(R.string.lockpattern_continue_button_text, true),
+ ContinueDisabled(R.string.lockpattern_continue_button_text, false),
+ Confirm(R.string.lockpattern_confirm_button_text, true),
+ ConfirmDisabled(R.string.lockpattern_confirm_button_text, false),
+ Ok(android.R.string.ok, true);
- // same for whether the patten is enabled
- if (stage.patternEnabled) {
- mLockPatternView.enableInput();
- } else {
- mLockPatternView.disableInput();
+ /**
+ * @param text The displayed text for this mode.
+ * @param enabled Whether the button should be enabled.
+ */
+ RightButtonMode(int text, boolean enabled) {
+ this.text = text;
+ this.enabled = enabled;
+ }
+
+ final int text;
+ final boolean enabled;
}
- // the rest of the stuff varies enough that it is easier just to handle
- // on a case by case basis.
- mLockPatternView.setDisplayMode(DisplayMode.Correct);
+ /**
+ * Keep track internally of where the user is in choosing a pattern.
+ */
+ protected enum Stage {
- switch (mUiStage) {
- case Introduction:
+ Introduction(
+ R.string.lockpattern_recording_intro_header,
+ LeftButtonMode.Cancel, RightButtonMode.ContinueDisabled,
+ R.string.lockpattern_recording_intro_footer, true),
+ HelpScreen(
+ R.string.lockpattern_settings_help_how_to_record,
+ LeftButtonMode.Gone, RightButtonMode.Ok, ID_EMPTY_MESSAGE, false),
+ ChoiceTooShort(
+ R.string.lockpattern_recording_incorrect_too_short,
+ LeftButtonMode.Retry, RightButtonMode.ContinueDisabled,
+ ID_EMPTY_MESSAGE, true),
+ FirstChoiceValid(
+ R.string.lockpattern_pattern_entered_header,
+ LeftButtonMode.Retry, RightButtonMode.Continue, ID_EMPTY_MESSAGE, false),
+ NeedToConfirm(
+ R.string.lockpattern_need_to_confirm,
+ LeftButtonMode.CancelDisabled, RightButtonMode.ConfirmDisabled,
+ ID_EMPTY_MESSAGE, true),
+ ConfirmWrong(
+ R.string.lockpattern_need_to_unlock_wrong,
+ LeftButtonMode.Cancel, RightButtonMode.ConfirmDisabled,
+ ID_EMPTY_MESSAGE, true),
+ ChoiceConfirmed(
+ R.string.lockpattern_pattern_confirmed_header,
+ LeftButtonMode.Cancel, RightButtonMode.Confirm, ID_EMPTY_MESSAGE, false);
+
+
+ /**
+ * @param headerMessage The message displayed at the top.
+ * @param leftMode The mode of the left button.
+ * @param rightMode The mode of the right button.
+ * @param footerMessage The footer message.
+ * @param patternEnabled Whether the pattern widget is enabled.
+ */
+ Stage(int headerMessage,
+ LeftButtonMode leftMode,
+ RightButtonMode rightMode,
+ int footerMessage, boolean patternEnabled) {
+ this.headerMessage = headerMessage;
+ this.leftMode = leftMode;
+ this.rightMode = rightMode;
+ this.footerMessage = footerMessage;
+ this.patternEnabled = patternEnabled;
+ }
+
+ final int headerMessage;
+ final LeftButtonMode leftMode;
+ final RightButtonMode rightMode;
+ final int footerMessage;
+ final boolean patternEnabled;
+ }
+
+ private Stage mUiStage = Stage.Introduction;
+
+ private Runnable mClearPatternRunnable = new Runnable() {
+ public void run() {
mLockPatternView.clearPattern();
- break;
- case HelpScreen:
- mLockPatternView.setPattern(DisplayMode.Animate, mAnimatePattern);
- break;
- case ChoiceTooShort:
- mLockPatternView.setDisplayMode(DisplayMode.Wrong);
- postClearPatternRunnable();
- break;
- case FirstChoiceValid:
- break;
- case NeedToConfirm:
- mLockPatternView.clearPattern();
- break;
- case ConfirmWrong:
- mLockPatternView.setDisplayMode(DisplayMode.Wrong);
- postClearPatternRunnable();
- break;
- case ChoiceConfirmed:
- break;
- }
- }
+ }
+ };
+ private ChooseLockSettingsHelper mChooseLockSettingsHelper;
- // clear the wrong pattern unless they have started a new one
- // already
- private void postClearPatternRunnable() {
- mLockPatternView.removeCallbacks(mClearPatternRunnable);
- mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
- }
+ private static final String KEY_UI_STAGE = "uiStage";
+ private static final String KEY_PATTERN_CHOICE = "chosenPattern";
- private void saveChosenPatternAndFinish() {
- LockPatternUtils utils = mChooseLockSettingsHelper.utils();
- final boolean lockVirgin = !utils.isPatternEverChosen();
-
- utils.saveLockPattern(mChosenPattern);
- utils.setLockPatternEnabled(true);
-
- if (lockVirgin) {
- utils.setVisiblePatternEnabled(true);
- utils.setTactileFeedbackEnabled(false);
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
}
- setResult(RESULT_FINISHED);
- finish();
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ // setupViews()
+ View view = inflater.inflate(R.layout.choose_lock_pattern, null);
+ mHeaderText = (TextView) view.findViewById(R.id.headerText);
+ mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
+ mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
+ mLockPatternView.setTactileFeedbackEnabled(
+ mChooseLockSettingsHelper.utils().isTactileFeedbackEnabled());
+
+ mFooterText = (TextView) view.findViewById(R.id.footerText);
+
+ mFooterLeftButton = (TextView) view.findViewById(R.id.footerLeftButton);
+ mFooterRightButton = (TextView) view.findViewById(R.id.footerRightButton);
+
+ mFooterLeftButton.setOnClickListener(this);
+ mFooterRightButton.setOnClickListener(this);
+
+ // make it so unhandled touch events within the unlock screen go to the
+ // lock pattern view.
+ final LinearLayoutWithDefaultTouchRecepient topLayout
+ = (LinearLayoutWithDefaultTouchRecepient) view.findViewById(
+ R.id.topLayout);
+ topLayout.setDefaultTouchRecepient(mLockPatternView);
+
+ final boolean confirmCredentials = getActivity().getIntent()
+ .getBooleanExtra("confirm_credentials", true);
+
+ if (savedInstanceState == null) {
+ if (confirmCredentials) {
+ // first launch. As a security measure, we're in NeedToConfirm mode until we
+ // know there isn't an existing password or the user confirms their password.
+ updateStage(Stage.NeedToConfirm);
+ boolean launchedConfirmationActivity =
+ mChooseLockSettingsHelper.launchConfirmationActivity(
+ CONFIRM_EXISTING_REQUEST, null, null);
+ if (!launchedConfirmationActivity) {
+ updateStage(Stage.Introduction);
+ }
+ } else {
+ updateStage(Stage.Introduction);
+ }
+ } else {
+ // restore from previous state
+ final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE);
+ if (patternString != null) {
+ mChosenPattern = LockPatternUtils.stringToPattern(patternString);
+ }
+ updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
+ }
+ return view;
+ }
+
+ public void onClick(View v) {
+ if (v == mFooterLeftButton) {
+ if (mUiStage.leftMode == LeftButtonMode.Retry) {
+ mChosenPattern = null;
+ mLockPatternView.clearPattern();
+ updateStage(Stage.Introduction);
+ } else if (mUiStage.leftMode == LeftButtonMode.Cancel) {
+ // They are canceling the entire wizard
+ getActivity().setResult(RESULT_FINISHED);
+ getActivity().finish();
+ } else {
+ throw new IllegalStateException("left footer button pressed, but stage of " +
+ mUiStage + " doesn't make sense");
+ }
+ } else if (v == mFooterRightButton) {
+
+ if (mUiStage.rightMode == RightButtonMode.Continue) {
+ if (mUiStage != Stage.FirstChoiceValid) {
+ throw new IllegalStateException("expected ui stage " + Stage.FirstChoiceValid
+ + " when button is " + RightButtonMode.Continue);
+ }
+ updateStage(Stage.NeedToConfirm);
+ } else if (mUiStage.rightMode == RightButtonMode.Confirm) {
+ if (mUiStage != Stage.ChoiceConfirmed) {
+ throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
+ + " when button is " + RightButtonMode.Confirm);
+ }
+ saveChosenPatternAndFinish();
+ } else if (mUiStage.rightMode == RightButtonMode.Ok) {
+ if (mUiStage != Stage.HelpScreen) {
+ throw new IllegalStateException("Help screen is only mode with ok button, but " +
+ "stage is " + mUiStage);
+ }
+ mLockPatternView.clearPattern();
+ mLockPatternView.setDisplayMode(DisplayMode.Correct);
+ updateStage(Stage.Introduction);
+ }
+ }
+ }
+
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
+ if (mUiStage == Stage.HelpScreen) {
+ updateStage(Stage.Introduction);
+ return true;
+ }
+ }
+ if (keyCode == KeyEvent.KEYCODE_MENU && mUiStage == Stage.Introduction) {
+ updateStage(Stage.HelpScreen);
+ return true;
+ }
+ return false;
+ }
+
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ outState.putInt(KEY_UI_STAGE, mUiStage.ordinal());
+ if (mChosenPattern != null) {
+ outState.putString(KEY_PATTERN_CHOICE,
+ LockPatternUtils.patternToString(mChosenPattern));
+ }
+ }
+
+ /**
+ * Updates the messages and buttons appropriate to what stage the user
+ * is at in choosing a view. This doesn't handle clearing out the pattern;
+ * the pattern is expected to be in the right state.
+ * @param stage
+ */
+ protected void updateStage(Stage stage) {
+
+ mUiStage = stage;
+
+ // header text, footer text, visibility and
+ // enabled state all known from the stage
+ if (stage == Stage.ChoiceTooShort) {
+ mHeaderText.setText(
+ getResources().getString(
+ stage.headerMessage,
+ LockPatternUtils.MIN_LOCK_PATTERN_SIZE));
+ } else {
+ mHeaderText.setText(stage.headerMessage);
+ }
+ if (stage.footerMessage == ID_EMPTY_MESSAGE) {
+ mFooterText.setText("");
+ } else {
+ mFooterText.setText(stage.footerMessage);
+ }
+
+ if (stage.leftMode == LeftButtonMode.Gone) {
+ mFooterLeftButton.setVisibility(View.GONE);
+ } else {
+ mFooterLeftButton.setVisibility(View.VISIBLE);
+ mFooterLeftButton.setText(stage.leftMode.text);
+ mFooterLeftButton.setEnabled(stage.leftMode.enabled);
+ }
+
+ mFooterRightButton.setText(stage.rightMode.text);
+ mFooterRightButton.setEnabled(stage.rightMode.enabled);
+
+ // same for whether the patten is enabled
+ if (stage.patternEnabled) {
+ mLockPatternView.enableInput();
+ } else {
+ mLockPatternView.disableInput();
+ }
+
+ // the rest of the stuff varies enough that it is easier just to handle
+ // on a case by case basis.
+ mLockPatternView.setDisplayMode(DisplayMode.Correct);
+
+ switch (mUiStage) {
+ case Introduction:
+ mLockPatternView.clearPattern();
+ break;
+ case HelpScreen:
+ mLockPatternView.setPattern(DisplayMode.Animate, mAnimatePattern);
+ break;
+ case ChoiceTooShort:
+ mLockPatternView.setDisplayMode(DisplayMode.Wrong);
+ postClearPatternRunnable();
+ break;
+ case FirstChoiceValid:
+ break;
+ case NeedToConfirm:
+ mLockPatternView.clearPattern();
+ break;
+ case ConfirmWrong:
+ mLockPatternView.setDisplayMode(DisplayMode.Wrong);
+ postClearPatternRunnable();
+ break;
+ case ChoiceConfirmed:
+ break;
+ }
+ }
+
+
+ // clear the wrong pattern unless they have started a new one
+ // already
+ private void postClearPatternRunnable() {
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
+ }
+
+ private void saveChosenPatternAndFinish() {
+ LockPatternUtils utils = mChooseLockSettingsHelper.utils();
+ final boolean lockVirgin = !utils.isPatternEverChosen();
+
+ utils.saveLockPattern(mChosenPattern);
+ utils.setLockPatternEnabled(true);
+
+ if (lockVirgin) {
+ utils.setVisiblePatternEnabled(true);
+ utils.setTactileFeedbackEnabled(false);
+ }
+
+ getActivity().setResult(RESULT_FINISHED);
+ getActivity().finish();
+ }
}
}
diff --git a/src/com/android/settings/ChooseLockPatternExample.java b/src/com/android/settings/ChooseLockPatternExample.java
index 3c96d53..454c406 100644
--- a/src/com/android/settings/ChooseLockPatternExample.java
+++ b/src/com/android/settings/ChooseLockPatternExample.java
@@ -16,83 +16,100 @@
package com.android.settings;
-import android.app.Activity;
+import android.app.Fragment;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
+import android.preference.PreferenceActivity;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.ImageView;
-public class ChooseLockPatternExample extends Activity implements View.OnClickListener {
- private static final long START_DELAY = 1000;
- protected static final String TAG = "Settings";
- private View mNextButton;
- private View mSkipButton;
- private View mImageView;
- private AnimationDrawable mAnimation;
- private Handler mHandler = new Handler();
- private Runnable mRunnable = new Runnable() {
- public void run() {
- startAnimation(mAnimation);
+public class ChooseLockPatternExample extends PreferenceActivity {
+
+ // required constructor for fragments
+ public ChooseLockPatternExample() {
+
+ }
+
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ChooseLockPatternExampleFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
+ }
+
+ public static class ChooseLockPatternExampleFragment extends Fragment
+ implements View.OnClickListener {
+ private static final long START_DELAY = 1000;
+ protected static final String TAG = "Settings";
+ private View mNextButton;
+ private View mSkipButton;
+ private View mImageView;
+ private AnimationDrawable mAnimation;
+ private Handler mHandler = new Handler();
+ private Runnable mRunnable = new Runnable() {
+ public void run() {
+ startAnimation(mAnimation);
+ }
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.choose_lock_pattern_example, null);
+ mNextButton = view.findViewById(R.id.next_button);
+ mNextButton.setOnClickListener(this);
+
+ mSkipButton = view.findViewById(R.id.skip_button);
+ mSkipButton.setOnClickListener(this);
+
+ mImageView = (ImageView) view.findViewById(R.id.lock_anim);
+ mImageView.setBackgroundResource(R.drawable.lock_anim);
+ mImageView.setOnClickListener(this);
+ mAnimation = (AnimationDrawable) mImageView.getBackground();
+ return view;
}
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.choose_lock_pattern_example);
- initViews();
- }
+ @Override
+ public void onResume() {
+ super.onResume();
+ mHandler.postDelayed(mRunnable, START_DELAY);
+ }
- @Override
- protected void onResume() {
- super.onResume();
- mHandler.postDelayed(mRunnable, START_DELAY);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- stopAnimation(mAnimation);
- }
-
- public void onClick(View v) {
- if (v == mSkipButton) {
- // Canceling, so finish all
- setResult(ChooseLockPattern.RESULT_FINISHED);
- finish();
- } else if (v == mNextButton) {
+ @Override
+ public void onPause() {
+ super.onPause();
stopAnimation(mAnimation);
- Intent intent = new Intent(this, ChooseLockPattern.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- intent.putExtra("confirm_credentials", false);
- startActivity(intent);
- finish();
}
- }
- private void initViews() {
- mNextButton = findViewById(R.id.next_button);
- mNextButton.setOnClickListener(this);
-
- mSkipButton = findViewById(R.id.skip_button);
- mSkipButton.setOnClickListener(this);
-
- mImageView = (ImageView) findViewById(R.id.lock_anim);
- mImageView.setBackgroundResource(R.drawable.lock_anim);
- mImageView.setOnClickListener(this);
- mAnimation = (AnimationDrawable) mImageView.getBackground();
- }
-
- protected void startAnimation(final AnimationDrawable animation) {
- if (animation != null && !animation.isRunning()) {
- animation.run();
+ public void onClick(View v) {
+ if (v == mSkipButton) {
+ // Canceling, so finish all
+ getActivity().setResult(ChooseLockPattern.RESULT_FINISHED);
+ getActivity().finish();
+ } else if (v == mNextButton) {
+ stopAnimation(mAnimation);
+ Intent intent = new Intent(getActivity(), ChooseLockPattern.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ intent.putExtra("confirm_credentials", false);
+ startActivity(intent);
+ getActivity().finish();
+ }
}
- }
- protected void stopAnimation(final AnimationDrawable animation) {
- if (animation != null && animation.isRunning()) animation.stop();
+ protected void startAnimation(final AnimationDrawable animation) {
+ if (animation != null && !animation.isRunning()) {
+ animation.run();
+ }
+ }
+
+ protected void stopAnimation(final AnimationDrawable animation) {
+ if (animation != null && animation.isRunning()) animation.stop();
+ }
}
}
diff --git a/src/com/android/settings/ChooseLockPatternTutorial.java b/src/com/android/settings/ChooseLockPatternTutorial.java
index e699abf..da600c4 100644
--- a/src/com/android/settings/ChooseLockPatternTutorial.java
+++ b/src/com/android/settings/ChooseLockPatternTutorial.java
@@ -18,49 +18,70 @@
import com.android.internal.widget.LockPatternUtils;
-import android.app.Activity;
+import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
-public class ChooseLockPatternTutorial extends Activity implements View.OnClickListener {
- private View mNextButton;
- private View mSkipButton;
+public class ChooseLockPatternTutorial extends PreferenceActivity {
+
+ // required constructor for fragments
+ public ChooseLockPatternTutorial() {
+
+ }
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Don't show the tutorial if the user has seen it before.
- LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
- if (savedInstanceState == null && lockPatternUtils.isPatternEverChosen()) {
- Intent intent = new Intent(this, ChooseLockPattern.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- intent.putExtra("confirm_credentials", false);
- startActivity(intent);
- finish();
- } else {
- initViews();
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ChooseLockPatternTutorialFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
+ }
+
+ public static class ChooseLockPatternTutorialFragment extends Fragment
+ implements View.OnClickListener {
+ private View mNextButton;
+ private View mSkipButton;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Don't show the tutorial if the user has seen it before.
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
+ if (savedInstanceState == null && lockPatternUtils.isPatternEverChosen()) {
+ Intent intent = new Intent(getActivity(), ChooseLockPattern.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ intent.putExtra("confirm_credentials", false);
+ startActivity(intent);
+ getActivity().finish();
+ }
}
- }
- private void initViews() {
- setContentView(R.layout.choose_lock_pattern_tutorial);
- mNextButton = findViewById(R.id.next_button);
- mNextButton.setOnClickListener(this);
- mSkipButton = findViewById(R.id.skip_button);
- mSkipButton.setOnClickListener(this);
- }
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.choose_lock_pattern_tutorial, null);
+ mNextButton = view.findViewById(R.id.next_button);
+ mNextButton.setOnClickListener(this);
+ mSkipButton = view.findViewById(R.id.skip_button);
+ mSkipButton.setOnClickListener(this);
+ return view;
+ }
- public void onClick(View v) {
- if (v == mSkipButton) {
- // Canceling, so finish all
- setResult(ChooseLockPattern.RESULT_FINISHED);
- finish();
- } else if (v == mNextButton) {
- Intent intent = new Intent(this, ChooseLockPatternExample.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- startActivity(intent);
- finish();
+ public void onClick(View v) {
+ if (v == mSkipButton) {
+ // Canceling, so finish all
+ getActivity().setResult(ChooseLockPattern.RESULT_FINISHED);
+ getActivity().finish();
+ } else if (v == mNextButton) {
+ Intent intent = new Intent(getActivity(), ChooseLockPatternExample.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ startActivity(intent);
+ getActivity().finish();
+ }
}
}
}
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 0e893fa..380e848 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -20,113 +20,140 @@
import com.android.internal.widget.PasswordEntryKeyboardHelper;
import com.android.internal.widget.PasswordEntryKeyboardView;
-import android.app.Activity;
+import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
+import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
-import android.text.Editable;
+import android.preference.PreferenceActivity;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
-import android.view.WindowManager;
+import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
-import android.widget.Button;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-public class ConfirmLockPassword extends Activity implements OnClickListener,
- OnEditorActionListener {
- private static final long ERROR_MESSAGE_TIMEOUT = 3000;
- private TextView mPasswordEntry;
- private LockPatternUtils mLockPatternUtils;
- private TextView mHeaderText;
- private Handler mHandler = new Handler();
- private PasswordEntryKeyboardHelper mKeyboardHelper;
- private PasswordEntryKeyboardView mKeyboardView;
+public class ConfirmLockPassword extends PreferenceActivity {
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mLockPatternUtils = new LockPatternUtils(this);
- initViews();
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ConfirmLockPasswordFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
}
- private void initViews() {
- final int storedQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality();
- setContentView(R.layout.confirm_lock_password);
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
// Disable IME on our window since we provide our own keyboard
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
-
- findViewById(R.id.cancel_button).setOnClickListener(this);
- findViewById(R.id.next_button).setOnClickListener(this);
- mPasswordEntry = (TextView) findViewById(R.id.password_entry);
- mPasswordEntry.setOnEditorActionListener(this);
- mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
- mHeaderText = (TextView) findViewById(R.id.headerText);
- final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
- || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
- || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality;
- mHeaderText.setText(isAlpha ? R.string.lockpassword_confirm_your_password_header
- : R.string.lockpassword_confirm_your_pin_header);
- mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
- mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
- : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
- mKeyboardView.requestFocus();
+ //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ super.onCreate(savedInstanceState);
}
- @Override
- protected void onPause() {
- super.onPause();
- mKeyboardView.requestFocus();
- }
+ public static class ConfirmLockPasswordFragment extends Fragment implements OnClickListener,
+ OnEditorActionListener {
+ private static final long ERROR_MESSAGE_TIMEOUT = 3000;
+ private TextView mPasswordEntry;
+ private LockPatternUtils mLockPatternUtils;
+ private TextView mHeaderText;
+ private Handler mHandler = new Handler();
+ private PasswordEntryKeyboardHelper mKeyboardHelper;
+ private PasswordEntryKeyboardView mKeyboardView;
- @Override
- protected void onResume() {
- // TODO Auto-generated method stub
- super.onResume();
- mKeyboardView.requestFocus();
- }
- private void handleNext() {
- final String pin = mPasswordEntry.getText().toString();
- if (mLockPatternUtils.checkPassword(pin)) {
- setResult(RESULT_OK);
- finish();
- } else {
- showError(R.string.lockpattern_need_to_unlock_wrong);
+ // required constructor for fragments
+ public ConfirmLockPasswordFragment() {
+
}
- }
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.next_button:
- handleNext();
- break;
-
- case R.id.cancel_button:
- setResult(RESULT_CANCELED);
- finish();
- break;
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLockPatternUtils = new LockPatternUtils(getActivity());
}
- }
- private void showError(int msg) {
- mHeaderText.setText(msg);
- mPasswordEntry.setText(null);
- mHandler.postDelayed(new Runnable() {
- public void run() {
- mHeaderText.setText(R.string.lockpassword_confirm_your_password_header);
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final int storedQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality();
+ View view = inflater.inflate(R.layout.confirm_lock_password, null);
+ // Disable IME on our window since we provide our own keyboard
+
+ view.findViewById(R.id.cancel_button).setOnClickListener(this);
+ view.findViewById(R.id.next_button).setOnClickListener(this);
+ mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
+ mPasswordEntry.setOnEditorActionListener(this);
+ mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
+ mHeaderText = (TextView) view.findViewById(R.id.headerText);
+ final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
+ || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
+ || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality;
+ mHeaderText.setText(isAlpha ? R.string.lockpassword_confirm_your_password_header
+ : R.string.lockpassword_confirm_your_pin_header);
+ mKeyboardHelper = new PasswordEntryKeyboardHelper(getActivity(),
+ mKeyboardView, mPasswordEntry);
+ mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
+ : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+ mKeyboardView.requestFocus();
+ return view;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mKeyboardView.requestFocus();
+ }
+
+ @Override
+ public void onResume() {
+ // TODO Auto-generated method stub
+ super.onResume();
+ mKeyboardView.requestFocus();
+ }
+
+ private void handleNext() {
+ final String pin = mPasswordEntry.getText().toString();
+ if (mLockPatternUtils.checkPassword(pin)) {
+ getActivity().setResult(RESULT_OK);
+ getActivity().finish();
+ } else {
+ showError(R.string.lockpattern_need_to_unlock_wrong);
}
- }, ERROR_MESSAGE_TIMEOUT);
- }
-
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- // Check if this was the result of hitting the enter key
- if (actionId == EditorInfo.IME_NULL) {
- handleNext();
- return true;
}
- return false;
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.next_button:
+ handleNext();
+ break;
+
+ case R.id.cancel_button:
+ getActivity().setResult(RESULT_CANCELED);
+ getActivity().finish();
+ break;
+ }
+ }
+
+ private void showError(int msg) {
+ mHeaderText.setText(msg);
+ mPasswordEntry.setText(null);
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ mHeaderText.setText(R.string.lockpassword_confirm_your_password_header);
+ }
+ }, ERROR_MESSAGE_TIMEOUT);
+ }
+
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ // Check if this was the result of hitting the enter key
+ if (actionId == EditorInfo.IME_NULL) {
+ handleNext();
+ return true;
+ }
+ return false;
+ }
}
}
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index 8d44875..25e8370 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -22,12 +22,16 @@
import com.android.internal.widget.LockPatternView.Cell;
import android.app.Activity;
+import android.app.Fragment;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.os.Bundle;
+import android.preference.PreferenceActivity;
import android.widget.TextView;
-import android.view.Window;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import java.util.List;
@@ -37,7 +41,7 @@
* Sets an activity result of {@link Activity#RESULT_OK} when the user
* successfully confirmed their pattern.
*/
-public class ConfirmLockPattern extends Activity {
+public class ConfirmLockPattern extends PreferenceActivity {
/**
* Names of {@link CharSequence} fields within the originating {@link Intent}
@@ -45,30 +49,11 @@
* The view will use the system-defined resource strings for any labels that
* the caller does not supply.
*/
- public static final String HEADER_TEXT = "com.android.settings.ConfirmLockPattern.header";
- public static final String FOOTER_TEXT = "com.android.settings.ConfirmLockPattern.footer";
- public static final String HEADER_WRONG_TEXT = "com.android.settings.ConfirmLockPattern.header_wrong";
- public static final String FOOTER_WRONG_TEXT = "com.android.settings.ConfirmLockPattern.footer_wrong";
-
- // how long we wait to clear a wrong pattern
- private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
-
- private static final String KEY_NUM_WRONG_ATTEMPTS = "num_wrong_attempts";
-
- private LockPatternView mLockPatternView;
- private LockPatternUtils mLockPatternUtils;
- private int mNumWrongConfirmAttempts;
- private CountDownTimer mCountdownTimer;
-
- private TextView mHeaderTextView;
- private TextView mFooterTextView;
-
- // caller-supplied text for various prompts
- private CharSequence mHeaderText;
- private CharSequence mFooterText;
- private CharSequence mHeaderWrongText;
- private CharSequence mFooterWrongText;
-
+ public static final String PACKAGE = "com.android.settings";
+ public static final String HEADER_TEXT = PACKAGE + ".ConfirmLockPattern.header";
+ public static final String FOOTER_TEXT = PACKAGE + ".ConfirmLockPattern.footer";
+ public static final String HEADER_WRONG_TEXT = PACKAGE + ".ConfirmLockPattern.header_wrong";
+ public static final String FOOTER_WRONG_TEXT = PACKAGE + ".ConfirmLockPattern.footer_wrong";
private enum Stage {
NeedToUnlock,
@@ -77,194 +62,232 @@
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ConfirmLockPatternFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
+ }
- mLockPatternUtils = new LockPatternUtils(this);
+ public static class ConfirmLockPatternFragment extends Fragment {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.confirm_lock_pattern);
+ // how long we wait to clear a wrong pattern
+ private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
- mHeaderTextView = (TextView) findViewById(R.id.headerText);
- mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
- mFooterTextView = (TextView) findViewById(R.id.footerText);
+ private static final String KEY_NUM_WRONG_ATTEMPTS = "num_wrong_attempts";
- // make it so unhandled touch events within the unlock screen go to the
- // lock pattern view.
- final LinearLayoutWithDefaultTouchRecepient topLayout
- = (LinearLayoutWithDefaultTouchRecepient) findViewById(
- R.id.topLayout);
- topLayout.setDefaultTouchRecepient(mLockPatternView);
+ private LockPatternView mLockPatternView;
+ private LockPatternUtils mLockPatternUtils;
+ private int mNumWrongConfirmAttempts;
+ private CountDownTimer mCountdownTimer;
- Intent intent = getIntent();
- if (intent != null) {
- mHeaderText = intent.getCharSequenceExtra(HEADER_TEXT);
- mFooterText = intent.getCharSequenceExtra(FOOTER_TEXT);
- mHeaderWrongText = intent.getCharSequenceExtra(HEADER_WRONG_TEXT);
- mFooterWrongText = intent.getCharSequenceExtra(FOOTER_WRONG_TEXT);
+ private TextView mHeaderTextView;
+ private TextView mFooterTextView;
+
+ // caller-supplied text for various prompts
+ private CharSequence mHeaderText;
+ private CharSequence mFooterText;
+ private CharSequence mHeaderWrongText;
+ private CharSequence mFooterWrongText;
+
+ // required constructor for fragments
+ public ConfirmLockPatternFragment() {
+
}
- mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
- mLockPatternView.setOnPatternListener(mConfirmExistingLockPatternListener);
- updateStage(Stage.NeedToUnlock);
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLockPatternUtils = new LockPatternUtils(getActivity());
+ }
- if (savedInstanceState != null) {
- mNumWrongConfirmAttempts = savedInstanceState.getInt(KEY_NUM_WRONG_ATTEMPTS);
- } else {
- // on first launch, if no lock pattern is set, then finish with
- // success (don't want user to get stuck confirming something that
- // doesn't exist).
- if (!mLockPatternUtils.savedPatternExists()) {
- setResult(RESULT_OK);
- finish();
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.confirm_lock_pattern, null);
+ mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
+ mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
+ mFooterTextView = (TextView) view.findViewById(R.id.footerText);
+
+ // make it so unhandled touch events within the unlock screen go to the
+ // lock pattern view.
+ final LinearLayoutWithDefaultTouchRecepient topLayout
+ = (LinearLayoutWithDefaultTouchRecepient) view.findViewById(R.id.topLayout);
+ topLayout.setDefaultTouchRecepient(mLockPatternView);
+
+ Intent intent = getActivity().getIntent();
+ if (intent != null) {
+ mHeaderText = intent.getCharSequenceExtra(HEADER_TEXT);
+ mFooterText = intent.getCharSequenceExtra(FOOTER_TEXT);
+ mHeaderWrongText = intent.getCharSequenceExtra(HEADER_WRONG_TEXT);
+ mFooterWrongText = intent.getCharSequenceExtra(FOOTER_WRONG_TEXT);
}
- }
- }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- // deliberately not calling super since we are managing this in full
- outState.putInt(KEY_NUM_WRONG_ATTEMPTS, mNumWrongConfirmAttempts);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- if (mCountdownTimer != null) {
- mCountdownTimer.cancel();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- // if the user is currently locked out, enforce it.
- long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
- if (deadline != 0) {
- handleAttemptLockout(deadline);
- } else if (!mLockPatternView.isEnabled()) {
- // The deadline has passed, but the timer was cancelled...
- // Need to clean up.
- mNumWrongConfirmAttempts = 0;
+ mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+ mLockPatternView.setOnPatternListener(mConfirmExistingLockPatternListener);
updateStage(Stage.NeedToUnlock);
- }
- }
- private void updateStage(Stage stage) {
-
- switch (stage) {
- case NeedToUnlock:
- if (mHeaderText != null) {
- mHeaderTextView.setText(mHeaderText);
- } else {
- mHeaderTextView.setText(R.string.lockpattern_need_to_unlock);
- }
- if (mFooterText != null) {
- mFooterTextView.setText(mFooterText);
- } else {
- mFooterTextView.setText(R.string.lockpattern_need_to_unlock_footer);
- }
-
- mLockPatternView.setEnabled(true);
- mLockPatternView.enableInput();
- break;
- case NeedToUnlockWrong:
- if (mHeaderWrongText != null) {
- mHeaderTextView.setText(mHeaderWrongText);
- } else {
- mHeaderTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
- }
- if (mFooterWrongText != null) {
- mFooterTextView.setText(mFooterWrongText);
- } else {
- mFooterTextView.setText(R.string.lockpattern_need_to_unlock_wrong_footer);
- }
-
- mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
- mLockPatternView.setEnabled(true);
- mLockPatternView.enableInput();
- break;
- case LockedOut:
- mLockPatternView.clearPattern();
- // enabled = false means: disable input, and have the
- // appearance of being disabled.
- mLockPatternView.setEnabled(false); // appearance of being disabled
- break;
- }
- }
-
- private Runnable mClearPatternRunnable = new Runnable() {
- public void run() {
- mLockPatternView.clearPattern();
- }
- };
-
- // clear the wrong pattern unless they have started a new one
- // already
- private void postClearPatternRunnable() {
- mLockPatternView.removeCallbacks(mClearPatternRunnable);
- mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
- }
-
- /**
- * The pattern listener that responds according to a user confirming
- * an existing lock pattern.
- */
- private LockPatternView.OnPatternListener mConfirmExistingLockPatternListener = new LockPatternView.OnPatternListener() {
-
- public void onPatternStart() {
- mLockPatternView.removeCallbacks(mClearPatternRunnable);
- }
-
- public void onPatternCleared() {
- mLockPatternView.removeCallbacks(mClearPatternRunnable);
- }
-
- public void onPatternCellAdded(List<Cell> pattern) {
-
- }
-
- public void onPatternDetected(List<LockPatternView.Cell> pattern) {
- if (mLockPatternUtils.checkPattern(pattern)) {
- setResult(RESULT_OK);
- finish();
+ if (savedInstanceState != null) {
+ mNumWrongConfirmAttempts = savedInstanceState.getInt(KEY_NUM_WRONG_ATTEMPTS);
} else {
- if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL &&
- ++mNumWrongConfirmAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
- handleAttemptLockout(deadline);
- } else {
- updateStage(Stage.NeedToUnlockWrong);
- postClearPatternRunnable();
+ // on first launch, if no lock pattern is set, then finish with
+ // success (don't want user to get stuck confirming something that
+ // doesn't exist).
+ if (!mLockPatternUtils.savedPatternExists()) {
+ getActivity().setResult(Activity.RESULT_OK);
+ getActivity().finish();
}
}
+ return view;
}
- };
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ // deliberately not calling super since we are managing this in full
+ outState.putInt(KEY_NUM_WRONG_ATTEMPTS, mNumWrongConfirmAttempts);
+ }
- private void handleAttemptLockout(long elapsedRealtimeDeadline) {
- updateStage(Stage.LockedOut);
- long elapsedRealtime = SystemClock.elapsedRealtime();
- mCountdownTimer = new CountDownTimer(
- elapsedRealtimeDeadline - elapsedRealtime,
- LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS) {
+ @Override
+ public void onPause() {
+ super.onPause();
- @Override
- public void onTick(long millisUntilFinished) {
- mHeaderTextView.setText(R.string.lockpattern_too_many_failed_confirmation_attempts_header);
- final int secondsCountdown = (int) (millisUntilFinished / 1000);
- mFooterTextView.setText(getString(
- R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
- secondsCountdown));
+ if (mCountdownTimer != null) {
+ mCountdownTimer.cancel();
}
+ }
- @Override
- public void onFinish() {
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ // if the user is currently locked out, enforce it.
+ long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
+ if (deadline != 0) {
+ handleAttemptLockout(deadline);
+ } else if (!mLockPatternView.isEnabled()) {
+ // The deadline has passed, but the timer was cancelled...
+ // Need to clean up.
mNumWrongConfirmAttempts = 0;
updateStage(Stage.NeedToUnlock);
}
- }.start();
+ }
+
+ private void updateStage(Stage stage) {
+
+ switch (stage) {
+ case NeedToUnlock:
+ if (mHeaderText != null) {
+ mHeaderTextView.setText(mHeaderText);
+ } else {
+ mHeaderTextView.setText(R.string.lockpattern_need_to_unlock);
+ }
+ if (mFooterText != null) {
+ mFooterTextView.setText(mFooterText);
+ } else {
+ mFooterTextView.setText(R.string.lockpattern_need_to_unlock_footer);
+ }
+
+ mLockPatternView.setEnabled(true);
+ mLockPatternView.enableInput();
+ break;
+ case NeedToUnlockWrong:
+ if (mHeaderWrongText != null) {
+ mHeaderTextView.setText(mHeaderWrongText);
+ } else {
+ mHeaderTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
+ }
+ if (mFooterWrongText != null) {
+ mFooterTextView.setText(mFooterWrongText);
+ } else {
+ mFooterTextView.setText(R.string.lockpattern_need_to_unlock_wrong_footer);
+ }
+
+ mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
+ mLockPatternView.setEnabled(true);
+ mLockPatternView.enableInput();
+ break;
+ case LockedOut:
+ mLockPatternView.clearPattern();
+ // enabled = false means: disable input, and have the
+ // appearance of being disabled.
+ mLockPatternView.setEnabled(false); // appearance of being disabled
+ break;
+ }
+ }
+
+ private Runnable mClearPatternRunnable = new Runnable() {
+ public void run() {
+ mLockPatternView.clearPattern();
+ }
+ };
+
+ // clear the wrong pattern unless they have started a new one
+ // already
+ private void postClearPatternRunnable() {
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
+ }
+
+ /**
+ * The pattern listener that responds according to a user confirming
+ * an existing lock pattern.
+ */
+ private LockPatternView.OnPatternListener mConfirmExistingLockPatternListener
+ = new LockPatternView.OnPatternListener() {
+
+ public void onPatternStart() {
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ }
+
+ public void onPatternCleared() {
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ }
+
+ public void onPatternCellAdded(List<Cell> pattern) {
+
+ }
+
+ public void onPatternDetected(List<LockPatternView.Cell> pattern) {
+ if (mLockPatternUtils.checkPattern(pattern)) {
+ getActivity().setResult(Activity.RESULT_OK);
+ getActivity().finish();
+ } else {
+ if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL &&
+ ++mNumWrongConfirmAttempts
+ >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
+ long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+ handleAttemptLockout(deadline);
+ } else {
+ updateStage(Stage.NeedToUnlockWrong);
+ postClearPatternRunnable();
+ }
+ }
+ }
+ };
+
+
+ private void handleAttemptLockout(long elapsedRealtimeDeadline) {
+ updateStage(Stage.LockedOut);
+ long elapsedRealtime = SystemClock.elapsedRealtime();
+ mCountdownTimer = new CountDownTimer(
+ elapsedRealtimeDeadline - elapsedRealtime,
+ LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS) {
+
+ @Override
+ public void onTick(long millisUntilFinished) {
+ mHeaderTextView.setText(R.string.lockpattern_too_many_failed_confirmation_attempts_header);
+ final int secondsCountdown = (int) (millisUntilFinished / 1000);
+ mFooterTextView.setText(getString(
+ R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
+ secondsCountdown));
+ }
+
+ @Override
+ public void onFinish() {
+ mNumWrongConfirmAttempts = 0;
+ updateStage(Stage.NeedToUnlock);
+ }
+ }.start();
+ }
}
}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 8666d64..eea98b4 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -90,6 +90,8 @@
private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
private static final int FALLBACK_LOCK_AFTER_TIMEOUT_VALUE = 5000; // compatible with pre-Froyo
+ private static final String TAG = "SecuritySettings";
+
// Credential storage
private final CredentialStorage mCredentialStorage = new CredentialStorage();
@@ -359,8 +361,8 @@
final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
- Intent intent = new Intent(getActivity(), ChooseLockGeneric.class);
- startActivityForResult(intent, SET_OR_CHANGE_LOCK_METHOD_REQUEST);
+ startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
+ SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
} else if (KEY_LOCK_ENABLED.equals(key)) {
lockPatternUtils.setLockPatternEnabled(isToggled(preference));
} else if (KEY_VISIBLE_PATTERN.equals(key)) {