Update confirm device credentials to spec, add fingerprint

- New strings in the screen.
- New layout/style.
- Clean up internal API's around it.
- Add fingerprint support if launched from externally
- Separate theme if launched from externally
- If launched from above Keyguard, use SHOW_WHEN_LOCKED flag

Change-Id: Icdf9bf9e0506841f24e8aab5f0f1d1f4b688951f
This commit is contained in:
Jorim Jaggi
2015-04-06 17:47:18 -07:00
parent b5aa73f46f
commit 8a09b619ae
41 changed files with 1005 additions and 824 deletions

View File

@@ -1299,10 +1299,12 @@
</intent-filter>
</activity>
<activity android:name="ConfirmLockPattern"/>
<activity android:name="ConfirmLockPattern"
android:theme="@style/Theme.ConfirmDeviceCredentials"/>
<activity android:name="ConfirmLockPassword"
android:windowSoftInputMode="stateVisible|adjustResize"/>
android:windowSoftInputMode="stateVisible|adjustResize"
android:theme="@style/Theme.ConfirmDeviceCredentials"/>
<activity android:name="FingerprintSettings" android:exported="false"/>
<activity android:name="FingerprintEnroll" android:exported="false"/>

View File

@@ -0,0 +1,36 @@
<!--
~ Copyright (C) 2015 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
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32.0"
android:viewportHeight="32.0">
<path
android:fillColor="#ffffff"
android:pathData="M23.7,5.9c-0.1,0.0 -0.2,0.0 -0.3,-0.1C21.0,4.5 18.6,3.9 16.0,3.9c-2.5,0.0 -4.6,0.6 -6.9,1.9C8.8,6.0 8.3,5.9 8.1,5.5C7.9,5.2 8.0,4.7 8.4,4.5c2.5,-1.4 4.9,-2.1 7.7,-2.1c2.8,0.0 5.4,0.7 8.0,2.1c0.4,0.2 0.5,0.6 0.3,1.0C24.2,5.7 24.0,5.9 23.7,5.9z"/>
<path
android:fillColor="#ffffff"
android:pathData="M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z"/>
<path
android:fillColor="#ffffff"
android:pathData="M13.3,29.6c-0.2,0.0 -0.4,-0.1 -0.5,-0.2c-1.1,-1.2 -1.7,-2.0 -2.6,-3.6c-0.9,-1.7 -1.4,-3.7 -1.4,-5.9c0.0,-4.1 3.3,-7.4 7.4,-7.4c4.1,0.0 7.4,3.3 7.4,7.4c0.0,0.4 -0.3,0.7 -0.7,0.7s-0.7,-0.3 -0.7,-0.7c0.0,-3.3 -2.7,-5.9 -5.9,-5.9c-3.3,0.0 -5.9,2.7 -5.9,5.9c0.0,2.0 0.4,3.8 1.2,5.2c0.8,1.6 1.4,2.2 2.4,3.3c0.3,0.3 0.3,0.8 0.0,1.0C13.7,29.5 13.5,29.6 13.3,29.6z"/>
<path
android:fillColor="#ffffff"
android:pathData="M22.6,27.1c-1.6,0.0 -2.9,-0.4 -4.1,-1.2c-1.9,-1.4 -3.1,-3.6 -3.1,-6.0c0.0,-0.4 0.3,-0.7 0.7,-0.7s0.7,0.3 0.7,0.7c0.0,1.9 0.9,3.7 2.5,4.8c0.9,0.6 1.9,1.0 3.2,1.0c0.3,0.0 0.8,0.0 1.3,-0.1c0.4,-0.1 0.8,0.2 0.8,0.6c0.1,0.4 -0.2,0.8 -0.6,0.8C23.4,27.1 22.8,27.1 22.6,27.1z"/>
<path
android:fillColor="#ffffff"
android:pathData="M20.0,29.9c-0.1,0.0 -0.1,0.0 -0.2,0.0c-2.1,-0.6 -3.4,-1.4 -4.8,-2.9c-1.8,-1.9 -2.8,-4.4 -2.8,-7.1c0.0,-2.2 1.8,-4.1 4.1,-4.1c2.2,0.0 4.1,1.8 4.1,4.1c0.0,1.4 1.2,2.6 2.6,2.6c1.4,0.0 2.6,-1.2 2.6,-2.6c0.0,-5.1 -4.2,-9.3 -9.3,-9.3c-3.6,0.0 -6.9,2.1 -8.4,5.4C7.3,17.1 7.0,18.4 7.0,19.8c0.0,1.1 0.1,2.7 0.9,4.9c0.1,0.4 -0.1,0.8 -0.4,0.9c-0.4,0.1 -0.8,-0.1 -0.9,-0.4c-0.6,-1.8 -0.9,-3.6 -0.9,-5.4c0.0,-1.6 0.3,-3.1 0.9,-4.4c1.7,-3.8 5.6,-6.3 9.8,-6.3c5.9,0.0 10.7,4.8 10.7,10.7c0.0,2.2 -1.8,4.1 -4.1,4.1s-4.0,-1.8 -4.0,-4.1c0.0,-1.4 -1.2,-2.6 -2.6,-2.6c-1.4,0.0 -2.6,1.2 -2.6,2.6c0.0,2.3 0.9,4.5 2.4,6.1c1.2,1.3 2.4,2.0 4.2,2.5c0.4,0.1 0.6,0.5 0.5,0.9C20.6,29.7 20.3,29.9 20.0,29.9z"/>
</vector>

View File

@@ -0,0 +1,30 @@
<!--
~ Copyright (C) 2015 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
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32.0"
android:viewportHeight="32.0">
<path
android:fillColor="@color/warning"
android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/>
<path
android:fillColor="@color/warning"
android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/>
<path
android:fillColor="@color/warning"
android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/>
</vector>

View File

@@ -1,104 +1,92 @@
<?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.
*/
<!-- Copyright (C) 2015 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 basically 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"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/topLayout"
android:orientation="vertical"
android:gravity="center_horizontal">
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
<TextView
style="@android:style/TextAppearance.Material.Title"
android:id="@+id/headerText"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginTop="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!-- "Enter PIN(Password) to unlock" -->
<TextView android:id="@+id/headerText"
android:layout_width="0dip"
android:textColor="?android:attr/colorAccent"/>
<TextView
style="@android:style/TextAppearance.Material.Body1"
android:id="@+id/detailsText"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginTop="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:layout_marginEnd="6dip"
android:layout_marginStart="6dip"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip"
android:gravity="start"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<!-- Password entry field -->
<EditText android:id="@+id/password_entry"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:layout_marginBottom="5dip"
android:layout_gravity="center"
android:layout_weight="1"
android:inputType="textPassword"
android:imeOptions="actionNext"
android:gravity="center"
android:textSize="24sp"
style="@style/TextAppearance.PasswordEntry"
/>
</LinearLayout>
<!-- Spacer between password entry and keyboard -->
<View
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
android:layout_height="0dp"
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
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="@android:drawable/bottom_bar"
android:visibility="gone">
android:orientation="horizontal">
<Button android:id="@+id/cancel_button"
android:layout_width="150dip"
<Button
style="@android:style/Widget.Material.Button.Borderless"
android:id="@+id/cancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentStart="true"
android:text="@string/lockpassword_cancel_label"
/>
android:layout_gravity="start|bottom"
android:text="@string/cancel"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="14dp"/>
<Button android:id="@+id/next_button"
android:layout_width="150dip"
<EditText android:id="@+id/password_entry"
android:layout_width="208dp"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentEnd="true"
android:drawableEnd="@drawable/ic_btn_next"
android:drawablePadding="10dip"
android:text="@string/lockpassword_continue_label"
/>
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="26dp"
android:inputType="textPassword"
android:imeOptions="actionNext|flagNoFullscreen"
android:gravity="center"
android:textSize="16sp"
style="@style/TextAppearance.PasswordEntry"/>
</RelativeLayout>
<TextView style="@style/TextAppearance.ConfirmDeviceCredentialsErrorText"
android:id="@+id/errorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="10dp"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="end|bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="28dp"
android:layout_marginEnd="20dp"
android:visibility="gone"/>
</FrameLayout>
</LinearLayout>

