Merge "Import translations. DO NOT MERGE" into qt-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 202335e..8e4d6a4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1588,6 +1588,10 @@
android:exported="false"
android:screenOrientation="portrait"/>
+ <activity android:name=".biometrics.face.FaceEnrollEducation"
+ android:exported="false"
+ android:screenOrientation="portrait"/>
+
<activity android:name=".biometrics.face.FaceEnrollEnrolling"
android:exported="false"
android:screenOrientation="portrait"/>
diff --git a/res/drawable/ic_arrow_back.xml b/res/drawable/ic_arrow_back.xml
index 374f16b..b6a80cf 100644
--- a/res/drawable/ic_arrow_back.xml
+++ b/res/drawable/ic_arrow_back.xml
@@ -18,6 +18,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
+ android:autoMirrored="true"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
diff --git a/res/drawable/ic_face_enroll_introduction_people.xml b/res/drawable/ic_face_enroll_introduction_people.xml
new file mode 100644
index 0000000..b452efe
--- /dev/null
+++ b/res/drawable/ic_face_enroll_introduction_people.xml
@@ -0,0 +1,42 @@
+<!--
+ ~ Copyright (C) 2019 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
+ -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:tint="?android:attr/colorControlNormal">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_0_G">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M15 8 C15,6.58 14.5,5.27 13.67,4.24 C14.09,4.1 14.53,4 15,4 C17.21,4 19,5.79 19,8 C19,10.21 17.21,12 15,12 C14.57,12 14.16,11.91 13.77,11.79 C13.74,11.78 13.71,11.77 13.67,11.76 C14.5,10.73 15,9.42 15,8c M16.66 13.13 C18.03,14.06 19,15.32 19,17 C19,17 19,20 19,20 C19,20 23,20 23,20 C23,20 23,17 23,17 C23,14.82 19.42,13.53 16.66,13.13c M9 6 C7.9,6 7,6.9 7,8 C7,9.1 7.9,10 9,10 C10.1,10 11,9.1 11,8 C11,6.9 10.1,6 9,6c M9 15 C6.3,15 3.2,16.29 3,17.01 C3,17.01 3,18 3,18 C3,18 15,18 15,18 C15,18 15,17 15,17 C14.8,16.29 11.7,15 9,15c M9 4 C11.21,4 13,5.79 13,8 C13,10.21 11.21,12 9,12 C6.79,12 5,10.21 5,8 C5,5.79 6.79,4 9,4c M9 13 C11.67,13 17,14.34 17,17 C17,17 17,20 17,20 C17,20 1,20 1,20 C1,20 1,17 1,17 C1,14.34 6.33,13 9,13c "/>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="2000"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/res/drawable/ic_face_enroll_introduction_shield.xml b/res/drawable/ic_face_enroll_introduction_shield.xml
new file mode 100644
index 0000000..09d3909
--- /dev/null
+++ b/res/drawable/ic_face_enroll_introduction_shield.xml
@@ -0,0 +1,45 @@
+<!--
+ ~ Copyright (C) 2019 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
+ -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:tint="?android:attr/colorControlNormal">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_0_G">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12 2 C12,2 3.82,5.64 3.82,5.64 C3.82,5.64 3.82,11.09 3.82,11.09 C3.82,16.14 7.31,20.85 12,22 C16.69,20.85 20.18,16.14 20.18,11.09 C20.18,11.09 20.18,5.64 20.18,5.64 C20.18,5.64 12,2 12,2c M18.18 11.09 C18.18,12.64 17.77,14.14 17.08,15.47 C15.77,14.5 13.4,14 12,14 C10.6,14 8.23,14.5 6.92,15.47 C6.23,14.14 5.82,12.64 5.82,11.09 C5.82,11.09 5.82,6.94 5.82,6.94 C5.82,6.94 12,4.19 12,4.19 C12,4.19 18.18,6.94 18.18,6.94 C18.18,6.94 18.18,11.09 18.18,11.09c "/>
+ <path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12 7.5 C13.66,7.5 15,8.84 15,10.5 C15,12.16 13.66,13.5 12,13.5 C10.34,13.5 9,12.16 9,10.5 C9,8.84 10.34,7.5 12,7.5c "/>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="2000"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/res/drawable/ic_face_enroll_introduction_visibility.xml b/res/drawable/ic_face_enroll_introduction_visibility.xml
new file mode 100644
index 0000000..04ff21f
--- /dev/null
+++ b/res/drawable/ic_face_enroll_introduction_visibility.xml
@@ -0,0 +1,45 @@
+<!--
+ ~ Copyright (C) 2019 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
+ -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:tint="?android:attr/colorControlNormal">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_0_G">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12 7 C9.52,7 7.5,9.02 7.5,11.5 C7.5,13.98 9.52,16 12,16 C14.48,16 16.5,13.98 16.5,11.5 C16.5,9.02 14.48,7 12,7c M12 14.2 C10.51,14.2 9.3,12.99 9.3,11.5 C9.3,10.01 10.51,8.8 12,8.8 C13.49,8.8 14.7,10.01 14.7,11.5 C14.7,12.99 13.49,14.2 12,14.2c "/>
+ <path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M12 4 C7,4 2.73,7.11 1,11.5 C2.73,15.89 7,19 12,19 C17,19 21.27,15.89 23,11.5 C21.27,7.11 17,4 12,4c M12 17 C8.21,17 4.83,14.87 3.18,11.5 C4.83,8.13 8.21,6 12,6 C15.79,6 19.17,8.13 20.82,11.5 C19.17,14.87 15.79,17 12,17c "/>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="2000"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/res/drawable/ic_pan_tool_18dp.xml b/res/drawable/ic_pan_tool_18dp.xml
new file mode 100644
index 0000000..3ebfc9c
--- /dev/null
+++ b/res/drawable/ic_pan_tool_18dp.xml
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="18dp"
+ android:height="18dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <group>
+ <clip-path android:pathData="M0,0h48v48H0z M 0,0"/>
+ <path
+ android:pathData="M46,11v29c0,4.4 -3.6,8 -8,8H23.4c-2.16,0 -4.2,-0.86 -5.7,-2.38L2,29.66s2.52,-2.46 2.6,-2.5c0.44,-0.38 0.98,-0.58 1.58,-0.58 0.44,0 0.84,0.12 1.2,0.32 0.08,0.02 8.62,4.92 8.62,4.92V8c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v14h2V3c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v19h2V5c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v17h2V11c0,-1.66 1.34,-3 3,-3s3,1.34 3,3z"
+ android:fillColor="#757575"/>
+ </group>
+</vector>
diff --git a/res/drawable/ic_visibility_18dp.xml b/res/drawable/ic_visibility_18dp.xml
new file mode 100644
index 0000000..9e27815c
--- /dev/null
+++ b/res/drawable/ic_visibility_18dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="18dp"
+ android:height="18dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:pathData="M24,9C14,9 5.46,15.22 2,24c3.46,8.78 12,15 22,15 10.01,0 18.54,-6.22 22,-15 -3.46,-8.78 -11.99,-15 -22,-15zM24,34c-5.52,0 -10,-4.48 -10,-10s4.48,-10 10,-10 10,4.48 10,10 -4.48,10 -10,10zM24,18c-3.31,0 -6,2.69 -6,6s2.69,6 6,6 6,-2.69 6,-6 -2.69,-6 -6,-6z"
+ android:fillColor="#757575"/>
+</vector>
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
index 887d0fb..51c8c96 100644
--- a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -61,6 +61,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginEnd="24dp"
android:textAlignment="center"
android:textColor="?android:attr/colorError"
android:visibility="invisible"/>
diff --git a/res/layout/disable_accessibility_service_dialog_content.xml b/res/layout/disable_accessibility_service_dialog_content.xml
new file mode 100644
index 0000000..e365484
--- /dev/null
+++ b/res/layout/disable_accessibility_service_dialog_content.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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
+ -->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:textDirection="locale"
+ android:scrollbarStyle="outsideOverlay"
+ android:gravity="top">
+
+ <LinearLayout
+ android:theme="@style/Theme.AlertDialog"
+ style="@style/AccessibilityDialog">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingTop="32dp"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp">
+
+ <TextView
+ android:id="@+id/permissionDialog_disable_title"
+ style="@style/AccessibilityDialogTitle" />
+
+ <TextView
+ android:id="@+id/permissionDialog_disable_message"
+ android:gravity="center"
+ android:text="@string/accessibility_service_warning_description"
+ style="@style/AccessibilityDialogDescription" />
+
+ </LinearLayout>
+ <!-- Buttons on bottom of dialog -->
+ <LinearLayout
+ style="@style/AccessibilityDialogButtonList">
+
+ <Space
+ style="@style/AccessibilityDialogButtonBarSpace"/>
+
+ <Button
+ android:id="@+id/permission_disable_stop_button"
+ android:text="@string/accessibility_dialog_button_stop"
+ style="@style/AccessibilityDialogButtonAllow" />
+
+ <Button
+ android:id="@+id/permission_disable_cancel_button"
+ android:text="@string/accessibility_dialog_button_cancel"
+ style="@style/AccessibilityDialogButtonDeny" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/res/layout/enable_accessibility_service_dialog_content.xml b/res/layout/enable_accessibility_service_dialog_content.xml
index e16dc65..066c339 100644
--- a/res/layout/enable_accessibility_service_dialog_content.xml
+++ b/res/layout/enable_accessibility_service_dialog_content.xml
@@ -23,28 +23,118 @@
android:gravity="top">
<LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingStart="16dip"
- android:paddingEnd="16dip">
+ android:theme="@style/Theme.AlertDialog"
+ style="@style/AccessibilityDialog">
- <TextView
- android:id="@+id/encryption_warning"
- android:layout_width="fill_parent"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="10dip"
- android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp">
- <TextView
- android:id="@+id/accessibility_service_warning"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="10dip"
- android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
+ <ImageView
+ android:id="@+id/permissionDialog_icon"
+ style="@style/AccessibilityDialogServiceIcon" />
+ <TextView
+ android:id="@+id/permissionDialog_title"
+ style="@style/AccessibilityDialogTitle" />
+
+ <TextView
+ android:id="@+id/encryption_warning"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dip"
+ android:textAlignment="viewStart"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+ <TextView
+ android:id="@+id/permissionDialog_description"
+ android:text="@string/accessibility_service_warning_description"
+ style="@style/AccessibilityDialogDescription" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginBottom="24dp" >
+
+ <ImageView
+ android:id="@+id/controlScreen_icon"
+ android:src="@drawable/ic_visibility_18dp"
+ style="@style/AccessibilityDialogIcon" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/controlScreen_title"
+ android:text="@string/accessibility_service_screen_control_title"
+ style="@style/AccessibilityDialogPermissionTitle" />
+
+ <TextView
+ android:id="@+id/controlScreen_description"
+ android:text="@string/accessibility_service_screen_control_description"
+ style="@style/AccessibilityDialogPermissionDescription" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginBottom="24dp" >
+
+ <ImageView
+ android:id="@+id/performAction_icon"
+ android:src="@drawable/ic_pan_tool_18dp"
+ style="@style/AccessibilityDialogIcon" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/performAction_title"
+ android:text="@string/accessibility_service_action_perform_title"
+ style="@style/AccessibilityDialogPermissionTitle" />
+
+ <TextView
+ android:id="@+id/performAction_description"
+ android:text="@string/accessibility_service_action_perform_description"
+ style="@style/AccessibilityDialogPermissionDescription" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <!-- Buttons on bottom of dialog -->
+ <LinearLayout
+ style="@style/AccessibilityDialogButtonList">
+
+ <Space
+ style="@style/AccessibilityDialogButtonBarSpace"/>
+
+ <Button
+ android:id="@+id/permission_enable_allow_button"
+ android:text="@string/accessibility_dialog_button_allow"
+ style="@style/AccessibilityDialogButtonAllow" />
+
+ <Button
+ android:id="@+id/permission_enable_deny_button"
+ android:text="@string/accessibility_dialog_button_deny"
+ style="@style/AccessibilityDialogButtonDeny" />
+
+ </LinearLayout>
</LinearLayout>
</ScrollView>
diff --git a/res/layout/face_enroll_education.xml b/res/layout/face_enroll_education.xml
new file mode 100644
index 0000000..c41c724
--- /dev/null
+++ b/res/layout/face_enroll_education.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.google.android.setupdesign.GlifLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:FaceEnrollAccessibilitySwitch="http://schemas.android.com/apk/res/com.android.settings"
+ style="?attr/face_layout_theme"
+ android:id="@+id/setup_wizard_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ style="@style/SudContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <com.google.android.setupdesign.view.RichTextView
+ android:id="@+id/sud_layout_description"
+ style="@style/SudDescription.Glif"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="center"
+ android:text="@string/security_settings_face_enroll_education_message"/>
+
+ <com.google.android.setupdesign.view.RichTextView
+ android:id="@+id/error_text"
+ style="@style/SudDescription.Glif"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginVertical="48dp">
+
+ <com.google.android.setupdesign.view.IllustrationVideoView
+ android:id="@+id/illustration_normal"
+ style="@style/SudContentIllustration"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:sudVideo="@raw/face_education"/>
+
+ <ImageView
+ android:id="@+id/illustration_accessibility"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:visibility="invisible"
+ android:background="@drawable/face_enroll_introduction"/>
+
+ </FrameLayout>
+
+ <!-- Contains the buttons and extra information text at the bottom -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center_horizontal|bottom">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/accessibility_button"
+ style="@style/SudGlifButton.Secondary"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_face_enroll_introduction_accessibility"/>
+
+ <com.android.settings.biometrics.face.FaceEnrollAccessibilityToggle
+ android:id="@+id/toggle_diversity"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ FaceEnrollAccessibilitySwitch:messageText="@string/security_settings_face_enroll_introduction_accessibility_diversity"/>
+
+ </FrameLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index 3115bb4..535a531 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2018 The Android Open Source Project
+ ~ Copyright (C) 2019 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.
@@ -37,13 +37,13 @@
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/security_settings_face_enroll_introduction_message" />
+ android:text="@string/security_settings_face_enroll_introduction_message"/>
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/error_text"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"/>
<FrameLayout
android:layout_width="match_parent"
@@ -52,18 +52,10 @@
<com.google.android.setupdesign.view.IllustrationVideoView
android:id="@+id/illustration_normal"
- style="@style/SudContentIllustration"
- android:layout_width="240dp"
- android:layout_height="240dp"
- app:sudVideo="@raw/face_enroll_introduction_animation" />
-
- <ImageView
- android:id="@+id/illustration_accessibility"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:visibility="invisible"
- android:background="@drawable/face_enroll_introduction" />
+ style="@style/SudContentIllustration"
+ app:sudVideo="@raw/face_enroll_introduction_animation"/>
</FrameLayout>
@@ -74,29 +66,7 @@
android:orientation="vertical"
android:layout_gravity="center_horizontal|bottom">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <Button
- android:id="@+id/accessibility_button"
- style="@style/SudGlifButton.Secondary"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/security_settings_face_enroll_introduction_accessibility" />
-
- <com.android.settings.biometrics.face.FaceEnrollAccessibilityToggle
- android:id="@+id/toggle_diversity"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- FaceEnrollAccessibilitySwitch:messageText="@string/security_settings_face_enroll_introduction_accessibility_diversity"/>
-
- </FrameLayout>
-
<LinearLayout
- android:id="@+id/footer_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@@ -107,15 +77,61 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@drawable/ic_face_enroll_introduction_detail">
+ android:background="@drawable/ic_face_enroll_introduction_shield">
</ImageView>
<Space
android:layout_width="8dp"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/security_settings_face_enroll_introduction_footer_message"/>
+ android:text="@string/security_settings_face_enroll_introduction_footer_part_1"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingTop="24dp">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/ic_face_enroll_introduction_visibility">
+ </ImageView>
+ <Space
+ android:layout_width="8dp"
+ android:layout_height="wrap_content"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_face_enroll_introduction_footer_part_2"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingTop="24dp">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/ic_face_enroll_introduction_people">
+ </ImageView>
+ <Space
+ android:layout_width="8dp"
+ android:layout_height="wrap_content"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_face_enroll_introduction_footer_part_3"/>
</LinearLayout>
</LinearLayout>
diff --git a/res/layout/manage_applications_apps_unsupported.xml b/res/layout/manage_applications_apps_unsupported.xml
index d7c6726..0c3a0a2 100644
--- a/res/layout/manage_applications_apps_unsupported.xml
+++ b/res/layout/manage_applications_apps_unsupported.xml
@@ -29,6 +29,7 @@
<TextView
android:id="@+id/empty_header"
+ android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/disabled_feature"
@@ -36,6 +37,7 @@
<TextView
android:id="@+id/empty_body"
+ android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/disabled_feature_reason_slow_down_phone"
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 7f1954b..d6c4aef 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -56,13 +56,6 @@
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:background="@android:color/transparent"
- app:layout_scrollFlags="scroll|enterAlways"/>
-
<include layout="@layout/search_bar"/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 68ba277..9364071 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -64,6 +64,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginEnd="24dp"
android:textAlignment="center"
android:textColor="?android:attr/colorError"
android:visibility="invisible"/>
diff --git a/res/raw/face_education.mp4 b/res/raw/face_education.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/face_education.mp4
diff --git a/res/values/strings.xml b/res/values/strings.xml
index af94db3..1b24912 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -888,6 +888,12 @@
<string name="security_settings_face_preference_summary_none">Tap to set up face authentication</string>
<!-- Title shown for menu item that launches face settings or enrollment. [CHAR LIMIT=32] -->
<string name="security_settings_face_preference_title">Face authentication</string>
+ <!-- Introduction title shown in face enrollment education screen [CHAR LIMIT=40] -->
+ <string name="security_settings_face_enroll_education_title">How to set up Face unlock</string>
+ <!-- Introduction title shown in face enrollment education screen to show the face authentication feature, when face unlock is disabled by device admin [CHAR LIMIT=40] -->
+ <string name="security_settings_face_enroll_education_title_unlock_disabled">Use your face to authenticate</string>
+ <!-- Introduction detail message shown in face education [CHAR LIMIT=NONE] -->
+ <string name="security_settings_face_enroll_education_message"></string>
<!-- Button shown which shows accessibility toggles for face enrollment when clicked. [CHAR LIMIT=32] -->
<string name="security_settings_face_enroll_introduction_accessibility">Use accessibility setup</string>
<!-- Additional details shown when the accessibility toggle is expanded. [CHAR LIMIT=NONE]-->
@@ -908,8 +914,12 @@
<string name="security_settings_face_enroll_introduction_message_unlock_disabled">Use your face to unlock your phone or approve purchases.\n\nNote: You can\u2019t use your face to unlock this device. For more information, contact your organization\u2019s admin.</string>
<!-- Introduction detail message shown in face enrollment screen in setup wizard. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_introduction_message_setup">Use your face to unlock your phone, authorize purchases, or sign in to apps</string>
- <!-- Introduction detail message shown in face enrollment that provides extra detais. [CHAR LIMIT=NONE] -->
- <string name="security_settings_face_enroll_introduction_footer_message"></string>
+ <!-- Introduction message shown in face enrollment that provides extra detail. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_face_enroll_introduction_footer_part_1"></string>
+ <!-- Introduction message shown in face enrollment that provides extra detail. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_face_enroll_introduction_footer_part_2"></string>
+ <!-- Introduction message shown in face enrollment that provides extra detail. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_face_enroll_introduction_footer_part_3"></string>
<!-- Title shown in face enrollment dialog [CHAR LIMIT=40] -->
<string name="security_settings_face_enroll_repeat_title">Center your face in the circle</string>
<!-- Button text to skip enrollment of face [CHAR LIMIT=40] -->
@@ -2895,7 +2905,7 @@
<string name="wallpaper_settings_fragment_title">Choose wallpaper from</string>
<!-- Styles and Wallpaper settings title [CHAR_LIMIT=46] -->
<string name="style_suggestion_title">Customize your Pixel</string>
- <!-- Styles and Wallpapers summary [CHAR_LIMIT=55] -->
+ <!-- Styles and Wallpapers summary [CHAR_LIMIT=70] -->
<string name="style_suggestion_summary">Try different styles, wallpapers, clocks, and more</string>
<!-- Display settings screen, trigger for screen saver options -->
<string name="screensaver_settings_title">Screen saver</string>
@@ -5070,8 +5080,9 @@
<!-- Title for a warning about security implications of enabling an accessibility
service. [CHAR LIMIT=NONE] -->
- <string name="enable_service_title">Use
- <xliff:g id="service" example="TalkBack">%1$s</xliff:g>?</string>
+ <string name="enable_service_title">Allow
+ <xliff:g id="service" example="TalkBack">%1$s</xliff:g> to have full contol of your
+ device?</string>
<!-- Title for the list of capabilities of an accessibility service. -->
<string name="capabilities_list_title"><xliff:g id="service" example="TalkBack">%1$s</xliff:g>
needs to:</string>
@@ -5112,11 +5123,43 @@
This level of control is not appropriate for most apps.
</string>
+ <!-- Warning description that explains that it's appropriate for accessibility
+ services to have full control to help users with accessibility needs. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_service_warning_description">Full control is appropriate for apps
+ that help you with accessibility needs, but not for most apps.
+ </string>
+
+ <!-- Title for the screen control in accessibility dialog. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_service_screen_control_title">View and control screen</string>
+
+ <!-- Description for the screen control in accessibility dialog. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_service_screen_control_description">It can read all content on the
+ screen and display content over other apps.
+ </string>
+
+ <!-- Title for the action perform in accessibility dialog. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_service_action_perform_title">View and platform actions</string>
+
+ <!-- Description for the action perform in accessibility dialog. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_service_action_perform_description">It can track your interactions
+ with an app or a hardware sensor, and interact with apps on your behalf.
+ </string>
+
+ <!-- String for the allow button in accessibility permission dialog. [CHAR LIMIT=10] -->
+ <string name="accessibility_dialog_button_allow">Allow</string>
+ <!-- String for the deny button in accessibility permission dialog. [CHAR LIMIT=10] -->
+ <string name="accessibility_dialog_button_deny">Deny</string>
+
+ <!-- String for the allow button in accessibility permission dialog. [CHAR LIMIT=10] -->
+ <string name="accessibility_dialog_button_stop">Stop</string>
+ <!-- String for the deny button in accessibility permission dialog. [CHAR LIMIT=10] -->
+ <string name="accessibility_dialog_button_cancel">Cancel</string>
+
<!-- Title for a warning about disabling an accessibility service. [CHAR LIMIT=NONE] -->
<string name="disable_service_title">Stop <xliff:g id="service" example="TalkBack">%1$s</xliff:g>?</string>
<!-- Message for a warning about disabling accessibility service. [CHAR LIMIT=NONE] -->
- <string name="disable_service_message">Tapping OK will
- stop <xliff:g id="service" example="TalkBack">%1$s</xliff:g>.</string>
+ <string name="disable_service_message">Tapping <xliff:g id="stop" example="Stop">%1$s</xliff:g> will
+ stop <xliff:g id="service" example="TalkBack">%2$s</xliff:g>.</string>
<!-- Title for the prompt shown as a placeholder if no accessibility services are installed. [CHAR LIMIT=50] -->
<string name="accessibility_no_services_installed">No services installed</string>
@@ -10500,9 +10543,9 @@
<!-- Note displayed when certain features are not available on low ram devices. [CHAR LIMIT=NONE] -->
<string name="disabled_low_ram_device">This feature is not available on this device</string>
<!-- Note displayed when certain features are not available. [CHAR LIMIT=NONE] -->
- <string name="disabled_feature">This feature is not available</string>
+ <string name="disabled_feature">Feature not available</string>
<!-- Note displayed to explain that a feature is not available because it will slow down the phone. [CHAR LIMIT=NONE] -->
- <string name="disabled_feature_reason_slow_down_phone">It will slow down this phone</string>
+ <string name="disabled_feature_reason_slow_down_phone">This feature has been turned off because it slows down your phone</string>
<!-- UI debug setting: preference title - enforce full raw GNSS satellite measurements [CHAR LIMIT=60] -->
<string name="enable_gnss_raw_meas_full_tracking">Force full GNSS measurements</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3662fac..d3d3199 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -566,4 +566,94 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
+ <style name="AccessibilityDialog">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">vertical</item>
+ <item name="android:divider">@*android:drawable/list_divider_material</item>
+ <item name="android:showDividers">middle</item>
+ </style>
+
+ <style name="AccessibilityDialogServiceIcon">
+ <item name="android:layout_width">36dp</item>
+ <item name="android:layout_height">36dp</item>
+ <item name="android:layout_marginTop">16dp</item>
+ <item name="android:layout_marginBottom">16dp</item>
+ <item name="android:scaleType">fitCenter</item>
+ </style>
+
+ <style name="AccessibilityDialogIcon">
+ <item name="android:layout_width">18dp</item>
+ <item name="android:layout_height">18dp</item>
+ <item name="android:layout_marginRight">12dp</item>
+ <item name="android:scaleType">fitCenter</item>
+ </style>
+
+ <style name="AccessibilityDialogTitle"
+ parent="@android:style/TextAppearance.DeviceDefault">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">center</item>
+ <item name="android:textSize">20sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:fontFamily">google-sans-medium</item>
+ </style>
+
+ <style name="AccessibilityDialogDescription"
+ parent="@android:style/TextAppearance.DeviceDefault">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginTop">16dp</item>
+ <item name="android:layout_marginBottom">32dp</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:fontFamily">sans-serif</item>
+ </style>
+
+ <style name="AccessibilityDialogPermissionTitle"
+ parent="@android:style/TextAppearance.DeviceDefault">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:fontFamily">sans-serif</item>
+ </style>
+
+ <style name="AccessibilityDialogPermissionDescription"
+ parent="@android:style/TextAppearance.DeviceDefault">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:fontFamily">sans-serif</item>
+ </style>
+
+ <style name="AccessibilityDialogButtonBarSpace">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">0dp</item>
+ <item name="android:visibility">gone</item>
+ </style>
+
+ <style name="AccessibilityDialogButtonList">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">vertical</item>
+ <item name="android:divider">@*android:drawable/list_divider_material</item>
+ <item name="android:showDividers">middle</item>
+ </style>
+
+ <style name="AccessibilityDialogButton"
+ parent="@*android:style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">56dp</item>
+ <item name="android:paddingLeft">8dp</item>
+ <item name="android:paddingRight">8dp</item>
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ </style>
+
+ <style name="AccessibilityDialogButtonAllow"
+ parent="@style/AccessibilityDialogButton"></style>
+ <style name="AccessibilityDialogButtonDeny"
+ parent="@style/AccessibilityDialogButton"></style>
+
</resources>
diff --git a/res/xml/gentle_notification_settings.xml b/res/xml/gentle_notification_settings.xml
index 80061ba..56c3c40 100644
--- a/res/xml/gentle_notification_settings.xml
+++ b/res/xml/gentle_notification_settings.xml
@@ -24,6 +24,7 @@
android:title="@string/summary_placeholder"
android:layout="@layout/drawable_layout"
settings:controller="com.android.settings.notification.GentleDrawablePreferenceController"
+ android:selectable="false"
android:order="1"
settings:allowDividerBelow="true"
android:persistent="false" />
diff --git a/res/xml/privacy_settings.xml b/res/xml/privacy_settings.xml
index 57c3d5e..2e09dbd 100644
--- a/res/xml/privacy_settings.xml
+++ b/res/xml/privacy_settings.xml
@@ -50,7 +50,7 @@
<Preference
android:key="backup_inactive"
- android:title="@string/backup_inactive_title"
+ android:title="@string/disabled_by_administrator_summary"
android:enabled="false"
android:selectable="false"
settings:controller="com.android.settings.backup.BackupInactivePreferenceController" />
diff --git a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
index dec734c..40ac641 100644
--- a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
+++ b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
@@ -22,7 +22,7 @@
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
-import android.content.DialogInterface;
+import android.graphics.drawable.Drawable;
import android.os.storage.StorageManager;
import android.text.BidiFormatter;
import android.view.LayoutInflater;
@@ -30,10 +30,13 @@
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
+import androidx.core.content.ContextCompat;
import com.android.settings.R;
@@ -44,40 +47,45 @@
* accessibility service to access user data before the service is enabled
*/
public class AccessibilityServiceWarning {
- public static Dialog createCapabilitiesDialog(Activity parentActivity,
- AccessibilityServiceInfo info, DialogInterface.OnClickListener listener) {
- final AlertDialog ad = new AlertDialog.Builder(parentActivity)
- .setTitle(parentActivity.getString(R.string.enable_service_title,
- getServiceName(parentActivity, info)))
- .setView(createEnableDialogContentView(parentActivity, info))
- .setPositiveButton(android.R.string.ok, listener)
- .setNegativeButton(android.R.string.cancel, listener)
- .create();
-
- final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {
- // Filter obscured touches by consuming them.
- if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)
- || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
- if (event.getAction() == MotionEvent.ACTION_UP) {
- Toast.makeText(v.getContext(), R.string.touch_filtered_warning,
- Toast.LENGTH_SHORT).show();
- }
- return true;
+ private static final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {
+ // Filter obscured touches by consuming them.
+ if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)
+ || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ Toast.makeText(v.getContext(), R.string.touch_filtered_warning,
+ Toast.LENGTH_SHORT).show();
}
- return false;
- };
+ return true;
+ }
+ return false;
+ };
+
+ public static Dialog createCapabilitiesDialog(Activity parentActivity,
+ AccessibilityServiceInfo info, View.OnClickListener listener) {
+ final AlertDialog ad = new AlertDialog.Builder(parentActivity)
+ .setView(createEnableDialogContentView(parentActivity, info, listener))
+ .create();
Window window = ad.getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.privateFlags |= SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
window.setAttributes(params);
ad.create();
- ad.getButton(AlertDialog.BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);
ad.setCanceledOnTouchOutside(true);
return ad;
}
+ public static Dialog createDisableDialog(Activity parentActivity,
+ AccessibilityServiceInfo info, View.OnClickListener listener) {
+ final AlertDialog ad = new AlertDialog.Builder(parentActivity)
+ .setView(createDisableDialogContentView(parentActivity, info, listener))
+ .setCancelable(true)
+ .create();
+
+ return ad;
+ }
+
/**
* Return whether the device is encrypted with legacy full disk encryption. Newer devices
* should be using File Based Encryption.
@@ -96,7 +104,7 @@
* @return A content view suitable for viewing
*/
private static View createEnableDialogContentView(Context context,
- AccessibilityServiceInfo info) {
+ AccessibilityServiceInfo info, View.OnClickListener listener) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
@@ -114,9 +122,55 @@
encryptionWarningView.setVisibility(View.GONE);
}
- TextView serviceWarningTextView = content.findViewById(R.id.accessibility_service_warning);
- serviceWarningTextView.setText(context.getString(R.string.accessibility_service_warning,
- getServiceName(context, info)));
+ final Drawable icon;
+ if (info.getResolveInfo().getIconResource() == 0) {
+ icon = ContextCompat.getDrawable(context, R.drawable.ic_accessibility_generic);
+ } else {
+ icon = info.getResolveInfo().loadIcon(context.getPackageManager());
+ }
+
+ ImageView permissionDialogIcon = content.findViewById(
+ R.id.permissionDialog_icon);
+ permissionDialogIcon.setImageDrawable(icon);
+
+ TextView permissionDialogTitle = content.findViewById(R.id.permissionDialog_title);
+ permissionDialogTitle.setText(context.getString(R.string.enable_service_title,
+ getServiceName(context, info)));
+
+ Button permissionAllowButton = content.findViewById(
+ R.id.permission_enable_allow_button);
+ Button permissionDenyButton = content.findViewById(
+ R.id.permission_enable_deny_button);
+ permissionAllowButton.setOnClickListener(listener);
+ permissionAllowButton.setOnTouchListener(filterTouchListener);
+ permissionDenyButton.setOnClickListener(listener);
+
+ return content;
+ }
+
+ private static View createDisableDialogContentView(Context context,
+ AccessibilityServiceInfo info, View.OnClickListener listener) {
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+
+ View content = inflater.inflate(R.layout.disable_accessibility_service_dialog_content,
+ null);
+
+ TextView permissionDialogTitle = content.findViewById(R.id.permissionDialog_disable_title);
+ permissionDialogTitle.setText(context.getString(R.string.disable_service_title,
+ getServiceName(context, info)));
+ TextView permissionDialogMessage = content
+ .findViewById(R.id.permissionDialog_disable_message);
+ permissionDialogMessage.setText(context.getString(R.string.disable_service_message,
+ context.getString(R.string.accessibility_dialog_button_stop),
+ getServiceName(context, info)));
+
+ Button permissionAllowButton = content.findViewById(
+ R.id.permission_disable_stop_button);
+ Button permissionDenyButton = content.findViewById(
+ R.id.permission_disable_cancel_button);
+ permissionAllowButton.setOnClickListener(listener);
+ permissionDenyButton.setOnClickListener(listener);
return content;
}
diff --git a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java
index 2da4f7a..bb26283 100644
--- a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java
+++ b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java
@@ -37,6 +37,7 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityManager;
+import android.view.View;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
@@ -148,7 +149,7 @@
}
public static class ConfirmationDialogFragment extends InstrumentedDialogFragment
- implements DialogInterface.OnClickListener {
+ implements View.OnClickListener {
private static final String EXTRA_KEY = "extra_key";
private static final String TAG = "ConfirmationDialogFragment";
private IBinder mToken;
@@ -182,9 +183,10 @@
}
@Override
- public void onClick(DialogInterface dialog, int which) {
+ public void onClick(View view) {
final Fragment fragment = getTargetFragment();
- if ((which == BUTTON_POSITIVE) && (fragment instanceof ShortcutServicePickerFragment)) {
+ if ((view.getId() == R.id.permission_enable_allow_button)
+ && (fragment instanceof ShortcutServicePickerFragment)) {
final Bundle bundle = getArguments();
((ShortcutServicePickerFragment) fragment).onServiceConfirmed(
bundle.getString(EXTRA_KEY));
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index d935d92..b28d8b5 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -22,7 +22,6 @@
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
@@ -34,10 +33,9 @@
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
+import android.view.View;
import android.view.accessibility.AccessibilityManager;
-import androidx.appcompat.app.AlertDialog;
-
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
@@ -48,7 +46,7 @@
import java.util.List;
public class ToggleAccessibilityServicePreferenceFragment
- extends ToggleFeaturePreferenceFragment implements DialogInterface.OnClickListener {
+ extends ToggleFeaturePreferenceFragment implements View.OnClickListener {
private static final int DIALOG_ID_ENABLE_WARNING = 1;
private static final int DIALOG_ID_DISABLE_WARNING = 2;
@@ -67,7 +65,7 @@
private ComponentName mComponentName;
- private int mShownDialogId;
+ private Dialog mDialog;
@Override
public int getMetricsCategory() {
@@ -129,35 +127,28 @@
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case DIALOG_ID_ENABLE_WARNING: {
- mShownDialogId = DIALOG_ID_ENABLE_WARNING;
final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
if (info == null) {
return null;
}
-
- return AccessibilityServiceWarning
+ mDialog = AccessibilityServiceWarning
.createCapabilitiesDialog(getActivity(), info, this);
+ break;
}
case DIALOG_ID_DISABLE_WARNING: {
- mShownDialogId = DIALOG_ID_DISABLE_WARNING;
AccessibilityServiceInfo info = getAccessibilityServiceInfo();
if (info == null) {
return null;
}
- return new AlertDialog.Builder(getActivity())
- .setTitle(getString(R.string.disable_service_title,
- info.getResolveInfo().loadLabel(getPackageManager())))
- .setMessage(getString(R.string.disable_service_message,
- info.getResolveInfo().loadLabel(getPackageManager())))
- .setCancelable(true)
- .setPositiveButton(android.R.string.ok, this)
- .setNegativeButton(android.R.string.cancel, this)
- .create();
+ mDialog = AccessibilityServiceWarning
+ .createDisableDialog(getActivity(), info, this);
+ break;
}
default: {
throw new IllegalArgumentException();
}
}
+ return mDialog;
}
@Override
@@ -205,30 +196,31 @@
}
@Override
- public void onClick(DialogInterface dialog, int which) {
- final boolean checked;
- switch (which) {
- case DialogInterface.BUTTON_POSITIVE:
- if (mShownDialogId == DIALOG_ID_ENABLE_WARNING) {
- if (isFullDiskEncrypted()) {
- String title = createConfirmCredentialReasonMessage();
- Intent intent = ConfirmDeviceCredentialActivity.createIntent(title, null);
- startActivityForResult(intent,
- ACTIVITY_REQUEST_CONFIRM_CREDENTIAL_FOR_WEAKER_ENCRYPTION);
- } else {
- handleConfirmServiceEnabled(true);
- }
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.permission_enable_allow_button:
+ if (isFullDiskEncrypted()) {
+ String title = createConfirmCredentialReasonMessage();
+ Intent intent = ConfirmDeviceCredentialActivity.createIntent(title, null);
+ startActivityForResult(intent,
+ ACTIVITY_REQUEST_CONFIRM_CREDENTIAL_FOR_WEAKER_ENCRYPTION);
} else {
- handleConfirmServiceEnabled(false);
+ handleConfirmServiceEnabled(true);
}
break;
- case DialogInterface.BUTTON_NEGATIVE:
- checked = (mShownDialogId == DIALOG_ID_DISABLE_WARNING);
- handleConfirmServiceEnabled(checked);
+ case R.id.permission_enable_deny_button:
+ handleConfirmServiceEnabled(false);
+ break;
+ case R.id.permission_disable_stop_button:
+ handleConfirmServiceEnabled(false);
+ break;
+ case R.id.permission_disable_cancel_button:
+ handleConfirmServiceEnabled(true);
break;
default:
throw new IllegalArgumentException();
}
+ mDialog.dismiss();
}
private void handleConfirmServiceEnabled(boolean confirmed) {
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
new file mode 100644
index 0000000..9660f3b
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2018 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.biometrics.face;
+
+import static android.provider.Settings.Secure.FACE_UNLOCK_EDUCATION_INFO_DISPLAYED;
+import static android.security.KeyStore.getApplicationContext;
+
+import android.app.settings.SettingsEnums;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.face.FaceManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CompoundButton;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricEnrollBase;
+import com.android.settings.password.ChooseLockSettingsHelper;
+
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupcompat.util.WizardManagerHelper;
+import com.google.android.setupdesign.view.IllustrationVideoView;
+
+public class FaceEnrollEducation extends BiometricEnrollBase {
+
+ private static final String TAG = "FaceEducation";
+ private static final int ON = 1;
+ private static final int OFF = 0;
+ // 10 seconds.
+ private static final long FACE_ENROLL_EDUCATION_DELAY = 16000;
+
+ private FaceManager mFaceManager;
+ private FaceEnrollAccessibilityToggle mSwitchDiversity;
+
+ private IllustrationVideoView mIllustrationNormal;
+ private View mIllustrationAccessibility;
+ private Handler mHandler;
+
+ private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
+ new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ mIllustrationNormal.stop();
+ mIllustrationNormal.setVisibility(View.INVISIBLE);
+ mIllustrationAccessibility.setVisibility(View.VISIBLE);
+ } else {
+ mIllustrationNormal.setVisibility(View.VISIBLE);
+ mIllustrationNormal.start();
+ mIllustrationAccessibility.setVisibility(View.INVISIBLE);
+ }
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.face_enroll_education);
+ getLayout().setHeaderText(R.string.security_settings_face_enroll_education_title);
+ setTitle(R.string.security_settings_face_enroll_education_title);
+ mHandler = new Handler();
+
+ mFaceManager = Utils.getFaceManagerOrNull(this);
+ final Button accessibilityButton = findViewById(R.id.accessibility_button);
+ accessibilityButton.setOnClickListener(view -> {
+ mSwitchDiversity.setChecked(true);
+ accessibilityButton.setVisibility(View.GONE);
+ mSwitchDiversity.setVisibility(View.VISIBLE);
+ });
+
+ mSwitchDiversity = findViewById(R.id.toggle_diversity);
+ mSwitchDiversity.setListener(mSwitchDiversityListener);
+
+ mIllustrationNormal = findViewById(R.id.illustration_normal);
+ mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
+
+ mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_enrolling_skip)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.SKIP)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+
+ final FooterButton footerButton = new FooterButton.Builder(this)
+ .setText(R.string.wizard_next)
+ .setListener(this::onNextButtonClick)
+ .setButtonType(FooterButton.ButtonType.NEXT)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build();
+
+ mFooterBarMixin.setPrimaryButton(footerButton);
+ final Context context = getApplicationContext();
+ final boolean didDisplayEdu = Settings.Secure.getIntForUser(context.getContentResolver(),
+ FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, OFF, mUserId) == ON;
+ if (!didDisplayEdu) {
+ Settings.Secure.putIntForUser(context.getContentResolver(),
+ FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, ON, mUserId);
+ footerButton.setEnabled(false);
+ mHandler.postDelayed(() -> {
+ footerButton.setEnabled(true);
+ }, FACE_ENROLL_EDUCATION_DELAY);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
+ mSwitchDiversity.isChecked());
+ }
+
+ @Override
+ protected void onNextButtonClick(View view) {
+ final Intent intent = new Intent();
+ if (mToken != null) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
+ }
+ if (mUserId != UserHandle.USER_NULL) {
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ }
+ final String flattenedString = getString(R.string.config_face_enroll);
+ if (!TextUtils.isEmpty(flattenedString)) {
+ ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
+ intent.setComponent(componentName);
+ } else {
+ intent.setClass(this, FaceEnrollEnrolling.class);
+ }
+ intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
+ }
+
+ protected void onSkipButtonClick(View view) {
+ setResult(RESULT_SKIP);
+ finish();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
+ setResult(resultCode);
+ finish();
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.FACE_ENROLL_INTRO;
+ }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 6887d51..525c1a3 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -18,14 +18,9 @@
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
-import android.content.ComponentName;
import android.content.Intent;
import android.hardware.face.FaceManager;
import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.View;
-import android.widget.Button;
-import android.widget.CompoundButton;
import android.widget.TextView;
import com.android.settings.R;
@@ -38,51 +33,18 @@
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
-import com.google.android.setupdesign.view.IllustrationVideoView;
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceIntro";
private FaceManager mFaceManager;
- private FaceEnrollAccessibilityToggle mSwitchDiversity;
-
- private IllustrationVideoView mIllustrationNormal;
- private View mIllustrationAccessibility;
-
- private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
- new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (isChecked) {
- mIllustrationNormal.stop();
- mIllustrationNormal.setVisibility(View.INVISIBLE);
- mIllustrationAccessibility.setVisibility(View.VISIBLE);
- } else {
- mIllustrationNormal.setVisibility(View.VISIBLE);
- mIllustrationNormal.start();
- mIllustrationAccessibility.setVisibility(View.INVISIBLE);
- }
- }
- };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFaceManager = Utils.getFaceManagerOrNull(this);
- final Button accessibilityButton = findViewById(R.id.accessibility_button);
- accessibilityButton.setOnClickListener(view -> {
- mSwitchDiversity.setChecked(true);
- accessibilityButton.setVisibility(View.GONE);
- mSwitchDiversity.setVisibility(View.VISIBLE);
- });
-
- mSwitchDiversity = findViewById(R.id.toggle_diversity);
- mSwitchDiversity.setListener(mSwitchDiversityListener);
-
- mIllustrationNormal = findViewById(R.id.illustration_normal);
- mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
@@ -116,13 +78,6 @@
}
@Override
- protected void onResume() {
- super.onResume();
- mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
- mSwitchDiversity.isChecked());
- }
-
- @Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
this, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId) != null;
@@ -200,16 +155,7 @@
@Override
protected Intent getEnrollingIntent() {
- final String flattenedString = getString(R.string.config_face_enroll);
- final Intent intent = new Intent();
- if (!TextUtils.isEmpty(flattenedString)) {
- ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
- intent.setComponent(componentName);
-
- } else {
- intent.setClass(this, FaceEnrollEnrolling.class);
- }
- intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
+ Intent intent = new Intent(this, FaceEnrollEducation.class);
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
return intent;
}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
index 95f913e..c18ec78 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -19,6 +19,7 @@
import static android.content.Context.CARRIER_CONFIG_SERVICE;
import static android.content.Context.EUICC_SERVICE;
import static android.content.Context.TELEPHONY_SERVICE;
+import static android.content.Context.TELEPHONY_SUBSCRIPTION_SERVICE;
import android.Manifest;
import android.content.BroadcastReceiver;
@@ -36,6 +37,7 @@
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import android.text.BidiFormatter;
@@ -53,8 +55,6 @@
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
-import java.util.List;
-
public class SimStatusDialogController implements LifecycleObserver, OnResume, OnPause {
private final static String TAG = "SimStatusDialogCtrl";
@@ -98,9 +98,21 @@
"com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
private final static String CELL_BROADCAST_RECEIVER_APP = "com.android.cellbroadcastreceiver";
+ private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
+ new OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfo(
+ mSubscriptionInfo.getSubscriptionId());
+ updateNetworkProvider();
+ }
+ };
+
+ private SubscriptionInfo mSubscriptionInfo;
+
private final SimStatusDialogFragment mDialog;
- private final SubscriptionInfo mSubscriptionInfo;
private final TelephonyManager mTelephonyManager;
+ private final SubscriptionManager mSubscriptionManager;
private final CarrierConfigManager mCarrierConfigManager;
private final EuiccManager mEuiccManager;
private final Resources mRes;
@@ -134,11 +146,10 @@
mDialog = dialog;
mContext = dialog.getContext();
mSubscriptionInfo = getPhoneSubscriptionInfo(slotId);
- mTelephonyManager = (TelephonyManager) mContext.getSystemService(
- TELEPHONY_SERVICE);
- mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService(
- CARRIER_CONFIG_SERVICE);
- mEuiccManager = (EuiccManager) mContext.getSystemService(EUICC_SERVICE);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+ mEuiccManager = mContext.getSystemService(EuiccManager.class);
+ mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
mRes = mContext.getResources();
@@ -155,9 +166,9 @@
}
mPhoneStateListener = getPhoneStateListener();
+ updateNetworkProvider();
final ServiceState serviceState = getCurrentServiceState();
- updateNetworkProvider(serviceState);
updatePhoneNumber();
updateLatestAreaInfo();
updateServiceState(serviceState);
@@ -179,6 +190,7 @@
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_SERVICE_STATE);
+ mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
if (mShowLatestAreaInfo) {
mContext.registerReceiver(mAreaInfoReceiver,
@@ -198,6 +210,7 @@
return;
}
+ mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId())
.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
@@ -206,8 +219,10 @@
}
}
- private void updateNetworkProvider(ServiceState serviceState) {
- mDialog.setText(NETWORK_PROVIDER_VALUE_ID, serviceState.getOperatorAlphaLong());
+ private void updateNetworkProvider() {
+ final CharSequence carrierName =
+ mSubscriptionInfo != null ? mSubscriptionInfo.getCarrierName() : null;
+ mDialog.setText(NETWORK_PROVIDER_VALUE_ID, carrierName);
}
private void updatePhoneNumber() {
@@ -441,7 +456,7 @@
@Override
public void onServiceStateChanged(ServiceState serviceState) {
- updateNetworkProvider(serviceState);
+ updateNetworkProvider();
updateServiceState(serviceState);
updateRoamingStatus(serviceState);
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
index a936e99..5442e7d 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
@@ -99,10 +99,15 @@
}
}
+ /**
+ * Adds the seekbar to the end of the provided preference screen
+ *
+ * @param screen The preference screen to add the seekbar to
+ */
public void addToScreen(PreferenceScreen screen) {
// makes sure it gets added after the preferences if called due to first time battery
// saver message
- mSeekBarPreference.setOrder(5);
+ mSeekBarPreference.setOrder(100);
screen.addPreference(mSeekBarPreference);
}
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
index 6553c60..31ee278 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
@@ -64,6 +64,7 @@
final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
+ getPreferenceScreen().removeAll();
updateCandidates();
}
};
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index dee5d62..96f8bc3 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -90,10 +90,13 @@
final List<MediaDevice> devices = getMediaDevices();
final MediaDevice connectedDevice = getWorker().getCurrentConnectedMediaDevice();
- listBuilder.addRow(getActiveDeviceHeaderRow(connectedDevice));
+ if (connectedDevice != null) {
+ listBuilder.addRow(getActiveDeviceHeaderRow(connectedDevice));
+ }
for (MediaDevice device : devices) {
- if (!TextUtils.equals(connectedDevice.getId(), device.getId())) {
+ if (connectedDevice == null
+ || !TextUtils.equals(connectedDevice.getId(), device.getId())) {
listBuilder.addRow(getMediaDeviceRow(device));
}
}
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index 2df16f5..c06b78b 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -30,6 +30,7 @@
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
+import com.android.settings.R;
import com.android.settings.network.MobileDataContentObserver;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -120,7 +121,13 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- preference.setEnabled(!isOpportunistic());
+ if (isOpportunistic()) {
+ preference.setEnabled(false);
+ preference.setSummary(R.string.mobile_data_settings_summary_auto_switch);
+ } else {
+ preference.setEnabled(true);
+ preference.setSummary(R.string.mobile_data_settings_summary);
+ }
}
private boolean isOpportunistic() {
diff --git a/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
index 1456c2d..809bfbd 100644
--- a/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
+++ b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
@@ -19,23 +19,36 @@
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
+import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.dashboard.profileselector.UserAdapter;
import com.android.settings.utils.ContentCaptureUtils;
-import com.android.settings.widget.MasterSwitchPreference;
+
+import java.util.ArrayList;
+import java.util.List;
public final class EnableContentCaptureWithServiceSettingsPreferenceController
extends TogglePreferenceController {
private static final String TAG = "ContentCaptureController";
+ private final UserManager mUserManager;
+
public EnableContentCaptureWithServiceSettingsPreferenceController(@NonNull Context context,
@NonNull String key) {
super(context, key);
+
+ mUserManager = UserManager.get(context);
}
@Override
@@ -61,6 +74,11 @@
Log.w(TAG, "No component name for custom service settings");
preference.setSelectable(false);
}
+
+ preference.setOnPreferenceClickListener((pref) -> {
+ ProfileSelectDialog.show(mContext, pref);
+ return true;
+ });
}
@Override
@@ -69,4 +87,28 @@
&& ContentCaptureUtils.getServiceSettingsComponentName() != null;
return available ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
+
+ private static final class ProfileSelectDialog {
+ public static void show(Context context, Preference pref) {
+ final UserManager userManager = UserManager.get(context);
+ final List<UserInfo> userInfos = userManager.getUsers();
+ final ArrayList<UserHandle> userHandles = new ArrayList<>(userInfos.size());
+ for (UserInfo info: userInfos) {
+ userHandles.add(info.getUserHandle());
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ UserAdapter adapter = UserAdapter.createUserAdapter(userManager, context, userHandles);
+ builder.setTitle(com.android.settingslib.R.string.choose_profile)
+ .setAdapter(adapter, (DialogInterface dialog, int which) -> {
+ final UserHandle user = userHandles.get(which);
+ // Show menu on top level items.
+ final Intent intent = pref.getIntent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startActivityAsUser(intent, user);
+ })
+ .show();
+ }
+ }
+
}
diff --git a/src/com/android/settings/security/ScreenPinningSettings.java b/src/com/android/settings/security/ScreenPinningSettings.java
index 22223fd..c60fd47 100644
--- a/src/com/android/settings/security/ScreenPinningSettings.java
+++ b/src/com/android/settings/security/ScreenPinningSettings.java
@@ -117,9 +117,13 @@
}
private boolean isScreenLockUsed() {
- int def = getCurrentSecurityTitle() != R.string.screen_pinning_unlock_none ? 1 : 0;
- return Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, def) != 0;
+ // This functionality should be kept consistent with
+ // com.android.server.wm.LockTaskController (see b/127605586)
+ int defaultValueIfSettingNull = mLockPatternUtils.isSecure(UserHandle.myUserId()) ? 1 : 0;
+ return Settings.Secure.getInt(
+ getContentResolver(),
+ Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
+ defaultValueIfSettingNull) != 0;
}
private boolean setScreenLockUsed(boolean isEnabled) {
diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java
index 14abd1b..7a8ab83 100644
--- a/src/com/android/settings/slices/SliceDataConverter.java
+++ b/src/com/android/settings/slices/SliceDataConverter.java
@@ -25,6 +25,7 @@
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_UNAVAILABLE_SLICE_SUBTITLE;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -52,6 +53,7 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.DatabaseIndexingUtils;
import com.android.settings.search.Indexable.SearchIndexProvider;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -76,10 +78,12 @@
private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";
+ private final MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
public SliceDataConverter(Context context) {
mContext = context;
+ mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
/**
@@ -151,6 +155,7 @@
XmlResourceParser parser = null;
final List<SliceData> xmlSliceData = new ArrayList<>();
+ String controllerClassName = "";
try {
parser = mContext.getResources().getXml(xmlResId);
@@ -188,7 +193,7 @@
for (Bundle bundle : metadata) {
// TODO (b/67996923) Non-controller Slices should become intent-only slices.
// Note that without a controller, dynamic summaries are impossible.
- final String controllerClassName = bundle.getString(METADATA_CONTROLLER);
+ controllerClassName = bundle.getString(METADATA_CONTROLLER);
if (TextUtils.isEmpty(controllerClassName)) {
continue;
}
@@ -226,12 +231,25 @@
}
} catch (SliceData.InvalidSliceDataException e) {
Log.w(TAG, "Invalid data when building SliceData for " + fragmentName, e);
- } catch (XmlPullParserException e) {
- Log.w(TAG, "XML Error parsing PreferenceScreen: ", e);
- } catch (IOException e) {
- Log.w(TAG, "IO Error parsing PreferenceScreen: ", e);
- } catch (Resources.NotFoundException e) {
- Log.w(TAG, "Resource not found error parsing PreferenceScreen: ", e);
+ mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+ SettingsEnums.ACTION_VERIFY_SLICE_ERROR_INVALID_DATA,
+ SettingsEnums.PAGE_UNKNOWN,
+ controllerClassName,
+ 1);
+ } catch (XmlPullParserException | IOException | Resources.NotFoundException e) {
+ Log.w(TAG, "Error parsing PreferenceScreen: ", e);
+ mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+ SettingsEnums.ACTION_VERIFY_SLICE_PARSING_ERROR,
+ SettingsEnums.PAGE_UNKNOWN,
+ fragmentName,
+ 1);
+ } catch (Exception e) {
+ Log.w(TAG, "Get slice data from XML failed ", e);
+ mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+ SettingsEnums.ACTION_VERIFY_SLICE_OTHER_EXCEPTION,
+ SettingsEnums.PAGE_UNKNOWN,
+ fragmentName + "_" + controllerClassName,
+ 1);
} finally {
if (parser != null) parser.close();
}
diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
index dfcc131..f8743d1 100644
--- a/src/com/android/settings/widget/SwitchBar.java
+++ b/src/com/android/settings/widget/SwitchBar.java
@@ -21,7 +21,6 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.TypedArray;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -112,8 +111,6 @@
// Set the whole SwitchBar focusable and clickable.
setFocusable(true);
setClickable(true);
- // Set a onClickListener to handle the functionality of ToggleSwitch.
- setOnClickListener((View v) -> getDelegatingView().performClick());
final TypedArray a = context.obtainStyledAttributes(attrs, XML_ATTRIBUTES);
final int switchBarMarginStart = (int) a.getDimension(0, 0);
@@ -170,6 +167,12 @@
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
+ // Override the performClick method to eliminate redundant click.
+ @Override
+ public boolean performClick() {
+ return getDelegatingView().performClick();
+ }
+
public void setMetricsTag(String tag) {
mMetricsTag = tag;
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index 7308741..5dfcc25 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -323,15 +323,10 @@
@Override
public boolean onNavigateUp() {
- Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
- if (fragment instanceof WifiDppQrCodeGeneratorFragment) {
+ if (!mFragmentManager.popBackStackImmediate()) {
finish();
- return true;
- } else if (fragment instanceof WifiDppQrCodeScannerFragment) {
- mFragmentManager.popBackStackImmediate();
}
-
- return false;
+ return true;
}
@Override
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
index 5a4a809..76c444e 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
@@ -63,6 +63,7 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
@@ -103,6 +104,8 @@
private PersistableBundle mPersistableBundle;
@Mock
private EuiccManager mEuiccManager;
+ @Mock
+ private SubscriptionManager mSubscriptionManager;
private SimStatusDialogController mController;
private Context mContext;
@@ -123,6 +126,7 @@
doReturn(mPhoneStateListener).when(mController).getPhoneStateListener();
doReturn("").when(mController).getPhoneNumber();
doReturn(mSignalStrength).when(mController).getSignalStrength();
+ doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
when(mEuiccManager.isEnabled()).thenReturn(true);
when(mEuiccManager.getEid()).thenReturn("");
@@ -130,6 +134,7 @@
ReflectionHelpers.setField(mController, "mCarrierConfigManager", mCarrierConfigManager);
ReflectionHelpers.setField(mController, "mSubscriptionInfo", mSubscriptionInfo);
ReflectionHelpers.setField(mController, "mEuiccManager", mEuiccManager);
+ ReflectionHelpers.setField(mController, "mSubscriptionManager", mSubscriptionManager);
when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mPersistableBundle);
final ShadowPackageManager shadowPackageManager =
@@ -141,8 +146,8 @@
@Test
public void initialize_updateNetworkProviderWithFoobarCarrier_shouldUpdateCarrierWithFoobar() {
- final String carrierName = "foobar";
- when(mServiceState.getOperatorAlphaLong()).thenReturn(carrierName);
+ final CharSequence carrierName = "foobar";
+ doReturn(carrierName).when(mSubscriptionInfo).getCarrierName();
mController.initialize();
diff --git a/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java
index 69d1cbc..295eac5 100644
--- a/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java
@@ -70,9 +70,9 @@
when(mPackageManager.getAttentionServicePackageName()).thenReturn("some.package");
when(mPackageManager.checkPermission(any(), any())).thenReturn(
PackageManager.PERMISSION_GRANTED);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController = new AdaptiveSleepPreferenceController(mContext, PREFERENCE_KEY);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
}
@Test
@@ -143,9 +143,11 @@
public void isChecked_returnsFalseWhenNotSufficientPermissions() {
when(mPackageManager.checkPermission(any(), any())).thenReturn(
PackageManager.PERMISSION_DENIED);
+ final AdaptiveSleepPreferenceController controller = new AdaptiveSleepPreferenceController(
+ mContext, PREFERENCE_KEY);
- mController.setChecked(true);
- assertThat(mController.isChecked()).isFalse();
+ controller.setChecked(true);
+ assertThat(controller.isChecked()).isFalse();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
index 03c9b0a..5022d4a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
@@ -7,9 +7,14 @@
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
+
+import androidx.preference.PreferenceScreen;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@@ -19,9 +24,12 @@
private Context mContext;
private ContentResolver mResolver;
private BatterySaverScheduleSeekBarController mController;
+ @Mock
+ private PreferenceScreen mScreen;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new BatterySaverScheduleSeekBarController(mContext);
mResolver = mContext.getContentResolver();
@@ -62,4 +70,14 @@
mController.updateSeekBar();
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
}
+
+ @Test
+ public void addToScreen_addsToEnd() {
+ Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+ PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
+ Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
+ mController.addToScreen(mScreen);
+ assertThat(mController.mSeekBarPreference.getOrder()).isEqualTo(100);
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 30b5408..86f2355 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -33,6 +33,8 @@
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.SwitchPreference;
+import com.android.settings.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -165,5 +167,19 @@
mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isFalse();
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.mobile_data_settings_summary_auto_switch));
+ }
+
+ @Test
+ public void updateState_notOpportunistic_enabled() {
+ doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+ mController.init(mFragmentManager, SUB_ID);
+ doReturn(false).when(mSubscriptionInfo).isOpportunistic();
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isTrue();
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.mobile_data_settings_summary));
}
}
diff --git a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
index 4bcc15f..10cf413 100644
--- a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
+++ b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
@@ -21,7 +21,6 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -36,11 +35,8 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageItemInfo;
-import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.graphics.drawable.ColorDrawable;
-import android.os.UserManager;
import android.webkit.UserPackage;
import androidx.fragment.app.FragmentActivity;
@@ -49,17 +45,18 @@
import com.android.settingslib.applications.DefaultAppInfo;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
+import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowPackageManager;
+import org.robolectric.shadows.ShadowUserManager;
import org.robolectric.util.ReflectionHelpers;
import java.util.Arrays;
@@ -68,34 +65,40 @@
@RunWith(RobolectricTestRunner.class)
public class WebViewAppPickerTest {
- private final static String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
-
- private Context mContext;
-
- private UserInfo mFirstUser;
- private UserInfo mSecondUser;
+ private final static String PACKAGE_NAME = "com.example.test";
+ private final static String PACKAGE_VERSION = "1.0.0";
@Mock
private FragmentActivity mActivity;
- @Mock
- private UserManager mUserManager;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private PackageManager mPackageManager;
+ private Context mContext;
+ private UserInfo mFirstUser;
+ private UserInfo mSecondUser;
+ private ShadowPackageManager mPackageManager;
private WebViewAppPicker mPicker;
private WebViewUpdateServiceWrapper mWvusWrapper;
-
- private static ApplicationInfo createApplicationInfo(String packageName) {
- ApplicationInfo ai = new ApplicationInfo();
- ai.packageName = packageName;
- return ai;
- }
+ private ShadowUserManager mUserManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+ mUserManager = Shadow.extract(mContext.getSystemService(Context.USER_SERVICE));
+ mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
+
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.name = PACKAGE_NAME;
+ applicationInfo.uid = 0;
+ applicationInfo.flags = 0;
+ applicationInfo.packageName = PACKAGE_NAME;
+
+ final PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = PACKAGE_NAME;
+ packageInfo.applicationInfo = applicationInfo;
+ packageInfo.versionName = PACKAGE_VERSION;
+ mPackageManager.addPackage(packageInfo);
+ mPackageManager.setUnbadgedApplicationIcon(PACKAGE_NAME, new ColorDrawable());
+
mFirstUser = new UserInfo(0, "FIRST_USER", 0);
mSecondUser = new UserInfo(0, "SECOND_USER", 0);
mPicker = new WebViewAppPicker();
@@ -104,13 +107,17 @@
doNothing().when(mPicker).updateCheckedState(any());
doReturn(mActivity).when(mPicker).getActivity();
- ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
ReflectionHelpers.setField(mPicker, "mMetricsFeatureProvider",
mock(MetricsFeatureProvider.class));
mWvusWrapper = mock(WebViewUpdateServiceWrapper.class);
mPicker.setWebViewUpdateServiceWrapper(mWvusWrapper);
}
+ @After
+ public void tearDown() {
+ mPackageManager.removePackage(PACKAGE_NAME);
+ }
+
@Test
public void testClickingItemChangesProvider() {
testSuccessfulClickChangesProvider();
@@ -134,105 +141,70 @@
testFailingClick();
}
- private void useWebViewSettingIntent() {
- Intent intent = new Intent(ACTION_WEBVIEW_SETTINGS);
- when(mActivity.getIntent()).thenReturn(intent);
- }
-
- private void testSuccessfulClickChangesProvider() {
- when(mWvusWrapper.getValidWebViewApplicationInfos(any()))
- .thenReturn(Collections.singletonList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
- when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(true);
-
- RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
- when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
- mPicker.onRadioButtonClicked(defaultPackagePref);
-
- verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
- verify(mPicker, times(1)).updateCheckedState(DEFAULT_PACKAGE_NAME);
- verify(mWvusWrapper, never()).showInvalidChoiceToast(any());
- }
-
- private void testFailingClickUpdatesSetting() {
- when(mWvusWrapper.getValidWebViewApplicationInfos(any()))
- .thenReturn(Collections.singletonList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
- when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(false);
-
- RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
- when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
- mPicker.onRadioButtonClicked(defaultPackagePref);
-
- verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
- // Ensure we update the list of packages when we click a non-valid package - the list must
- // have changed, otherwise this click wouldn't fail.
- verify(mPicker, times(1)).updateCandidates();
- verify(mWvusWrapper, times(1)).showInvalidChoiceToast(any());
- }
-
@Test
- @Ignore
public void testDisabledPackageShownAsDisabled() {
- DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
- createApplicationInfo(DEFAULT_PACKAGE_NAME), "disabled");
+ DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext,
+ mContext.getPackageManager(),
+ createApplicationInfo(PACKAGE_NAME), "disabled");
RadioButtonPreference preference = mock(RadioButtonPreference.class);
- mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
- mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
+ mPicker.bindPreference(preference, PACKAGE_NAME, webviewAppInfo, null);
+ mPicker.bindPreferenceExtra(preference, PACKAGE_NAME, webviewAppInfo, null, null);
verify(preference, times(1)).setEnabled(eq(false));
verify(preference, never()).setEnabled(eq(true));
}
@Test
- @Ignore
public void testEnabledPackageShownAsEnabled() {
String disabledReason = "";
- DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
- createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
+ DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext,
+ mContext.getPackageManager(),
+ createApplicationInfo(PACKAGE_NAME), disabledReason);
RadioButtonPreference preference = mock(RadioButtonPreference.class);
- mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
- mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
+ mPicker.bindPreference(preference, PACKAGE_NAME, webviewAppInfo, null);
+ mPicker.bindPreferenceExtra(preference, PACKAGE_NAME, webviewAppInfo, null, null);
verify(preference, times(1)).setEnabled(eq(true));
verify(preference, never()).setEnabled(eq(false));
}
@Test
- @Ignore
public void testDisabledPackageShowsDisabledReasonSummary() {
String disabledReason = "disabled";
- DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
- createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
+ DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext,
+ mContext.getPackageManager(),
+ createApplicationInfo(PACKAGE_NAME), disabledReason);
RadioButtonPreference preference = mock(RadioButtonPreference.class);
- mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
- mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
+ mPicker.bindPreference(preference, PACKAGE_NAME, webviewAppInfo, null);
+ mPicker.bindPreferenceExtra(preference, PACKAGE_NAME, webviewAppInfo, null, null);
verify(preference, times(1)).setSummary(eq(disabledReason));
// Ensure we haven't called setSummary several times.
verify(preference, times(1)).setSummary(any());
}
@Test
- @Ignore
public void testEnabledPackageShowsEmptySummary() {
- DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
- createApplicationInfo(DEFAULT_PACKAGE_NAME), null);
+ DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext,
+ mContext.getPackageManager(),
+ createApplicationInfo(PACKAGE_NAME), null);
RadioButtonPreference preference = mock(RadioButtonPreference.class);
- mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
- mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
+ mPicker.bindPreference(preference, PACKAGE_NAME, webviewAppInfo, null);
+ mPicker.bindPreferenceExtra(preference, PACKAGE_NAME, webviewAppInfo, null, null);
verify(preference, never()).setSummary(any());
}
@Test
public void testFinishIfNotAdmin() {
- doReturn(false).when(mUserManager).isAdminUser();
+ mUserManager.setIsAdminUser(false);
mPicker.onAttach(mContext);
verify(mActivity, times(1)).finish();
}
@Test
public void testNotFinishedIfAdmin() {
- doReturn(true).when(mUserManager).isAdminUser();
+ mUserManager.setIsAdminUser(true);
mPicker.onAttach(mContext);
verify(mActivity, never()).finish();
}
@@ -248,10 +220,10 @@
when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
- when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
+ when(wvusWrapper.getPackageInfosAllUsers(any(), eq(PACKAGE_NAME)))
.thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
- assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME)).isNull();
+ assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, PACKAGE_NAME)).isNull();
}
@Test
@@ -262,11 +234,11 @@
when(packageForFirstUser.getUserInfo()).thenReturn(mFirstUser);
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
- when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
+ when(wvusWrapper.getPackageInfosAllUsers(any(), eq(PACKAGE_NAME)))
.thenReturn(Collections.singletonList(packageForFirstUser));
final String expectedReason = String.format("(disabled for user %s)", mFirstUser.name);
- assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
+ assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, PACKAGE_NAME))
.isEqualTo(expectedReason);
}
@@ -278,11 +250,11 @@
when(packageForFirstUser.getUserInfo()).thenReturn(mFirstUser);
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
- when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
+ when(wvusWrapper.getPackageInfosAllUsers(any(), eq(PACKAGE_NAME)))
.thenReturn(Collections.singletonList(packageForFirstUser));
final String expectedReason = String.format("(uninstalled for user %s)", mFirstUser.name);
- assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
+ assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, PACKAGE_NAME))
.isEqualTo(expectedReason);
}
@@ -299,11 +271,11 @@
when(packageForSecondUser.getUserInfo()).thenReturn(mSecondUser);
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
- when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
+ when(wvusWrapper.getPackageInfosAllUsers(any(), eq(PACKAGE_NAME)))
.thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
final String expectedReason = String.format("(disabled for user %s)", mFirstUser.name);
- assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
+ assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, PACKAGE_NAME))
.isEqualTo(expectedReason);
}
@@ -324,11 +296,11 @@
when(packageForSecondUser.getUserInfo()).thenReturn(mSecondUser);
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
- when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
+ when(wvusWrapper.getPackageInfosAllUsers(any(), eq(PACKAGE_NAME)))
.thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
final String expectedReason = String.format("(uninstalled for user %s)", mFirstUser.name);
- assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
+ assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, PACKAGE_NAME))
.isEqualTo(expectedReason);
}
@@ -337,29 +309,58 @@
* preference title.
*/
@Test
- public void testWebViewVersionAddedAfterLabel() throws PackageManager.NameNotFoundException {
- PackageItemInfo mockPackageItemInfo = mock(PackageItemInfo.class);
- mockPackageItemInfo.packageName = DEFAULT_PACKAGE_NAME;
- when(mockPackageItemInfo.loadLabel(any())).thenReturn("myPackage");
- DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
- mockPackageItemInfo, "" /* disabledReason */);
+ public void testWebViewVersionAddedAfterLabel() {
+ final DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext,
+ mContext.getPackageManager(),
+ createApplicationInfo(PACKAGE_NAME), "" /* disabledReason */);
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.versionName = "myVersionName";
- when(mPackageManager.getPackageInfo(eq(DEFAULT_PACKAGE_NAME), anyInt())).thenReturn(
- packageInfo);
+ final RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
+ mPicker.bindPreference(mockPreference, PACKAGE_NAME, webviewAppInfo, null);
+ mPicker.bindPreferenceExtra(
+ mockPreference, PACKAGE_NAME, webviewAppInfo, null, null);
- // Subvert attempts to load an unbadged icon for the application.
- PackageManager pm = RuntimeEnvironment.application.getPackageManager();
- ShadowPackageManager spm = Shadows.shadowOf(pm);
- spm.setUnbadgedApplicationIcon(DEFAULT_PACKAGE_NAME, new ColorDrawable());
+ verify(mockPreference).setTitle(eq(PACKAGE_NAME + " " + PACKAGE_VERSION));
+ verify(mockPreference).setTitle(any());
+ }
- RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
- mPicker.bindPreference(mockPreference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
- mPicker
- .bindPreferenceExtra(mockPreference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null,
- null);
- verify(mockPreference, times(1)).setTitle(eq("myPackage myVersionName"));
- verify(mockPreference, times(1)).setTitle(any());
+ private static ApplicationInfo createApplicationInfo(String packageName) {
+ ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = packageName;
+ return ai;
+ }
+
+ private void useWebViewSettingIntent() {
+ Intent intent = new Intent(ACTION_WEBVIEW_SETTINGS);
+ when(mActivity.getIntent()).thenReturn(intent);
+ }
+
+ private void testSuccessfulClickChangesProvider() {
+ when(mWvusWrapper.getValidWebViewApplicationInfos(any()))
+ .thenReturn(Collections.singletonList(createApplicationInfo(PACKAGE_NAME)));
+ when(mWvusWrapper.setWebViewProvider(eq(PACKAGE_NAME))).thenReturn(true);
+
+ RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
+ when(defaultPackagePref.getKey()).thenReturn(PACKAGE_NAME);
+ mPicker.onRadioButtonClicked(defaultPackagePref);
+
+ verify(mWvusWrapper, times(1)).setWebViewProvider(eq(PACKAGE_NAME));
+ verify(mPicker, times(1)).updateCheckedState(PACKAGE_NAME);
+ verify(mWvusWrapper, never()).showInvalidChoiceToast(any());
+ }
+
+ private void testFailingClickUpdatesSetting() {
+ when(mWvusWrapper.getValidWebViewApplicationInfos(any()))
+ .thenReturn(Collections.singletonList(createApplicationInfo(PACKAGE_NAME)));
+ when(mWvusWrapper.setWebViewProvider(eq(PACKAGE_NAME))).thenReturn(false);
+
+ RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
+ when(defaultPackagePref.getKey()).thenReturn(PACKAGE_NAME);
+ mPicker.onRadioButtonClicked(defaultPackagePref);
+
+ verify(mWvusWrapper, times(1)).setWebViewProvider(eq(PACKAGE_NAME));
+ // Ensure we update the list of packages when we click a non-valid package - the list must
+ // have changed, otherwise this click wouldn't fail.
+ verify(mPicker, times(1)).updateCandidates();
+ verify(mWvusWrapper, times(1)).showInvalidChoiceToast(any());
}
}
diff --git a/tests/robotests/src/com/android/settings/widget/SwitchBarTest.java b/tests/robotests/src/com/android/settings/widget/SwitchBarTest.java
index 35fa2c6..f186222 100644
--- a/tests/robotests/src/com/android/settings/widget/SwitchBarTest.java
+++ b/tests/robotests/src/com/android/settings/widget/SwitchBarTest.java
@@ -95,4 +95,11 @@
mBar.setDisabledByAdmin(null);
assertThat(mBar.getDelegatingView().getId()).isEqualTo(R.id.switch_widget);
}
+
+ @Test
+ public void performClick_shouldIsCheckedValueChange() {
+ boolean isChecked = mBar.isChecked();
+ mBar.performClick();
+ assertThat(mBar.isChecked()).isEqualTo(!isChecked);
+ }
}
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index 38211b3..de78828 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -175,4 +175,40 @@
assertThat(restoredWifiNetworkConfig.getNetworkId()).isEqualTo(0);
assertThat(restoredWifiNetworkConfig.isHotspot()).isTrue();
}
+
+ @Test
+ public void launchScanner_onNavigateUp_shouldFinish() {
+ Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY, "password");
+ final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+ mActivityRule.launchActivity(intent);
+
+ instrumentation.runOnMainSync(() -> {
+ mActivityRule.getActivity().onNavigateUp();
+
+ assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(true);
+ });
+ }
+
+ @Test
+ public void launchGenerator_onNavigateUp_shouldFinish() {
+ Intent intent = new Intent(
+ WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY, "password");
+ final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+ mActivityRule.launchActivity(intent);
+
+ instrumentation.runOnMainSync(() -> {
+ mActivityRule.getActivity().onNavigateUp();
+
+ assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(true);
+ });
+ }
+
}