View File

@@ -13,56 +13,102 @@
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: instructions and messages -->
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1.0"
>
android:clipChildren="false"
android:clipToPadding="false">
<!-- header message -->
<TextView android:id="@+id/headerText"
android:layout_width="match_parent"
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:textSize="18sp"/>
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">
<!-- fill space between header and button below -->
<View
android:layout_weight="1.0"
android:layout_width="match_parent"
android:layout_height="0dip"
/>
<!-- footer message -->
<TextView android:id="@+id/footerText"
android:layout_width="match_parent"
<TextView
style="@android:style/TextAppearance.Material.Headline"
android:id="@+id/headerText"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="14sp"/>
android:textColor="?android:attr/colorAccent"/>
<TextView
style="@android:style/TextAppearance.Material.Body1"
android:id="@+id/detailsText"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
style="@android:style/Widget.Material.Button.Borderless"
android:id="@+id/cancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"/>
</LinearLayout>
<View
android:background="@*android:drawable/code_lock_left"
android:layout_width="2dip"
android:layout_height="match_parent" />
<!-- right side: lock pattern -->
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
android:layout_width="match_parent"
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/lock_pattern_background" />
android:layout_weight="1"
android:orientation="horizontal"
android:clipChildren="false"
android:clipToPadding="false">
<View
android:id="@+id/leftSpacer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"/>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false">
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="288dp"
android:layout_height="288dp"
android:layout_marginStart="-42dp"
android:layout_marginEnd="-42dp"
android:layout_gravity="center_vertical"/>
<TextView
style="@style/TextAppearance.ConfirmDeviceCredentialsErrorText"
android:id="@+id/errorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="24dp"/>
</FrameLayout>
<View
android:id="@+id/rightSpacer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_vertical"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>

View File

@@ -1,91 +0,0 @@
<?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 tag fails -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
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_marginEnd="6dip"
android:layout_marginStart="6dip"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip"
android:gravity="start"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<!-- Password entry field -->
<EditText android:id="@+id/password_entry"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:layout_marginBottom="5dip"
android:layout_gravity="center"
android:layout_weight="1"
android:inputType="textPassword"
android:imeOptions="actionNext"
android:gravity="center"
android:textSize="24sp"
style="@style/TextAppearance.PasswordEntry"
/>
</LinearLayout>
<!-- confirm / restart buttons -->
<LinearLayout
style="@style/SecurityPreferenceButtonContainer"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<!-- left / top button: skip, or re-try -->
<Button android:id="@+id/cancel_button"
style="@style/SecurityPreferenceButton"
android:text="@string/lockpassword_cancel_label"/>
<!-- right / bottom button: confirm or ok -->
<Button android:id="@+id/next_button"
style="@style/SecurityPreferenceButton"
android:text="@string/lockpassword_continue_label"/>
</LinearLayout>
<!-- 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>

View File

@@ -1,64 +0,0 @@
<?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="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<!-- header message -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="40dip">
<TextView android:id="@+id/headerText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</ScrollView>
<!-- footer message -->
<TextView android:id="@+id/footerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dip"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<View
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="0.6"/>
<!-- lock pattern widget -->
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
android:layout_width="354dip"
android:layout_height="354dip"
android:background="@color/lock_pattern_background"
aspect="square"/>
<View
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"/>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>

View File

@@ -1,103 +1,26 @@
<?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: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:textAppearance="?android:attr/textAppearanceMedium"/>
<!-- 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"
~ Copyright (C) 2015 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
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dip"
android:layout_marginStart="30dip"
android:layout_marginEnd="30dip"
android:layout_gravity="center"
android:inputType="textPassword"
android:imeOptions="actionNext"
android:gravity="center"
android:textSize="32sp"
style="@style/TextAppearance.PasswordEntry"
/>
<!-- 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"
android:visibility="gone"
/>
<View
android:layout_width="match_parent"
android:layout_height="0dip"
/>
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<LinearLayout
style="@style/SecurityPreferenceButtonContainer"
android:layout_alignParentEnd="true"
android:orientation="horizontal">
<Button android:id="@+id/cancel_button"
style="@style/SecurityPreferenceButton"
android:text="@string/lockpassword_cancel_label"/>
<Button android:id="@+id/next_button"
style="@style/SecurityPreferenceButton"
android:text="@string/lockpassword_continue_label"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
android:layout_height="match_parent"
android:paddingTop="48dp">
<include layout="@layout/confirm_lock_password_base"
android:layout_width="328dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"/>
</FrameLayout>

View File

@@ -13,48 +13,19 @@
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"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
android:paddingTop="48dp"
android:background="#80000000">
<!-- top: instructions and buttons -->
<!-- header message -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="96dip">
<View android:layout_width="328dp"
android:layout_height="match_parent"
android:background="@color/confirm_device_credential_dark_background"
android:layout_gravity="center_horizontal"/>
<TextView android:id="@+id/headerText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</ScrollView>
<!-- footer message -->
<TextView android:id="@+id/footerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dip"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<!-- bottom: lock pattern -->
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
android:layout_width="354dip"
android:layout_height="354dip"
android:layout_marginTop="80dip"
android:background="@color/lock_pattern_background"
aspect="square"/>
<View
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"/>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
<include layout="@layout/confirm_lock_pattern_base"
android:layout_width="328dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"/>
</FrameLayout>

View File

@@ -1,89 +0,0 @@
<?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: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:textAppearance="?android:attr/textAppearanceMedium"/>
<!-- Password entry field -->
<EditText android:id="@+id/password_entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dip"
android:layout_marginEnd="30dip"
android:layout_gravity="center"
android:inputType="textPassword"
android:imeOptions="actionNext"
android:gravity="center"
android:textSize="24sp"
style="@style/TextAppearance.PasswordEntry"
/>
<!-- 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"
/>
<View
android:layout_width="match_parent"
android:layout_height="0dip"
/>
<LinearLayout
style="@style/SecurityPreferenceButtonContainer"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<!-- left / top button: skip, or re-try -->
<Button android:id="@+id/cancel_button"
style="@style/SecurityPreferenceButton"
android:text="@string/lockpattern_tutorial_cancel_label"/>
<!-- right / bottom button: confirm or ok -->
<Button android:id="@+id/next_button"
style="@style/SecurityPreferenceButton"
android:text="@string/lockpattern_tutorial_continue_label"/>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 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">
<TextView
style="@android:style/TextAppearance.Material.Headline"
android:id="@+id/headerText"
android:layout_marginStart="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginEnd="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginTop="?attr/confirmDeviceCredentialsTopMargin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/colorAccent"/>
<TextView
style="@android:style/TextAppearance.Material.Body1"
android:id="@+id/detailsText"
android:layout_marginStart="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginEnd="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginTop="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
style="@android:style/Widget.Material.Button.Borderless"
android:id="@+id/cancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"/>
<View android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<EditText
android:id="@+id/password_entry"
android:layout_width="208dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-40dp"
android:inputType="textPassword"
android:imeOptions="actionNext"
android:gravity="center"
android:textSize="16sp"
style="@style/TextAppearance.PasswordEntry"/>
<TextView
style="@style/TextAppearance.ConfirmDeviceCredentialsErrorText"
android:id="@+id/errorText"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:gravity="center_vertical"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="24dp"
android:visibility="gone"/>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>

View File

@@ -1,42 +0,0 @@
<?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">
<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"/>
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/lock_pattern_background" />
<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>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 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">
<TextView
style="@android:style/TextAppearance.Material.Headline"
android:id="@+id/headerText"
android:layout_marginStart="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginEnd="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginTop="?attr/confirmDeviceCredentialsTopMargin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/colorAccent"/>
<TextView
style="@android:style/TextAppearance.Material.Body1"
android:id="@+id/detailsText"
android:layout_marginStart="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginEnd="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginTop="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
style="@android:style/Widget.Material.Button.Borderless"
android:id="@+id/cancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"/>
<View android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"/>
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="312dp"
android:layout_height="312dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-46dp"
android:layout_marginBottom="-46dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.ConfirmDeviceCredentialsErrorText"
android:id="@+id/errorText"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:gravity="center_vertical"/>
<ImageView
android:id="@+id/fingerprintIcon"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="24dp"
android:visibility="gone"/>
</LinearLayout>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2015 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
-->
<resources>
<style name="Theme.ConfirmDeviceCredentials" parent="Theme.SubSettings">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

View File

@@ -87,4 +87,6 @@
<dimen name="wifi_assistant_padding_start_end">24dp</dimen>
<dimen name="wifi_assistant_padding">25dp</dimen>
<dimen name="wifi_assistant_text_padding">24dp</dimen>
<dimen name="confirm_credentials_security_method_margin">72dp</dimen>
</resources>

View File

@@ -68,5 +68,4 @@
<style name="KeyguardAppWidgetItem">
<item name="android:textSize">16sp</item>
</style>
</resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2015 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
-->
<resources>
<style name="Theme.ConfirmDeviceCredentials" parent="Theme.SubSettings">
</style>
</resources>

View File

@@ -15,7 +15,8 @@
-->
<resources>
<item name="notification_app_section" type="layout">@*android:layout/preference_category_material
</item>
<item name="notification_app_section" type="layout">@*android:layout/preference_category_material</item>
<item name="confirm_lock_pattern" type="layout">@layout/confirm_lock_pattern_base</item>
<item name="confirm_lock_password" type="layout">@layout/confirm_lock_password_base</item>
</resources>

View File

@@ -109,4 +109,8 @@
<attr name="switchBarMarginEnd" format="dimension" />
<attr name="preferenceBackgroundColor" format="color" />
<!-- Confirm device credentials screen -->
<attr name="confirmDeviceCredentialsSideMargin" format="dimension" />
<attr name="confirmDeviceCredentialsTopMargin" format="dimension" />
</resources>

View File

@@ -53,7 +53,9 @@
<color name="lock_pattern_background">#00000000</color>
<color name="lock_pattern_view_regular_color">#ff37474f</color>
<color name="lock_pattern_view_error_color">#fff4511e</color>
<color name="lock_pattern_view_error_color">@color/warning</color>
<color name="lock_pattern_view_regular_color_dark">#ffffff</color>
<color name="unlock_pattern_view_regular_color">@android:color/white</color>
<color name="unlock_pattern_view_error_color">#fff4511e</color>
@@ -76,4 +78,6 @@
<color name="wifi_divider">#ffe0e0e0</color>
<color name="sim_noitification">@*android:color/material_deep_teal_500</color>
<color name="warning">#ff5621</color>
<color name="confirm_device_credential_dark_background">#263238</color>
</resources>

View File

@@ -238,4 +238,5 @@
<dimen name="fingerprint_ring_radius">96dip</dimen>
<dimen name="fingerprint_ring_thickness">4dip</dimen>
<dimen name="confirm_credentials_security_method_margin">48dp</dimen>
</resources>

View File

@@ -835,12 +835,6 @@
<string name="crypt_keeper_dialog_need_password_message">You need to set a lock screen PIN or
password before you can start encryption.</string>
<!-- String at bottom of screen when prompting for pattern.
Note: This is only for the pattern case. -->
<string name="crypt_keeper_confirm_encrypt">
You need to draw your unlock pattern to confirm encrypting your device.
</string>
<!-- Title of the final confirmation screen before starting device encryption -->
<string name="crypt_keeper_confirm_title">Encrypt?</string>
<!-- Warning text in the final confirmation screen before starting device encryption -->
@@ -2430,8 +2424,6 @@
<string name="reset_network_final_desc">Reset all network settings? You can\'t reverse this action!</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Reset settings button -->
<string name="reset_network_final_button_text">Reset settings</string>
<!-- Explanation of drawing unlock pattern to reset settings -->
<string name="reset_network_gesture_explanation">You need to draw your unlock pattern to confirm a network settings reset.</string>
<!-- Reset settings confirmation screen title [CHAR LIMIT=30] -->
<string name="reset_network_confirm_title">Reset?</string>
<!-- Reset settings complete toast text [CHAR LIMIT=75] -->
@@ -2472,8 +2464,6 @@
<string name="master_clear_final_desc">Erase all your personal information and downloaded apps? You can\'t reverse this action!</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Reset phone button -->
<string name="master_clear_final_button_text">Erase everything</string>
<!-- Explanation of drawing unlock pattern to reset phone -->
<string name="master_clear_gesture_explanation">You need to draw your unlock pattern to confirm a factory data reset.</string>
<!-- Master clear failed message -->
<string name="master_clear_failed">No reset was performed because the System Clear service isn\'t available.</string>
<!-- Master clear confirmation screen title [CHAR LIMIT=30] -->
@@ -2508,10 +2498,6 @@
<string name="media_format_final_desc" product="default">Erase the SD card, deleting all files stored there? You can\'t reverse this action!</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Format media button -->
<string name="media_format_final_button_text">Erase everything</string>
<!-- Explanation of drawing unlock pattern to format card [CHAR LIMIT=NONE] -->
<string name="media_format_gesture_explanation" product="nosdcard">You need to draw your unlock pattern to confirm that you want to erase the USB storage.</string>
<!-- Explanation of drawing unlock pattern to format card [CHAR LIMIT=NONE] -->
<string name="media_format_gesture_explanation" product="default">You need to draw your unlock pattern to confirm that you want to erase the SD card.</string>
<!-- Main settings screen, Call settings title for item to go into the call settings -->
<string name="call_settings_title">Call settings</string>
@@ -2764,6 +2750,26 @@
<!-- Toast shown if setting pattern was successful -->
<string name="lockpassword_pattern_set_toast">Pattern has been set</string>
<!-- Message to be used to explain the user that he needs to enter his pattern to continue a
particular operation. [CHAR LIMIT=70]-->
<string name="lockpassword_confirm_your_pattern_generic">Use your device pattern to continue.</string>
<!-- Message to be used to explain the user that he needs to enter his PIN to continue a
particular operation. [CHAR LIMIT=70]-->
<string name="lockpassword_confirm_your_pin_generic">Enter your device PIN to continue.</string>
<!-- Message to be used to explain the user that he needs to enter his password to continue a
particular operation. [CHAR LIMIT=70]-->
<string name="lockpassword_confirm_your_password_generic">Enter your device password to continue.</string>
<!-- Security & location settings screen, change security method screen instruction if user
enters incorrect PIN [CHAR LIMIT=30] -->
<string name="lockpassword_invalid_pin">Wrong PIN</string>
<!-- Security & location settings screen, change security method screen instruction if user
enters incorrect password [CHAR LIMIT=30] -->
<string name="lockpassword_invalid_password">Wrong password</string>
<!-- Security & location settings screen, change unlock pattern screen instruction if user
draws incorrect pattern [CHAR LIMIT=30] -->
<string name="lockpattern_need_to_unlock_wrong">Wrong pattern</string>
<!-- Lock Pattern settings -->
<!-- Security & location settings screen, header -->
<string name="lock_settings_title">Device security</string>
@@ -2771,14 +2777,6 @@
<string name="lockpattern_change_lock_pattern_label">Change unlock pattern</string>
<!-- Security & location settings screen, change unlock pattern screen instruction when the user chooses "Change unlock pattern". We first ask the user toe nter the current pattern, and this is the message seen -->
<string name="lockpattern_change_lock_pin_label">Change unlock PIN</string>
<!-- Security & location settings screen, change unlock pattern screen instruction when the user chooses "Change unlock pattern". We first ask the user toe nter the current pattern, and this is the message seen -->
<string name="lockpattern_need_to_unlock">Confirm saved pattern</string>
<!-- Do not translate. -->
<string name="lockpattern_need_to_unlock_footer" />
<!-- Security & location settings screen, change unlock pattern screen instruction if user draws incorrect pattern -->
<string name="lockpattern_need_to_unlock_wrong">Try again:</string>
<!-- Do not translate. -->
<string name="lockpattern_need_to_unlock_wrong_footer" />
<!-- Security & location settings screen, change unlock pattern screen instruction on top of screen. This si when they are supposed to draw a new unlock pattern (for example, if they are changing their unlock patterns)..-->
<string name="lockpattern_recording_intro_header">Draw an unlock pattern</string>
<!-- Security & location settings screen, change unlock pattern screen hint on bottom of screen. We are telling them to press the menu button to see more options or help. -->
@@ -2820,10 +2818,9 @@
<string name="lockpattern_settings_change_lock_pattern">Change unlock pattern</string>
<!-- Security & location settings screen, the help instructions (an animation) caption -->
<string name="lockpattern_settings_help_how_to_record">How to draw an unlock pattern</string>
<!-- Security & location settings screen, change unlock pattern screen instruction on top of screen after too many incorrect attempts -->
<string name="lockpattern_too_many_failed_confirmation_attempts_header">Too many incorrect attempts!</string>
<!-- Security & location settings screen, change unlock pattern screen countdown hint on bottom of screen after too many incorrect attempts -->
<string name="lockpattern_too_many_failed_confirmation_attempts_footer">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string>
<!-- Security & location settings screen, confirm unlock pattern screen hint at the bottom after
too many incorrect attempts [CHAR LIMIT=120]-->
<string name="lockpattern_too_many_failed_confirmation_attempts">Too many incorrect attempts. Try again in <xliff:g id="number">%d</xliff:g> seconds.</string>
<!-- Displayed when user launches a widget configuration activity that was uninstalled -->
<string name="activity_not_found">Application is not installed on your phone.</string>
@@ -3410,10 +3407,6 @@
<string name="oem_unlock_enable">OEM unlocking</string>
<!-- setting Checkbox summary whether to enable OEM unlock [CHAR_LIMIT=50] -->
<string name="oem_unlock_enable_summary">Allow the bootloader to be unlocked</string>
<!-- Message to enter device PIN to enable OEM unlock -->
<string name="oem_unlock_enable_pin_prompt">Enter your PIN</string>
<!-- Explanation to enter device pin to enable OEM unlock -->
<string name="oem_unlock_enable_pin_description">Enter your device PIN to enable OEM unlock</string>
<!-- Confirmation dialog title to ensure user wishes to enable OEM unlock and disable theft protection features -->
<string name="confirm_enable_oem_unlock_title">Allow OEM unlocking?</string>
<!-- Warning dialog message to confirm user wishes to enable OEM unlock and disable theft protection features -->
@@ -4388,9 +4381,6 @@
<!-- Error message for users that aren't allowed to see or modify credentials [CHAR LIMIT=none] -->
<string name="credentials_settings_not_available">Credentials are not available for this user</string>
<!-- Explanation of drawing unlock pattern to install credentials -->
<string name="credentials_install_gesture_explanation">You need to draw your unlock pattern to confirm credential installation.</string>
<!-- Title of dialog to enable credential storage [CHAR LIMIT=30] -->
<string name="credentials_unlock"></string>
<!-- Description of dialog to enable credential storage [CHAR LIMIT=NONE] -->
@@ -6224,6 +6214,9 @@
<item quantity="other"><xliff:g id="count" example="10">%d</xliff:g> apps can open their domain URLs</item>
</plurals>
<!-- Fingerprint hint message when finger was not recognized.-->
<string name="fingerprint_not_recognized">Not recognized</string>
<!-- Title for Default Apps settings [CHAR LIMIT=30] -->
<string name="default_apps_title">Default Apps</string>

View File

@@ -78,7 +78,6 @@
<style name="TextAppearance.PasswordEntry" parent="android:TextAppearance.Material">
<item name="android:gravity">center</item>
<item name="android:singleLine">true</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
@@ -350,6 +349,11 @@
<item name="android:textColor">@color/fingerprint_message_color</item>
</style>
<style name="TextAppearance.ConfirmDeviceCredentialsErrorText"
parent="android:TextAppearance.Material.Caption">
<item name="android:textColor">@color/warning</item>
</style>
<style name="TextAppearance.Small.SwitchBar">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textStyle">normal</item>

View File

@@ -211,4 +211,24 @@
<item name="android:colorAccent">@color/switch_accent_color</item>
</style>
<style name="Theme.ConfirmDeviceCredentials" parent="Theme.SubSettings">
<item name="confirmDeviceCredentialsSideMargin">16dp</item>
<item name="confirmDeviceCredentialsTopMargin">16dp</item>
</style>
<style name="Theme.ConfirmDeviceCredentialsDark" parent="@android:style/Theme.Material">
<item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
<item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="preferenceBackgroundColor">@color/confirm_device_credential_dark_background</item>
<item name="confirmDeviceCredentialsSideMargin">32dp</item>
<item name="confirmDeviceCredentialsTopMargin">32dp</item>
<!-- LockPatternView colors -->
<item name="@*android:regularColor">@color/lock_pattern_view_regular_color_dark</item>
<item name="@*android:successColor">@color/lock_pattern_view_regular_color_dark</item>
<item name="@*android:errorColor">@color/lock_pattern_view_error_color</item>
</style>
</resources>

View File

@@ -145,7 +145,8 @@ public class ChooseLockGeneric extends SettingsActivity {
} else if (!mWaitingForConfirmation) {
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null)) {
if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
getString(R.string.unlock_set_unlock_launch_picker_title))) {
mPasswordConfirmed = true; // no password set, so no need to confirm
updatePreferencesOrFinish();
} else {

View File

@@ -243,7 +243,7 @@ public class ChooseLockPassword extends SettingsActivity {
updateStage(Stage.Introduction);
if (confirmCredentials) {
mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
null, null);
getString(R.string.unlock_set_unlock_launch_picker_title));
}
} else {
mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);

View File

@@ -379,7 +379,8 @@ public class ChooseLockPattern extends SettingsActivity {
updateStage(Stage.NeedToConfirm);
boolean launchedConfirmationActivity =
mChooseLockSettingsHelper.launchConfirmationActivity(
CONFIRM_EXISTING_REQUEST, null, null);
CONFIRM_EXISTING_REQUEST,
getString(R.string.unlock_set_unlock_launch_picker_title));
if (!launchedConfirmationActivity) {
updateStage(Stage.Introduction);
}

View File

@@ -16,13 +16,14 @@
package com.android.settings;
import com.android.internal.widget.LockPatternUtils;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import com.android.internal.widget.LockPatternUtils;
public final class ChooseLockSettingsHelper {
static final String EXTRA_KEY_TYPE = "type";
@@ -48,64 +49,77 @@ public final class ChooseLockSettingsHelper {
/**
* If a pattern, password or PIN exists, prompt the user before allowing them to change it.
* @param message optional message to display about the action about to be done
* @param details optional detail message to display
*
* @param title title of the confirmation screen; shown in the action bar
* @return true if one exists and we launched an activity to confirm it
* @see #onActivityResult(int, int, android.content.Intent)
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
boolean launchConfirmationActivity(int request, CharSequence message, CharSequence details) {
return launchConfirmationActivity(request, message, details, false);
boolean launchConfirmationActivity(int request, CharSequence title) {
return launchConfirmationActivity(request, title, null, null, false, false);
}
/**
* If a pattern, password or PIN exists, prompt the user before allowing them to change it.
* @param message optional message to display about the action about to be done
* @param details optional detail message to display
*
* @param title title of the confirmation screen; shown in the action bar
* @param returnCredentials if true, put credentials into intent. Note that if this is true,
this can only be called internally.
* this can only be called internally.
* @return true if one exists and we launched an activity to confirm it
* @see #onActivityResult(int, int, android.content.Intent)
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
boolean launchConfirmationActivity(int request, CharSequence message, CharSequence details,
boolean returnCredentials) {
boolean launchConfirmationActivity(int request, CharSequence title, boolean returnCredentials) {
return launchConfirmationActivity(request, title, null, null, returnCredentials, false);
}
/**
* If a pattern, password or PIN exists, prompt the user before allowing them to change it.
*
* @param title title of the confirmation screen; shown in the action bar
* @param header header of the confirmation screen; shown as large text
* @param description description of the confirmation screen
* @param returnCredentials if true, put credentials into intent. Note that if this is true,
* this can only be called internally.
* @param external specifies whether this activity is launched externally, meaning that it will
* get a dark theme and allow fingerprint authentication
* @return true if one exists and we launched an activity to confirm it
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external) {
boolean launched = false;
switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
launched = confirmPattern(request, message, details, returnCredentials);
launched = launchConfirmationActivity(request, title, header, description,
returnCredentials
? ConfirmLockPattern.InternalActivity.class
: ConfirmLockPattern.class, external);
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
// TODO: update UI layout for ConfirmPassword to show message and details
launched = confirmPassword(request, message, returnCredentials);
launched = launchConfirmationActivity(request, title, header, description,
returnCredentials
? ConfirmLockPassword.InternalActivity.class
: ConfirmLockPassword.class, external);
break;
}
return launched;
}
/**
* Launch screen to confirm the existing lock pattern.
* @param message shown in header of ConfirmLockPattern if not null
* @param details shown in footer of ConfirmLockPattern if not null
* @param returnCredentials if true, put credentials into intent.
* @see #onActivityResult(int, int, android.content.Intent)
* @return true if we launched an activity to confirm pattern
*/
private boolean confirmPattern(int request, CharSequence message,
CharSequence details, boolean returnCredentials) {
if (!mLockPatternUtils.isLockPatternEnabled()) {
return false;
}
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
CharSequence message, Class<?> activityClass, boolean external) {
final Intent intent = new Intent();
// supply header and footer text in the intent
intent.putExtra(ConfirmLockPattern.HEADER_TEXT, message);
intent.putExtra(ConfirmLockPattern.FOOTER_TEXT, details);
intent.setClassName("com.android.settings",
returnCredentials
? ConfirmLockPattern.InternalActivity.class.getName()
: ConfirmLockPattern.class.getName());
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT, message);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.ALLOW_FP_AUTHENTICATION, external);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, external);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_CANCEL_BUTTON, external);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
if (mFragment != null) {
mFragment.startActivityForResult(intent, request);
} else {
@@ -113,31 +127,4 @@ public final class ChooseLockSettingsHelper {
}
return true;
}
/**
* Launch screen to confirm the existing lock password.
* @param message shown in header of ConfirmLockPassword if not null
* @param returnCredentials if true, put credentials into intent.
* @see #onActivityResult(int, int, android.content.Intent)
* @return true if we launched an activity to confirm password
*/
private boolean confirmPassword(int request, CharSequence message,
boolean returnCredentials) {
if (!mLockPatternUtils.isLockPasswordEnabled()) return false;
final Intent intent = new Intent();
// supply header text in the intent
intent.putExtra(ConfirmLockPattern.HEADER_TEXT, message);
intent.setClassName("com.android.settings",
returnCredentials
? ConfirmLockPassword.InternalActivity.class.getName()
: ConfirmLockPassword.class.getName());
if (mFragment != null) {
mFragment.startActivityForResult(intent, request);
} else {
mActivity.startActivityForResult(intent, request);
}
return true;
}
}

View File

@@ -48,7 +48,8 @@ public class ConfirmDeviceCredentialActivity extends Activity {
String details = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
if (!helper.launchConfirmationActivity(0 /* request code */, title, details)) {
if (!helper.launchConfirmationActivity(0 /* request code */, null /* title */, title,
details, false /* returnCredentials */, true /* isExternal */)) {
Log.d(TAG, "No pattern, password or PIN set.");
setResult(Activity.RESULT_OK);
finish();

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2015 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
*/
package com.android.settings;
import android.app.KeyguardManager;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.WindowManager;
public class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {
@Override
protected void onCreate(Bundle savedState) {
if (getIntent().getBooleanExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, false)) {
setTheme(R.style.Theme_ConfirmDeviceCredentialsDark);
}
super.onCreate(savedState);
boolean deviceLocked = getSystemService(KeyguardManager.class).isKeyguardLocked();
if (deviceLocked && getIntent().getBooleanExtra(
ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, false)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
CharSequence msg = getIntent().getStringExtra(
ConfirmDeviceCredentialBaseFragment.TITLE_TEXT);
setTitle(msg);
if (getActionBar() != null) {
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2015 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
*/
package com.android.settings;
import android.annotation.Nullable;
import android.app.Fragment;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Base fragment to be shared for PIN/Pattern/Password confirmation fragments.
*/
public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment
implements FingerprintUiHelper.Callback {
public static final String PACKAGE = "com.android.settings";
public static final String TITLE_TEXT = PACKAGE + ".ConfirmCredentials.title";
public static final String HEADER_TEXT = PACKAGE + ".ConfirmCredentials.header";
public static final String DETAILS_TEXT = PACKAGE + ".ConfirmCredentials.details";
public static final String ALLOW_FP_AUTHENTICATION =
PACKAGE + ".ConfirmCredentials.allowFpAuthentication";
public static final String DARK_THEME = PACKAGE + ".ConfirmCredentials.darkTheme";
public static final String SHOW_CANCEL_BUTTON =
PACKAGE + ".ConfirmCredentials.showCancelButton";
public static final String SHOW_WHEN_LOCKED =
PACKAGE + ".ConfirmCredentials.showWhenLocked";
private FingerprintUiHelper mFingerprintHelper;
private boolean mAllowFpAuthentication;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAllowFpAuthentication = getActivity().getIntent().getBooleanExtra(
ALLOW_FP_AUTHENTICATION, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mFingerprintHelper = new FingerprintUiHelper(
(ImageView) view.findViewById(R.id.fingerprintIcon),
(TextView) view.findViewById(R.id.errorText), this);
boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
SHOW_CANCEL_BUTTON, false);
Button cancelButton = (Button) view.findViewById(R.id.cancelButton);
cancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
}
@Override
public void onResume() {
super.onResume();
if (mAllowFpAuthentication) {
mFingerprintHelper.startListening();
}
}
@Override
public void onPause() {
super.onPause();
if (mAllowFpAuthentication) {
mFingerprintHelper.stopListening();
}
}
@Override
public void onAuthenticated() {
// Check whether we are still active.
if (getActivity() != null && getActivity().isResumed()) {
authenticationSucceeded(null /* password */);
}
}
protected abstract void authenticationSucceeded(@Nullable String password);
@Override
public void onFingerprintIconVisibilityChanged(boolean visible) {
}
}

View File

@@ -16,14 +16,11 @@
package com.android.settings;
import android.annotation.Nullable;
import android.text.TextUtils;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternUtils;
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;
@@ -31,23 +28,18 @@ import android.os.CountDownTimer;
import android.os.Handler;
import android.os.SystemClock;
import android.os.storage.StorageManager;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
public class ConfirmLockPassword extends SettingsActivity {
public static final String PACKAGE = "com.android.settings";
public static final String HEADER_TEXT = PACKAGE + ".ConfirmLockPattern.header";
public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
public static class InternalActivity extends ConfirmLockPassword {
}
@@ -65,28 +57,17 @@ public class ConfirmLockPassword extends SettingsActivity {
return false;
}
@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);
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_confirm_your_password_header);
setTitle(msg);
}
public static class ConfirmLockPasswordFragment extends InstrumentedFragment
implements OnClickListener, OnEditorActionListener, TextWatcher {
public static class ConfirmLockPasswordFragment extends ConfirmDeviceCredentialBaseFragment
implements OnClickListener, OnEditorActionListener {
private static final String KEY_NUM_WRONG_CONFIRM_ATTEMPTS
= "confirm_lock_password_fragment.key_num_wrong_confirm_attempts";
private static final long ERROR_MESSAGE_TIMEOUT = 3000;
private TextView mPasswordEntry;
private LockPatternUtils mLockPatternUtils;
private TextView mHeaderText;
private TextView mHeaderTextView;
private TextView mDetailsTextView;
private TextView mErrorTextView;
private Handler mHandler = new Handler();
private PasswordEntryKeyboardHelper mKeyboardHelper;
private PasswordEntryKeyboardView mKeyboardView;
private Button mContinueButton;
private int mNumWrongConfirmAttempts;
private CountDownTimer mCountdownTimer;
private boolean mIsAlpha;
@@ -111,51 +92,35 @@ public class ConfirmLockPassword extends SettingsActivity {
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);
mContinueButton = (Button) view.findViewById(R.id.next_button);
mContinueButton.setOnClickListener(this);
mContinueButton.setEnabled(false); // disable until the user enters at least one char
mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.addTextChangedListener(this);
mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
mHeaderText = (TextView) view.findViewById(R.id.headerText);
mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
mErrorTextView = (TextView) view.findViewById(R.id.errorText);
mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
|| DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
|| DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality;
Intent intent = getActivity().getIntent();
if (intent != null) {
CharSequence headerMessage = intent.getCharSequenceExtra(HEADER_TEXT);
CharSequence headerMessage = intent.getCharSequenceExtra(
ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
CharSequence detailsMessage = intent.getCharSequenceExtra(
ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
if (TextUtils.isEmpty(headerMessage)) {
headerMessage = getString(getDefaultHeader());
}
mHeaderText.setText(headerMessage);
if (TextUtils.isEmpty(detailsMessage)) {
detailsMessage = getString(getDefaultDetails());
}
mHeaderTextView.setText(headerMessage);
mDetailsTextView.setText(detailsMessage);
}
final Activity activity = getActivity();
mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
mKeyboardView, mPasswordEntry);
mKeyboardHelper.setKeyboardMode(mIsAlpha ?
PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
: PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
mKeyboardView.requestFocus();
int currentType = mPasswordEntry.getInputType();
mPasswordEntry.setInputType(mIsAlpha ? currentType
: (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
if (activity instanceof SettingsActivity) {
final SettingsActivity sa = (SettingsActivity) activity;
int id = getDefaultHeader();
CharSequence title = getText(id);
sa.setTitle(title);
}
return view;
}
@@ -164,10 +129,19 @@ public class ConfirmLockPassword extends SettingsActivity {
: R.string.lockpassword_confirm_your_pin_header;
}
private int getDefaultDetails() {
return mIsAlpha ? R.string.lockpassword_confirm_your_password_generic
: R.string.lockpassword_confirm_your_pin_generic;
}
private int getErrorMessage() {
return mIsAlpha ? R.string.lockpassword_invalid_password
: R.string.lockpassword_invalid_pin;
}
@Override
public void onPause() {
super.onPause();
mKeyboardView.requestFocus();
if (mCountdownTimer != null) {
mCountdownTimer.cancel();
mCountdownTimer = null;
@@ -181,9 +155,7 @@ public class ConfirmLockPassword extends SettingsActivity {
@Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
mKeyboardView.requestFocus();
long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
if (deadline != 0) {
handleAttemptLockout(deadline);
@@ -196,33 +168,35 @@ public class ConfirmLockPassword extends SettingsActivity {
outState.putInt(KEY_NUM_WRONG_CONFIRM_ATTEMPTS, mNumWrongConfirmAttempts);
}
private void handleNext() {
final String pin = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(pin)) {
@Override
protected void authenticationSucceeded(@Nullable String password) {
Intent intent = new Intent();
if (getActivity() instanceof ConfirmLockPassword.InternalActivity) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
: StorageManager.CRYPT_TYPE_PIN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
}
getActivity().setResult(RESULT_OK, intent);
getActivity().finish();
}
private void handleNext() {
final String pin = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(pin)) {
authenticationSucceeded(pin);
} else {
if (++mNumWrongConfirmAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
handleAttemptLockout(deadline);
} else {
showError(R.string.lockpattern_need_to_unlock_wrong);
showError(getErrorMessage());
}
}
}
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
long elapsedRealtime = SystemClock.elapsedRealtime();
showError(R.string.lockpattern_too_many_failed_confirmation_attempts_header, 0);
mPasswordEntry.setEnabled(false);
mCountdownTimer = new CountDownTimer(
elapsedRealtimeDeadline - elapsedRealtime,
@@ -231,15 +205,15 @@ public class ConfirmLockPassword extends SettingsActivity {
@Override
public void onTick(long millisUntilFinished) {
final int secondsCountdown = (int) (millisUntilFinished / 1000);
mHeaderText.setText(getString(
R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
secondsCountdown));
showError(getString(
R.string.lockpattern_too_many_failed_confirmation_attempts,
secondsCountdown), 0);
}
@Override
public void onFinish() {
mPasswordEntry.setEnabled(true);
mHeaderText.setText(getDefaultHeader());
mErrorTextView.setText("");
mNumWrongConfirmAttempts = 0;
}
}.start();
@@ -264,13 +238,13 @@ public class ConfirmLockPassword extends SettingsActivity {
private final Runnable mResetErrorRunnable = new Runnable() {
public void run() {
mHeaderText.setText(getDefaultHeader());
mErrorTextView.setText("");
}
};
private void showError(int msg, long timeout) {
mHeaderText.setText(msg);
mHeaderText.announceForAccessibility(mHeaderText.getText());
private void showError(CharSequence msg, long timeout) {
mErrorTextView.setText(msg);
mErrorTextView.announceForAccessibility(mErrorTextView.getText());
mPasswordEntry.setText(null);
mHandler.removeCallbacks(mResetErrorRunnable);
if (timeout != 0) {
@@ -278,6 +252,10 @@ public class ConfirmLockPassword extends SettingsActivity {
}
}
private void showError(int msg, long timeout) {
showError(getText(msg), timeout);
}
// {@link OnEditorActionListener} methods.
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter or "done" key
@@ -289,16 +267,5 @@ public class ConfirmLockPassword extends SettingsActivity {
}
return false;
}
// {@link TextWatcher} methods.
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void afterTextChanged(Editable s) {
mContinueButton.setEnabled(mPasswordEntry.getText().length() > 0);
}
}
}

View File

@@ -22,13 +22,14 @@ import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
import com.android.internal.widget.LockPatternView.Cell;
import android.annotation.Nullable;
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.os.storage.StorageManager;
import android.view.MenuItem;
import android.widget.TextView;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,36 +43,17 @@ import java.util.List;
* Sets an activity result of {@link Activity#RESULT_OK} when the user
* successfully confirmed their pattern.
*/
public class ConfirmLockPattern extends SettingsActivity {
public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
public static class InternalActivity extends ConfirmLockPattern {
}
/**
* Names of {@link CharSequence} fields within the originating {@link Intent}
* that are used to configure the keyguard confirmation view's labeling.
* The view will use the system-defined resource strings for any labels that
* the caller does not supply.
*/
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,
NeedToUnlockWrong,
LockedOut
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_confirm_your_pattern_header);
setTitle(msg);
}
@Override
public Intent getIntent() {
Intent modIntent = new Intent(super.getIntent());
@@ -85,7 +67,7 @@ public class ConfirmLockPattern extends SettingsActivity {
return false;
}
public static class ConfirmLockPatternFragment extends InstrumentedFragment {
public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment {
// how long we wait to clear a wrong pattern
private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
@@ -98,13 +80,14 @@ public class ConfirmLockPattern extends SettingsActivity {
private CountDownTimer mCountdownTimer;
private TextView mHeaderTextView;
private TextView mFooterTextView;
private TextView mDetailsTextView;
private TextView mErrorTextView;
private View mLeftSpacerLandscape;
private View mRightSpacerLandscape;
// caller-supplied text for various prompts
private CharSequence mHeaderText;
private CharSequence mFooterText;
private CharSequence mHeaderWrongText;
private CharSequence mFooterWrongText;
private CharSequence mDetailsText;
// required constructor for fragments
public ConfirmLockPatternFragment() {
@@ -123,7 +106,10 @@ public class ConfirmLockPattern extends SettingsActivity {
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);
mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
mErrorTextView = (TextView) view.findViewById(R.id.errorText);
mLeftSpacerLandscape = view.findViewById(R.id.leftSpacer);
mRightSpacerLandscape = view.findViewById(R.id.rightSpacer);
// make it so unhandled touch events within the unlock screen go to the
// lock pattern view.
@@ -133,10 +119,10 @@ public class ConfirmLockPattern extends SettingsActivity {
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);
mHeaderText = intent.getCharSequenceExtra(
ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
mDetailsText = intent.getCharSequenceExtra(
ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
}
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
@@ -199,28 +185,21 @@ public class ConfirmLockPattern extends SettingsActivity {
if (mHeaderText != null) {
mHeaderTextView.setText(mHeaderText);
} else {
mHeaderTextView.setText(R.string.lockpattern_need_to_unlock);
mHeaderTextView.setText(R.string.lockpassword_confirm_your_pattern_header);
}
if (mFooterText != null) {
mFooterTextView.setText(mFooterText);
if (mDetailsText != null) {
mDetailsTextView.setText(mDetailsText);
} else {
mFooterTextView.setText(R.string.lockpattern_need_to_unlock_footer);
mDetailsTextView.setText(
R.string.lockpassword_confirm_your_pattern_generic);
}
mErrorTextView.setText("");
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);
}
mErrorTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
mLockPatternView.setEnabled(true);
@@ -252,6 +231,28 @@ public class ConfirmLockPattern extends SettingsActivity {
mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
}
@Override
protected void authenticationSucceeded(@Nullable String password) {
Intent intent = new Intent();
if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
StorageManager.CRYPT_TYPE_PATTERN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
}
getActivity().setResult(Activity.RESULT_OK, intent);
getActivity().finish();
}
@Override
public void onFingerprintIconVisibilityChanged(boolean visible) {
if (mLeftSpacerLandscape != null && mRightSpacerLandscape != null) {
// In landscape, adjust spacing depending on fingerprint icon visibility.
mLeftSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
mRightSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
}
}
/**
* The pattern listener that responds according to a user confirming
* an existing lock pattern.
@@ -273,17 +274,7 @@ public class ConfirmLockPattern extends SettingsActivity {
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
if (mLockPatternUtils.checkPattern(pattern)) {
Intent intent = new Intent();
if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
StorageManager.CRYPT_TYPE_PATTERN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
LockPatternUtils.patternToString(pattern));
}
getActivity().setResult(Activity.RESULT_OK, intent);
getActivity().finish();
authenticationSucceeded(LockPatternUtils.patternToString(pattern));
} else {
if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL &&
++mNumWrongConfirmAttempts
@@ -308,10 +299,9 @@ public class ConfirmLockPattern extends SettingsActivity {
@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,
mErrorTextView.setText(getString(
R.string.lockpattern_too_many_failed_confirmation_attempts,
secondsCountdown));
}

View File

@@ -439,9 +439,8 @@ public final class CredentialStorage extends Activity {
private boolean confirmKeyGuard() {
Resources res = getResources();
boolean launched = new ChooseLockSettingsHelper(this)
.launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST, null,
res.getText(R.string.credentials_install_gesture_explanation),
true);
.launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST,
res.getText(R.string.credentials_title), true);
return launched;
}

View File

@@ -166,9 +166,8 @@ public class CryptKeeperSettings extends InstrumentedFragment {
return true;
}
return helper.launchConfirmationActivity(request, null,
res.getText(R.string.crypt_keeper_confirm_encrypt),
true);
return helper.launchConfirmationActivity(request,
res.getText(R.string.crypt_keeper_encrypt_title), true);
}
@Override

View File

@@ -1610,10 +1610,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
}
private boolean showKeyguardConfirmation(Resources resources, int requestCode) {
return new ChooseLockSettingsHelper(getActivity(), this)
.launchConfirmationActivity(requestCode,
resources.getString(R.string.oem_unlock_enable_pin_prompt),
resources.getString(R.string.oem_unlock_enable_pin_description));
return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
requestCode, resources.getString(R.string.oem_unlock_enable));
}
@Override

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2015 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
*/
package com.android.settings;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.os.Vibrator;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Small helper class to manage text/icon around fingerprint authentication UI.
*/
public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
private static final long ERROR_TIMEOUT = 1300;
private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};
private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};
private ImageView mIcon;
private TextView mErrorTextView;
private CancellationSignal mCancellationSignal;
private Callback mCallback;
private FingerprintManager mFingerprintManager;
public FingerprintUiHelper(ImageView icon, TextView errorTextView, Callback callback) {
mFingerprintManager = icon.getContext().getSystemService(FingerprintManager.class);
mIcon = icon;
mErrorTextView = errorTextView;
mCallback = callback;
}
public void startListening() {
if (mFingerprintManager.getEnrolledFingerprints().size() > 0) {
mCancellationSignal = new CancellationSignal();
mFingerprintManager.authenticate(null, mCancellationSignal, this, 0 /* flags */);
setFingerprintIconVisibility(true);
mIcon.setImageResource(R.drawable.ic_fingerprint);
}
}
public void stopListening() {
mCancellationSignal.cancel();
mCancellationSignal = null;
}
private void setFingerprintIconVisibility(boolean visible) {
mIcon.setVisibility(visible ? View.VISIBLE : View.GONE);
mCallback.onFingerprintIconVisibilityChanged(visible);
}
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
showError(errString);
setFingerprintIconVisibility(false);
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
showError(helpString);
}
@Override
public void onAuthenticationFailed() {
showError(mIcon.getResources().getString(
R.string.fingerprint_not_recognized));
}
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
vibrateFingerprintSuccess();
mCallback.onAuthenticated();
}
private void showError(CharSequence error) {
vibrateFingerprintError();
mIcon.setImageResource(R.drawable.ic_fingerprint_error);
mErrorTextView.setText(error);
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT);
}
private void vibrateFingerprintError() {
mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_ERROR_VIBRATE_PATTERN, -1);
}
private void vibrateFingerprintSuccess() {
mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);
}
private Runnable mResetErrorTextRunnable = new Runnable() {
@Override
public void run() {
mErrorTextView.setText("");
mIcon.setImageResource(R.drawable.ic_fingerprint);
}
};
public interface Callback {
void onAuthenticated();
void onFingerprintIconVisibilityChanged(boolean visible);
}
}

View File

@@ -75,8 +75,8 @@ public class MasterClear extends InstrumentedFragment {
*/
private boolean runKeyguardConfirmation(int request) {
Resources res = getActivity().getResources();
return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(request,
null, res.getText(R.string.master_clear_gesture_explanation));
return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
request, res.getText(R.string.master_clear_title));
}
@Override

View File

@@ -72,9 +72,8 @@ public class MediaFormat extends Activity {
* component as a subactivity
*/
private boolean runKeyguardConfirmation(int request) {
return new ChooseLockSettingsHelper(this)
.launchConfirmationActivity(request, null,
getText(R.string.media_format_gesture_explanation));
return new ChooseLockSettingsHelper(this).launchConfirmationActivity(request,
getText(R.string.media_format_title));
}
@Override

View File

@@ -78,8 +78,8 @@ public class ResetNetwork extends InstrumentedFragment {
*/
private boolean runKeyguardConfirmation(int request) {
Resources res = getActivity().getResources();
return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(request,
null, res.getText(R.string.reset_network_gesture_explanation));
return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
request, res.getText(R.string.reset_network_title));
}
@Override

View File

@@ -603,8 +603,9 @@ public class SecuritySettings extends SettingsPreferenceFragment
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
mTrustAgentClickIntent = preference.getIntent();
if (!helper.launchConfirmationActivity(CHANGE_TRUST_AGENT_SETTINGS, null, null) &&
mTrustAgentClickIntent != null) {
boolean confirmationLaunched = helper.launchConfirmationActivity(
CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
if (!confirmationLaunched&& mTrustAgentClickIntent != null) {
// If this returns false, it means no password confirmation is required.
startActivity(mTrustAgentClickIntent);
mTrustAgentClickIntent = null;