Merge qt-r1-dev-plus-aosp-without-vendor (5817612) into stage-aosp-master

Bug: 135460123
Change-Id: Ifbb4b45d2d592e4a4ede265d2c882dc1cb4a0410
Merged-In: Idcc078c0e541c04633db6d94c613ac4c861ba963
This commit is contained in:
Xin Li
2019-09-08 13:06:57 -07:00
91 changed files with 1837 additions and 556 deletions

View File

@@ -3037,4 +3037,36 @@
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;face_intro_outline&quot;>#ffdadce0&lt;/color> &lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="150"
column="40"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:fillColor=&quot;@color/face_intro_outline&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/face_enroll_introduction.xml"
line="25"
column="40"/>
</issue>
</issues>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 608 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -16,13 +16,13 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="240dp"
android:height="240dp"
android:width="300dp"
android:height="300dp"
android:viewportWidth="300"
android:viewportHeight="300">
<path
android:fillColor="#DADCE0"
android:fillColor="@color/face_intro_outline"
android:fillType="evenOdd"
android:pathData="M150,0C67.16,0,0,67.16,0,150s67.16,150,150,150 s150-67.16,150-150S232.84,0,150,0 M150,4c39,0,75.66,15.19,103.24,42.76C280.81,74.34,296,111,296,150s-15.19,75.66-42.76,103.24 C225.66,280.81,189,296,150,296s-75.66-15.19-103.24-42.76C19.19,225.66,4,189,4,150S19.19,74.34,46.76,46.76 C74.34,19.19,111,4,150,4" />
<path

View File

@@ -16,9 +16,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?android:attr/colorControlNormal"
android:fillColor="@android:color/white"
android:pathData="M12,16.41l-6.71,-6.7l1.42,-1.42l5.29,5.3l5.29,-5.3l1.42,1.42z"/>
</vector>

View File

@@ -1,9 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="@*android:color/material_grey_600"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"
android:fillColor="#757575"/>
android:fillColor="@android:color/white"/>
</vector>

View File

@@ -16,9 +16,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="@android:color/black"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:fillColor="@android:color/white"
android:pathData="M3,6h18L21,4L3,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h4v-2L3,18L3,6zM13,12L9,12v1.78c-0.61,0.55 -1,1.33 -1,2.22 0,0.89 0.39,1.67 1,2.22L9,20h4v-1.78c0.61,-0.55 1,-1.34 1,-2.22s-0.39,-1.67 -1,-2.22L13,12zM11,17.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM22,8h-6c-0.5,0 -1,0.5 -1,1v10c0,0.5 0.5,1 1,1h6c0.5,0 1,-0.5 1,-1L23,9c0,-0.5 -0.5,-1 -1,-1zM21,18h-4v-8h4v8z"/>
</vector>

View File

@@ -0,0 +1,29 @@
<?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
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M10.25,13c0,0.69-0.56,1.25-1.25,1.25S7.75,13.69,7.75,13S8.31,11.75,9,11.75S10.25,12.31,10.25,13z M15,11.75 c-0.69,0-1.25,0.56-1.25,1.25s0.56,1.25,1.25,1.25s1.25-0.56,1.25-1.25S15.69,11.75,15,11.75z M22,12c0,5.52-4.48,10-10,10 S2,17.52,2,12S6.48,2,12,2S22,6.48,22,12z M20,12c0-0.78-0.12-1.53-0.33-2.24C18.97,9.91,18.25,10,17.5,10 c-3.13,0-5.92-1.44-7.76-3.69c-1.05,2.56-3.14,4.57-5.74,5.55C4.01,11.9,4,11.95,4,12c0,4.41,3.59,8,8,8S20,16.41,20,12z" />
<path
android:pathData="M0,0h24v24H0V0z" />
</vector>

View File

@@ -17,9 +17,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/colorControlNormal"
android:fillColor="@android:color/white"
android:pathData="M18,8h-1V6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2H9V6zM18,20H6V10h12V20zM12,17c1.1,0 2,-0.9 2,-2c0,-1.1 -0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2C10,16.1 10.9,17 12,17z"/>
</vector>

View File

@@ -0,0 +1,31 @@
<!--
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
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#12B5CB"
android:pathData="M10.67,21H7v-1h3.13c-0.27-0.63-0.46-1.3-0.56-2H7V6h10v3.5c0.69,0,1.36,0.1,2,0.28V3 c0-1.1-0.9-1.99-2-1.99L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h5.52C11.79,22.45,11.16,21.77,10.67,21z M7,3h10v1H7V3z" />
<path
android:fillColor="#FA903E"
android:pathData="M17,12.5c2.48,0,4.5,2.02,4.5,4.5s-2.02,4.5-4.5,4.5s-4.5-2.02-4.5-4.5S14.52,12.5,17,12.5 M17,11 c-3.31,0-6,2.69-6,6s2.69,6,6,6c3.31,0,6-2.69,6-6S20.31,11,17,11L17,11z" />
<path
android:fillColor="#FA903E"
android:pathData="M17,14v3l-2.12,2.12C15.42,19.66,16.17,20,17,20c1.66,0,3-1.34,3-3S18.66,14,17,14z" />
</vector>

View File

@@ -18,8 +18,9 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12,2c-1.78,0 -3.44,0.46 -4.89,1.28l1.48,1.48C9.63,4.28 10.78,4 12,4c4.41,0 8,3.59 8,8c0,1.22 -0.28,2.37 -0.76,3.41l1.48,1.48C21.54,15.44 22,13.78 22,12C22,6.48 17.52,2 12,2zM18.12,17.13L6.87,5.87L3.31,2.31L1.89,3.72l2.19,2.19C2.77,7.59 2,9.71 2,12c0,5.52 4.48,10 10,10c2.29,0 4.41,-0.77 6.09,-2.08l2.19,2.19l1.41,-1.41L18.12,17.13zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-1.74 0.56,-3.35 1.51,-4.66l11.15,11.15C15.35,19.44 13.74,20 12,20zM8.59,4.76L7.11,3.28"/>
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2c-1.78,0 -3.44,0.46 -4.89,1.28l1.48,1.48C9.63,4.28 10.78,4 12,4c4.41,0 8,3.59 8,8c0,1.22 -0.28,2.37 -0.76,3.41l1.48,1.48C21.54,15.44 22,13.78 22,12C22,6.48 17.52,2 12,2zM18.12,17.13L6.87,5.87L3.31,2.31L1.89,3.72l2.19,2.19C2.77,7.59 2,9.71 2,12c0,5.52 4.48,10 10,10c2.29,0 4.41,-0.77 6.09,-2.08l2.19,2.19l1.41,-1.41L18.12,17.13zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-1.74 0.56,-3.35 1.51,-4.66l11.15,11.15C15.35,19.44 13.74,20 12,20zM8.59,4.76L7.11,3.28"/>
</vector>

View File

@@ -18,8 +18,9 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:fillColor="@android:color/white"
android:pathData="M15.59,10.09L13,12.67V2h-2v10.67l-2.59,-2.58L7,11.5l5,5l5,-5L15.59,10.09zM15,2.46v2.13c2.93,1.19 5,4.06 5,7.41c0,4.41 -3.59,8 -8,8s-8,-3.59 -8,-8c0,-3.35 2.07,-6.22 5,-7.41V2.46C4.94,3.74 2,7.53 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,7.53 19.06,3.74 15,2.46z"/>
</vector>

View File

@@ -16,10 +16,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="32.0"
android:viewportHeight="32.0"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M4.59 6.89c0.7-0.71 1.4-1.35 1.71-1.22 0.5 0.2 0 1.03-0.3 1.52-0.25 0.42 -2.86 3.89-2.86 6.31 0 1.28 0.48 2.34 1.34 2.98 0.75 0.56 1.74 0.73 2.64 0.46 1.07-0.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78 0.64 -5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H21v-2.5h-2.47c-0.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-0.58 0.73 -2.06 2.48-2.29 2.72-0.25 0.3 -0.68 0.84 -1.11 0.84 -0.45 0-0.72-0.83-0.36-1.92 0.35 -1.09 1.4-2.86 1.85-3.52 0.78 -1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25c-0.36 0.36 -0.66 0.66 -0.88 0.93 l1.75 1.71zm9.29 11.66c-0.31 0-0.74-0.26-0.74-0.72 0-0.6 0.73 -2.2 2.87-2.76-0.3 2.69-1.43 3.48-2.13 3.48z" />
android:pathData="M17,18L7,18L7,6L17,6L17,7L19,7L19,3C19,1.895 18.105,1 17,1L7,1C5.895,1 5,1.895 5,3L5,21C5,22.105 5.895,23 7,23L17,23C18.105,23 19,22.105 19,21L19,17L17,17L17,18ZM7,3L17,3L17,4L7,4L7,3ZM17,21L7,21L7,20L17,20L17,21ZM17.94,12.06L20,13L17.94,13.94L17,16L16.06,13.94L14,13L16.06,12.06L17,10L17.94,12.06ZM20.63,8.38L22,9L20.63,9.63L20,11L19.38,9.63L18,9L19.38,8.38L20,7L20.63,8.38Z"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillColor="#000000"
android:strokeWidth="1"/>
</vector>

View File

@@ -21,6 +21,6 @@
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M3,12c0,2.21 0.91,4.2 2.36,5.64L3,20h6v-6l-2.24,2.24C5.68,15.15 5,13.66 5,12c0,-2.61 1.67,-4.83 4,-5.65L9,4.26C5.55,5.15 3,8.27 3,12zM11,17h2v-2h-2v2zM21,4h-6v6l2.24,-2.24C18.32,8.85 19,10.34 19,12c0,2.61 -1.67,4.83 -4,5.65v2.09c3.45,-0.89 6,-4.01 6,-7.74 0,-2.21 -0.91,-4.2 -2.36,-5.64L21,4zM11,13h2L13,7h-2v6z"/>
android:fillColor="@android:color/white"
android:pathData="M11 4.07v2.02C8.17 6.57 6 9.03 6 12c0 2.22 1.21 4.15 3 5.19V14h2v6H5v-2h1.74C5.07 16.54 4 14.4 4 12c0-4.08 3.05-7.44 7-7.93zm8.51 10.67c0.3 0.52 0.49 1.11 0.49 1.76 0 1.93-1.57 3.5-3.5 3.5-0.65 0-1.25-0.19-1.77-0.49-0.65-0.38-1.17-0.96-1.46-1.67-0.17-0.41-0.27-0.87-0.27-1.34 0-1.93 1.57-3.5 3.5-3.5 0.48 0 0.93 0.1 1.35 0.27 0.09-0.41 0.15 -0.83 0.15 -1.27 0-2.22-1.21-4.15-3-5.19V10h-2V4h6v2h-1.74C18.93 7.46 20 9.6 20 12c0 0.96-0.18 1.89-0.49 2.74zM17 18h-1v1h1v-1zm0-4h-1v3h1v-3z" />
</vector>

View File

@@ -25,7 +25,7 @@
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="left"
android:gravity="start"
android:orientation="vertical"
android:paddingEnd="@dimen/contextual_card_padding_end"
android:paddingTop="@dimen/contextual_deferred_setup_card_padding_top"

View File

@@ -56,7 +56,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/SudContentIllustration"
app:sudVideo="@raw/face_enroll_introduction_animation"/>
app:sudVideo="@raw/face_settings"/>
</FrameLayout>
@@ -65,13 +65,35 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_horizontal|bottom">
android:layout_gravity="center_horizontal|bottom"
android:paddingTop="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_info_outline_24dp">
</ImageView>
<Space
android:layout_width="24dp"
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_0"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="24dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@@ -27,5 +27,6 @@
<color name="notification_importance_selection_bg">@*android:color/material_grey_800</color>
<color name="notification_importance_button_selected">#AECBFA</color> <!-- material blue 200 -->
<color name="notification_importance_button_unselected">#5F6368</color>
<color name="face_intro_outline">?android:attr/colorAccent</color>
</resources>

View File

@@ -147,4 +147,5 @@
<!-- Dialog background color -->
<color name="dialog_background">@*android:color/background_device_default_light</color>
<color name="face_intro_outline">#ffdadce0</color>
</resources>

View File

@@ -790,13 +790,13 @@
<!-- Security Settings --><skip />
<!-- Security settings screen, setting option name to change screen timeout -->
<string name="lock_after_timeout">Automatically lock</string>
<string name="lock_after_timeout">Lock after screen timeout</string>
<!-- Security settings screen, setting option summary to change screen timeout -->
<string name="lock_after_timeout_summary"><xliff:g id="timeout_string">%1$s</xliff:g> after sleep</string>
<string name="lock_after_timeout_summary"><xliff:g id="timeout_string">%1$s</xliff:g> after timeout</string>
<!-- Security settings screen, setting option summary to change screen timeout, with additional explanation-->
<string name="lock_immediately_summary_with_exception">Immediately after sleep, except when kept unlocked by <xliff:g id="trust_agent_name">%1$s</xliff:g></string>
<string name="lock_immediately_summary_with_exception">Immediately after timeout, except when kept unlocked by <xliff:g id="trust_agent_name">%1$s</xliff:g></string>
<!-- Security settings screen, setting option summary to change screen timeout, with additional explanation-->
<string name="lock_after_timeout_summary_with_exception"><xliff:g id="timeout_string">%1$s</xliff:g> after sleep, except when kept unlocked by <xliff:g id="trust_agent_name">%2$s</xliff:g></string>
<string name="lock_after_timeout_summary_with_exception"><xliff:g id="timeout_string">%1$s</xliff:g> after timeout, except when kept unlocked by <xliff:g id="trust_agent_name">%2$s</xliff:g></string>
<!-- Text shown next to checkbox for showing owner info on LockScreen [CHAR LIMIT=50]-->
<string name="show_owner_info_on_lockscreen_label">Show owner info on lock screen</string>
<!-- Text shown for title of owner info setting [CHAR LIMIT=20]-->
@@ -808,7 +808,7 @@
<!-- Text shown for the title of the lockdown option -->
<string name="lockdown_settings_title">Show lockdown option</string>
<!-- Text shown for the description of the lockdown option -->
<string name="lockdown_settings_summary">Display power button option that turns off Smart Lock, fingerprint unlocking, and notifications on the lock screen</string>
<string name="lockdown_settings_summary">Display power button option that turns off Smart Lock, biometric unlocking, and notifications on the lock screen</string>
<!-- Text shown for the title of the extend unlock mode option for trust agents [CHAR LIMIT=40] -->
<string name="trust_agents_extend_unlock_title">Trust agents only extend unlock</string>
@@ -882,17 +882,19 @@
<string name="security_dashboard_summary_no_fingerprint">Screen lock</string>
<!-- Face enrollment and settings --><skip />
<!-- Message shown in summary field when face authentication is set up. [CHAR LIMIT=40] -->
<!-- Message shown in summary field when face unlock is set up. [CHAR LIMIT=40] -->
<string name="security_settings_face_preference_summary">Face added</string>
<!-- Message shown in summary field when face authentication is not set up. [CHAR LIMIT=54] -->
<string name="security_settings_face_preference_summary_none">Tap to set up face authentication</string>
<!-- Message shown in summary field when face unlock is not set up. [CHAR LIMIT=54] -->
<string name="security_settings_face_preference_summary_none">Set up face unlock</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>
<string name="security_settings_face_preference_title">Face unlock</string>
<!-- Title shown for menu item that launches face settings or enrollment, for work profile [CHAR LIMIT=50] -->
<string name="security_settings_face_profile_preference_title">Face unlock for work</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>
<string name="security_settings_face_enroll_education_title">How to set up face unlock</string>
<!-- Introduction title shown in face enrollment education screen for accessibility [CHAR LIMI=40]-->
<string name="security_settings_face_enroll_education_title_accessibility">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=60] -->
<string name="security_settings_face_enroll_education_title_accessibility">Set up face unlock</string>
<!-- Introduction title shown in face enrollment education screen to show the face unlock feature, when face unlock is disabled by device admin [CHAR LIMIT=60] -->
<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>
@@ -910,7 +912,7 @@
<string name="security_settings_face_enroll_introduction_cancel">Cancel</string>
<!-- Introduction title shown in face enrollment to introduce the face unlock feature [CHAR LIMIT=40] -->
<string name="security_settings_face_enroll_introduction_title">Unlock with your face</string>
<!-- Introduction title shown in face enrollment to introduce the face authentication feature, when face unlock is disabled by device admin [CHAR LIMIT=60] -->
<!-- Introduction title shown in face enrollment to introduce the face unlock feature, when face unlock is disabled by device admin [CHAR LIMIT=60] -->
<string name="security_settings_face_enroll_introduction_title_unlock_disabled">Use your face to authenticate</string>
<!-- Introduction detail message shown in face enrollment dialog [CHAR LIMIT=NONE]-->
<string name="security_settings_face_enroll_introduction_message">Use your face to unlock your phone, authorize purchases, or sign in to apps.</string>
@@ -919,6 +921,8 @@
<!-- 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 message shown in face enrollment that provides extra detail. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_introduction_footer_part_0"></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>
@@ -950,29 +954,30 @@
<string name="security_settings_face_settings_use_face_category">Use face unlock for</string>
<!-- Text shown on a toggle which allows or disallows the device to use face for unlocking the device. [CHAR LIMIT=20] -->
<string name="security_settings_face_settings_use_face_unlock_phone">Unlocking your phone</string>
<!-- Text shown on a toggle which allows or disallows the device to use face authentication for apps. This will be presented to the user together with the context of security_settings_face_settings_use_face_category. [CHAR LIMIT=30] -->
<!-- Text shown on a toggle which allows or disallows the device to use face unlock for apps. This will be presented to the user together with the context of security_settings_face_settings_use_face_category. [CHAR LIMIT=30] -->
<string name="security_settings_face_settings_use_face_for_apps">App sign-in \u0026 payments</string>
<!-- Title for a category shown for the face settings page, followed by items that the user can toggle on/off to require/disable. -->
<string name="security_settings_face_settings_require_category">Require for face unlock</string>
<!-- Text shown on a toggle which disables/enables face authentication, depending if the user's eyes are open. [CHAR LIMIT=30] -->
<string name="security_settings_face_settings_require_attention">Open eyes looking at screen</string>
<!-- Text shown on the details of a toggle which disables/enables face authentication, depending if the user's eyes are open. [CHAR LIMIT=70] -->
<string name="security_settings_face_settings_require_attention_details">To unlock the phone, always require looking at the screen with your eyes open</string>
<string name="security_settings_face_settings_require_category">Requirements for face unlock</string>
<!-- Text shown on a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=30] -->
<string name="security_settings_face_settings_require_attention">Require eyes to be open</string>
<!-- Text shown on the details of a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=70] -->
<string name="security_settings_face_settings_require_attention_details">To unlock the phone, your eyes must be open</string>
<!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=50] -->
<string name="security_settings_face_settings_require_confirmation">Confirm button</string>
<string name="security_settings_face_settings_require_confirmation">Always require confirmation</string>
<!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=70] -->
<string name="security_settings_face_settings_require_confirmation_details">When authenticating for apps, always require confirmation</string>
<string name="security_settings_face_settings_require_confirmation_details">When using face unlock in apps, always require confirmation step</string>
<!-- Button text in face settings which removes the user's faces from the device [CHAR LIMIT=20] -->
<string name="security_settings_face_settings_remove_face_data">Delete face data</string>
<!-- Button text in face settings which lets the user enroll their face [CHAR LIMIT=40] -->
<string name="security_settings_face_settings_enroll">Set up new face unlock</string>
<string name="security_settings_face_settings_enroll">Set up face unlock</string>
<!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_footer">Use Face unlock to unlock your device, sign in to apps, and confirm payments.\n\nKeep in mind:\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face while your eyes are open.\n\nYour phone can be unlocked by someone who looks a lot like you, say, your child or an identical sibling.</string>
<string name="security_settings_face_settings_footer">Use face unlock to unlock your device, sign in to apps, and confirm payments.\n\nKeep in mind:\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face, even if your eyes are closed.\n\nYour phone can be unlocked by someone who looks a lot like you, say, an identical sibling.</string>
<!-- Dialog title shown when the user removes an enrollment [CHAR LIMIT=35] -->
<string name="security_settings_face_settings_remove_dialog_title">Delete face data?</string>
<!-- Dialog contents shown when the user removes an enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_remove_dialog_details">Data recorded by face unlock will be permanently and securely deleted. After removal, you will need your PIN, pattern, or password to unlock your phone, sign in to apps, and confirm payments.</string>
<string name="security_settings_face_settings_remove_dialog_details">The images and biometric data used by face unlock will be permanently and securely deleted. After removal, you will need your PIN, pattern, or password to unlock your phone, sign in to apps, and confirm payments.</string>
<!-- Subtitle shown for contextual setting face enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_context_subtitle">Use face unlock to unlock your phone</string>
<!-- Fingerprint enrollment and settings --><skip />
<!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
@@ -1072,12 +1077,12 @@
<string name="fingerprint_lock_screen_setup_skip_dialog_text" product="device">Protect your device with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up fingerprint. Tap Cancel, then set a PIN, pattern, or password.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set fingerprint. (default) [CHAR LIMIT=NONE] -->
<string name="fingerprint_lock_screen_setup_skip_dialog_text" product="default">Protect your phone with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up fingerprint. Tap Cancel, then set a PIN, pattern, or password.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face authentication. (tablet) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="tablet">Protect your tablet with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN, pattern, or password.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face authentication. (device) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="device">Protect your device with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN, pattern, or password.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face authentication. (default) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="default">Protect your phone with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN, pattern, or password.</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face unlock. (tablet) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="tablet">By protecting your tablet with a screen lock option, no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face unlock. To go back, tap Cancel. </string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face unlock. (device) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="device">By protecting your device with a screen lock option, no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face unlock. To go back, tap Cancel. </string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning that they can't continue to set face unlock. (default) [CHAR LIMIT=NONE] -->
<string name="face_lock_screen_setup_skip_dialog_text" product="default">By protecting your phone with a screen lock option, no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face unlock. To go back, tap Cancel.</string>
<!-- Title of dialog shown when the user tries to skip setting up a PIN, warning them of potential consequences of not doing so [CHAR LIMIT=48]-->
<string name="lock_screen_pin_skip_title">Skip PIN setup?</string>
<!-- Title of dialog shown when the user tries to skip setting up a password, warning them of potential consequences of not doing so [CHAR LIMIT=48]-->
@@ -1321,7 +1326,7 @@
<!-- Message shown in screen lock picker while setting up the backup/fallback screen lock method for fingerprint. Users can choose to use this method to unlock the screen instead of fingerprint, or when fingerprint is not accepted. [CHAR LIMIT=80] [BACKUP_MESSAGE_ID=2799884038398627882] -->
<string name="lock_settings_picker_fingerprint_message">Choose your backup screen lock method</string>
<!-- Message shown in screen lock picker while setting up the backup/fallbakc screen lock method for face authentication. Users can choose to use this method to unlock the screen instead of face authentication, or when face authentication is not accepted. [CHAR LIMIT=80] -->
<!-- Message shown in screen lock picker while setting up the backup/fallback screen lock method for face unlock. Users can choose to use this method to unlock the screen instead of face unlock, or when face unlock is not accepted. [CHAR LIMIT=80] -->
<string name="lock_settings_picker_face_message">Choose your backup screen lock method</string>
<!-- Label for button in screen lock settings, allowing users to choose other types of screen locks. [CHAR LIMIT=40] -->
@@ -1399,19 +1404,19 @@
<!-- Message shown in screen lock picker while setting up the new screen lock with fingerprint option. [CHAR LIMIT=NONE]-->
<string name="fingerprint_unlock_title">You can unlock your phone using your fingerprint. For security, this option requires a backup screen lock.</string>
<!-- Title for preference that guides the user through creating a backup unlock pattern for face authentication [CHAR LIMIT=45]-->
<string name="face_unlock_set_unlock_pattern">Face authentication + Pattern</string>
<!-- Title for preference that guides the user through creating a backup unlock pattern for face unlock [CHAR LIMIT=45]-->
<string name="face_unlock_set_unlock_pattern">Face unlock + Pattern</string>
<!-- Title for preference that guides the user through creating a backup unlock PIN for face authentication [CHAR LIMIT=45]-->
<string name="face_unlock_set_unlock_pin">Face authentication + PIN</string>
<!-- Title for preference that guides the user through creating a backup unlock PIN for face unlock [CHAR LIMIT=45]-->
<string name="face_unlock_set_unlock_pin">Face unlock + PIN</string>
<!-- Title for preference that guides the user through creating a backup unlock password for face authentication [CHAR LIMIT=45]-->
<string name="face_unlock_set_unlock_password">Face authentication + Password</string>
<!-- Title for preference that guides the user through creating a backup unlock password for face unlock [CHAR LIMIT=45]-->
<string name="face_unlock_set_unlock_password">Face unlock + Password</string>
<!-- Title for preference that guides the user to skip face authentication setup [CHAR LIMIT=60]-->
<string name="face_unlock_skip_face">Continue without face authentication</string>
<!-- Title for preference that guides the user to skip face unlock setup [CHAR LIMIT=60]-->
<string name="face_unlock_skip_face">Continue without face unlock</string>
<!-- Message shown in screen lock picker while setting up the new screen lock with face authentication option. [CHAR LIMIT=NONE] -->
<!-- Message shown in screen lock picker while setting up the new screen lock with face unlock option. [CHAR LIMIT=NONE] -->
<string name="face_unlock_title">You can unlock your phone using your face. For security, this option requires a backup screen lock.</string>
<!-- Summary for preference that has been disabled by because of the DevicePolicyAdmin, or because device encryption is enabled, or because there are credentials in the credential storage [CHAR LIMIT=50] -->
@@ -2826,17 +2831,24 @@
<!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] -->
<string name="display_white_balance_title">Display white balance</string>
<!-- Display settings screen, display white balance settings summary [CHAR LIMIT=NONE] -->
<string name="display_white_balance_summary"></string>
<!-- Display settings screen, setting option name to enable adaptive sleep [CHAR LIMIT=30] -->
<string name="adaptive_sleep_title">Screen attention</string>
<!-- Setting option summary when adaptive sleep is on [CHAR LIMIT=NONE] -->
<string name="adaptive_sleep_summary_on">On / Screen wont turn off if youre looking at it</string>
<string name="adaptive_sleep_summary_on">On / Screen won\u2019t turn off if you\u2019re looking at it</string>
<!-- Setting option summary when adaptive sleep is off [CHAR LIMIT=NONE] -->
<string name="adaptive_sleep_summary_off">Off</string>
<!-- adaptive_sleep settings screen, title about the required permission is missing [CHAR LIMIT=NONE]-->
<string name="adaptive_sleep_title_no_permission">Camera access needed</string>
<!-- adaptive_sleep settings screen, subtitle when permission is missing [CHAR LIMIT=NONE]-->
<string name="adaptive_sleep_summary_no_permission">Tap to manage permissions for Device Personalization Services</string>
<!-- Description about the feature adaptive sleep [CHAR LIMIT=NONE]-->
<string name="adaptive_sleep_description">Prevents your screen from turning off if youre looking at it.</string>
<string name="adaptive_sleep_description">Prevents your screen from turning off if you\u2019re looking at it</string>
<!-- Description feature's privacy sensitive details to make sure users understand what feature users, what it saves/sends etc [CHAR LIMIT=NONE]-->
<string name="adaptive_sleep_privacy">Screen attention uses the front camera to see if someone is looking at the screen. It works on device, and images are never stored or sent to Google.</string>
<!-- Description about the contextual adaptive sleep card [CHAR LIMIT=NONE]-->
<string name="adaptive_sleep_contextual_slice_summary">Keep screen on when viewing it</string>
<!-- Night display screen, setting option name to enable night display (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
<string name="night_display_title">Night Light</string>
@@ -2912,7 +2924,7 @@
<!-- Styles and Wallpaper settings title [CHAR_LIMIT=46] -->
<string name="style_suggestion_title">Customize your Pixel</string>
<!-- Styles and Wallpapers summary [CHAR_LIMIT=70] -->
<string name="style_suggestion_summary">Try different styles, wallpapers, clocks, and more</string>
<string name="style_suggestion_summary">Try different styles, wallpapers, and more</string>
<!-- Display settings screen, trigger for screen saver options -->
<string name="screensaver_settings_title">Screen saver</string>
<!-- Display settings screen, summary fragment for screen saver options, activated when docked or asleep and charging -->
@@ -4052,12 +4064,12 @@
<string name="lockpassword_pin_set_toast">PIN has been set</string>
<!-- Toast shown if setting pattern was successful -->
<string name="lockpassword_pattern_set_toast">Pattern has been set</string>
<!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_password_header_for_face">To use face authentication, set password</string>
<!-- Header on first screen of choose pattern as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
<!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
<!-- Header on first screen of choose password/PIN as backup for face unlock flow. If this string cannot be translated in under 40 characters, please translate "Set face unlock backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_password_header_for_face">To use face unlock, set password</string>
<!-- Header on first screen of choose pattern as backup for face unlock flow. If this string cannot be translated in under 40 characters, please translate "Set face unlock backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pattern_header_for_face">To use face unlock, set pattern</string>
<!-- Header on first screen of choose password/PIN as backup for face unlock flow. If this string cannot be translated in under 40 characters, please translate "Set face unlock backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pin_header_for_face">To use face unlock, set PIN</string>
<!-- Message to be used to explain the user that he needs to enter his pattern to continue a
particular operation. [CHAR LIMIT=70]-->
@@ -4873,6 +4885,8 @@
<string name="accessibility_tutorial_dialog_button">Got it</string>
<!-- Summary text appearing on the accessibility preference screen to enable screen magnification from the nav bar when the feature is enabled, but the accessibility button is not configured correctly for the feature to be used [CHAR LIMIT=none] -->
<string name="accessibility_screen_magnification_navbar_configuration_warning">The Accessibility button is set to <xliff:g id="service" example="Select to Speak">%1$s</xliff:g>. To use magnification, touch &amp; hold the Accessibility button, then select magnification.</string>
<!-- Summary text appearing on the accessibility preference screen to enable screen magnification from the nav bar when the feature is enabled, but the accessibility button is not configured correctly for the feature to be used [CHAR LIMIT=none] -->
<string name="accessibility_screen_magnification_gesture_navigation_warning">The accessibility gesture is set to the <xliff:g id="service" example="Select to Speak">%1$s</xliff:g>. To use magnification, swipe up with two fingers from the bottom of the screen and hold. Then select magnification.</string>
<!-- Title for the preference to configure the accessibility shortcut, which uses the volume keys. [CHAR LIMIT=35] -->
<string name="accessibility_global_gesture_preference_title">Volume key shortcut</string>
<!-- Title for the preference to choose the service that is turned on and off by the accessibility shortcut. [CHAR LIMIT=35] -->
@@ -4949,6 +4963,8 @@
<string name="accessibility_daltonizer_master_switch_title">Use color correction</string>
<!-- Used in the Captions settings screen to control turning on/off the feature entirely -->
<string name="accessibility_caption_master_switch_title">Use captions</string>
<!-- Used in the Captions preference to tell users that the setting doesn't support all apps. [CHAR LIMIT=NONE] -->
<string name="accessibility_caption_preference_summary">Not all apps support this setting.</string>
<!-- Button text for the accessibility dialog continue to the next screen for hearing aid. [CHAR LIMIT=32] -->
<string name="accessibility_hearingaid_instruction_continue_button">Continue</string>
@@ -7993,6 +8009,15 @@
<!-- Configure Notifications: Title for the option controlling notifications on the lockscreen. [CHAR LIMIT=30] -->
<string name="lock_screen_notifications_title">Lock screen</string>
<!-- Configure lock screen: Title for the option of unlocking directly to home. [CHAR LIMIT=30] -->
<string name="lockscreen_bypass_title">Skip lock screen</string>
<!-- Configure lock screen: Summary for the option of unlocking directly to home. [CHAR LIMIT=100] -->
<string name="lockscreen_bypass_summary">After face unlock, go directly to last used screen</string>
<!-- Configure lock screen: Search keywords for the option of unlocking directly to home. [CHAR LIMIT=100] -->
<string name="keywords_lockscreen_bypass">Lock screen, Lockscreen, Skip, Bypass</string>
<!-- Configure Notifications: Title for the option controlling notifications for work profile. [CHAR LIMIT=30] -->
<string name="locked_work_profile_notification_title">When work profile is locked</string>
@@ -10000,12 +10025,6 @@
<!-- [CHAR_LIMIT=NONE] Developer Settings: Title of the settings category for theme overlays. -->
<string name="theme_customization_category">Theming</string>
<!-- [CHAR_LIMIT=NONE] Developer Settings: Title of the setting which enables overlays to customize accent color. -->
<string name="theme_customization_accent_color_title">Accent color</string>
<!-- [CHAR_LIMIT=NONE] Developer Settings: Title of the setting which enables overlays to customize headline and body fonts. -->
<string name="theme_customization_font_title">Headline / Body font</string>
<!-- [CHAR_LIMIT=NONE] Developer Settings: Title of the setting which enables overlays to customize the adaptive icon shape (e.g. launcher and quick settings icons). -->
<string name="theme_customization_icon_shape_title">Icon shape</string>
<!-- [CHAR_LIMIT=NONE] Developer Settings: Label for the option that turns off customizations for a given category.-->
<string name="theme_customization_device_default">Device default</string>

View File

@@ -28,6 +28,14 @@
settings:preview="@drawable/adaptive_sleep"
settings:controller="com.android.settings.widget.VideoPreferenceController"/>
<Preference
android:key="adaptive_sleep_permission"
android:title="@string/adaptive_sleep_title_no_permission"
android:summary="@string/adaptive_sleep_summary_no_permission"
android:icon="@drawable/ic_info_outline_24"
settings:controller="com.android.settings.display.AdaptiveSleepPermissionPreferenceController"
/>
<com.android.settingslib.RestrictedSwitchPreference
android:key="adaptive_sleep"
android:title="@string/adaptive_sleep_title"

View File

@@ -30,10 +30,9 @@
<PreferenceCategory
android:key="standard"
android:title="@string/captioning_standard_options_title" >
<com.android.settings.accessibility.LocalePreference
android:key="captioning_locale"
android:summary="%s"
android:title="@string/captioning_locale" />
<SwitchPreference
android:key="captioning_preference_switch"
android:title="@string/accessibility_caption_master_switch_title" />
<ListPreference
android:entries="@array/captioning_font_size_selector_titles"
@@ -45,6 +44,11 @@
<com.android.settings.accessibility.PresetPreference
android:key="captioning_preset"
android:title="@string/captioning_preset" />
<com.android.settings.accessibility.LocalePreference
android:key="captioning_locale"
android:summary="%s"
android:title="@string/captioning_locale" />
</PreferenceCategory>
<PreferenceCategory
android:key="custom"
@@ -88,4 +92,8 @@
android:title="@string/captioning_window_opacity" />
</PreferenceCategory>
<com.android.settingslib.widget.FooterPreference
android:title="@string/accessibility_caption_preference_summary"
android:selectable="false" />
</PreferenceScreen>

View File

@@ -72,6 +72,13 @@
android:summary="@string/lock_screen_notifs_redact_work_summary"
settings:controller="com.android.settings.notification.RedactNotificationPreferenceController" />
<SwitchPreference
android:key="notification_lockscreen_bypass"
android:title="@string/lockscreen_bypass_title"
android:summary="@string/lockscreen_bypass_summary"
settings:searchable="false"
settings:controller="com.android.settings.biometrics.face.FaceSettingsLockscreenBypassPreferenceController" />
</PreferenceCategory>
<PreferenceCategory

View File

@@ -571,7 +571,7 @@
<com.android.settings.development.autofill.AutofillPreferenceCategory
android:key="debug_autofill_category"
android:title="@string/debug_autofill_category"
android:order="1100">
android:order="1100"> <!-- Incremented by 100 from last order (i.e. 1000) -->
<ListPreference
android:key="autofill_logging_level"
@@ -592,20 +592,4 @@
android:title="@string/autofill_reset_developer_options" />
</com.android.settings.development.autofill.AutofillPreferenceCategory>
<PreferenceCategory
android:key="theme_customization_category"
android:title="@string/theme_customization_category"
android:order="1200"> <!-- Incremented by 100 from last order (i.e. 1100) -->
<ListPreference
android:key="android.theme.customization.accent_color"
android:title="@string/theme_customization_accent_color_title"/>
<ListPreference
android:key="android.theme.customization.font"
android:title="@string/theme_customization_font_title"/>
<ListPreference
android:key="android.theme.customization.adaptive_icon_shape"
android:title="@string/theme_customization_icon_shape_title"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -93,6 +93,7 @@
<SwitchPreference
android:key="display_white_balance"
android:title="@string/display_white_balance_title"
android:summary="@string/display_white_balance_summary"
settings:controller="com.android.settings.display.DisplayWhiteBalancePreferenceController" />
<Preference
@@ -118,12 +119,11 @@
android:fragment="com.android.settings.dream.DreamSettings"
settings:searchable="false" />
<com.android.settingslib.RestrictedPreference
<Preference
android:key="lockscreen_from_display_settings"
android:title="@string/lockscreen_settings_title"
android:fragment="com.android.settings.security.LockscreenDashboardFragment"
settings:controller="com.android.settings.security.screenlock.LockScreenPreferenceController"
settings:userRestriction="no_ambient_display" />
settings:controller="com.android.settings.security.screenlock.LockScreenPreferenceController" />
<SwitchPreference
android:key="camera_gesture"

View File

@@ -20,9 +20,11 @@
android:key="mobile_network_list_screen"
android:title="@string/network_settings_title">
<Preference
<com.android.settingslib.RestrictedPreference
android:key="add_more"
settings:isPreferenceVisible="false"
settings:userRestriction="no_config_mobile_networks"
settings:useAdminDisabledSummary="true"
android:title="@string/mobile_network_list_add_more"
android:icon="@drawable/ic_menu_add_activated_tint"
android:order="100" >
@@ -30,6 +32,6 @@
<extra android:name="android.telephony.euicc.extra.FORCE_PROVISION"
android:value="true"/>
</intent>
</Preference>
</com.android.settingslib.RestrictedPreference>
</PreferenceScreen>

View File

@@ -30,6 +30,13 @@
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_lock_screen_notif"/>
<SwitchPreference
android:key="security_dispaly_lockscreen_bypass"
android:title="@string/lockscreen_bypass_title"
android:summary="@string/lockscreen_bypass_summary"
settings:searchable="false"
settings:controller="com.android.settings.biometrics.face.FaceSettingsLockscreenBypassPreferenceController" />
<com.android.settingslib.RestrictedSwitchPreference
android:key="security_lockscreen_add_users_when_locked"
android:title="@string/user_add_on_lockscreen_menu"
@@ -53,11 +60,12 @@
android:title="@string/ambient_display_category_triggers"
android:order="1000">
<SwitchPreference
<com.android.settingslib.RestrictedSwitchPreference
android:key="ambient_display_always_on"
android:title="@string/doze_always_on_title"
android:summary="@string/doze_always_on_summary"
settings:controller="com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController" />
settings:controller="com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController"
settings:userRestriction="no_ambient_display" />
<Preference
android:key="ambient_display_tap"

View File

@@ -17,6 +17,7 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="security_settings_face_settings_page"
android:title="@string/security_settings_face_preference_title">
@@ -39,18 +40,17 @@
android:title="@string/security_settings_face_settings_use_face_for_apps"
app:keywords="@string/keywords_face_unlock"
app:controller="com.android.settings.biometrics.face.FaceSettingsAppPreferenceController"/>
<SwitchPreference
android:key="security_lockscreen_bypass"
android:title="@string/lockscreen_bypass_title"
android:summary="@string/lockscreen_bypass_summary"
settings:keywords="@string/keywords_lockscreen_bypass"
settings:controller="com.android.settings.biometrics.face.FaceSettingsLockscreenBypassPreferenceController" />
</PreferenceCategory>
<PreferenceCategory
android:key="security_settings_face_manage_category"
android:title="@string/security_settings_face_settings_require_category">
<SwitchPreference
android:key="security_settings_face_require_attention"
android:title="@string/security_settings_face_settings_require_attention"
android:summary="@string/security_settings_face_settings_require_attention_details"
app:keywords="@string/keywords_face_unlock"
app:controller="com.android.settings.biometrics.face.FaceSettingsAttentionPreferenceController"/>
<SwitchPreference
android:key="security_settings_face_require_confirmation"
android:title="@string/security_settings_face_settings_require_confirmation"

View File

@@ -26,6 +26,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SetupWizardUtils;
import com.android.settings.core.SubSettingLauncher;
@@ -97,6 +98,7 @@ public class AccessibilitySettingsForSetupWizardActivity extends SettingsActivit
super.onCreate(savedState);
tryLaunchFontSizeSettings();
findViewById(R.id.content_parent).setFitsSystemWindows(false);
}
@VisibleForTesting

View File

@@ -31,18 +31,17 @@ import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreference;
import com.android.internal.widget.SubtitleView;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.ToggleSwitch;
import com.android.settings.widget.ToggleSwitch.OnBeforeCheckedChangeListener;
import com.android.settingslib.accessibility.AccessibilityUtils;
import com.android.settingslib.widget.LayoutPreference;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
@@ -63,6 +62,7 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
private static final String PREF_TYPEFACE = "captioning_typeface";
private static final String PREF_LOCALE = "captioning_locale";
private static final String PREF_PRESET = "captioning_preset";
private static final String PREF_SWITCH = "captioning_preference_switch";
private static final String PREF_CUSTOM = "custom";
/** WebVtt specifies line height as 5.3% of the viewport height. */
@@ -72,10 +72,9 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
private SubtitleView mPreviewText;
private View mPreviewWindow;
private View mPreviewViewport;
private SwitchBar mSwitchBar;
private ToggleSwitch mToggleSwitch;
// Standard options.
private SwitchPreference mSwitch;
private LocalePreference mLocale;
private ListPreference mFontSize;
private PresetPreference mPreset;
@@ -94,6 +93,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
private boolean mShowingCustom;
private final List<Preference> mPreferenceList = new ArrayList<>();
@Override
public int getMetricsCategory() {
return SettingsEnums.ACCESSIBILITY_CAPTION_PROPERTIES;
@@ -110,31 +111,18 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
updateAllPreferences();
refreshShowingCustom();
installUpdateListeners();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final boolean enabled = mCaptioningManager.isEnabled();
SettingsActivity activity = (SettingsActivity) getActivity();
mSwitchBar = activity.getSwitchBar();
mSwitchBar.setSwitchBarText(R.string.accessibility_caption_master_switch_title,
R.string.accessibility_caption_master_switch_title);
mSwitchBar.setCheckedInternal(enabled);
mToggleSwitch = mSwitchBar.getSwitch();
getPreferenceScreen().setEnabled(enabled);
refreshPreviewText();
installSwitchBarToggleSwitch();
}
@Override
public void onDestroyView() {
super.onDestroyView();
removeSwitchBarToggleSwitch();
private void setPreferenceViewEnabled(boolean enabled) {
for (Preference preference : mPreferenceList) {
preference.setEnabled(enabled);
}
}
private void refreshPreferenceViewEnabled(boolean enabled) {
setPreferenceViewEnabled(enabled);
mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
}
private void refreshPreviewText() {
@@ -196,38 +184,10 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
}
}
protected void onInstallSwitchBarToggleSwitch() {
mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
@Override
public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
mSwitchBar.setCheckedInternal(checked);
Settings.Secure.putInt(getActivity().getContentResolver(),
Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, checked ? 1 : 0);
getPreferenceScreen().setEnabled(checked);
if (mPreviewText != null) {
mPreviewText.setVisibility(checked ? View.VISIBLE : View.INVISIBLE);
}
return false;
}
});
}
private void installSwitchBarToggleSwitch() {
onInstallSwitchBarToggleSwitch();
mSwitchBar.show();
}
private void removeSwitchBarToggleSwitch() {
mSwitchBar.hide();
mToggleSwitch.setOnBeforeCheckedChangeListener(null);
}
private void initializeAllPreferences() {
final LayoutPreference captionPreview = findPreference(PREF_CAPTION_PREVIEW);
final boolean enabled = mCaptioningManager.isEnabled();
mPreviewText = captionPreview.findViewById(R.id.preview_text);
mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
mPreviewWindow = captionPreview.findViewById(R.id.preview_window);
@@ -236,9 +196,6 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
-> refreshPreviewText());
mLocale = (LocalePreference) findPreference(PREF_LOCALE);
mFontSize = (ListPreference) findPreference(PREF_FONT_SIZE);
final Resources res = getResources();
final int[] presetValues = res.getIntArray(R.array.captioning_preset_selector_values);
final String[] presetTitles = res.getStringArray(R.array.captioning_preset_selector_titles);
@@ -246,6 +203,17 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
mPreset.setValues(presetValues);
mPreset.setTitles(presetTitles);
mSwitch = (SwitchPreference) findPreference(PREF_SWITCH);
mLocale = (LocalePreference) findPreference(PREF_LOCALE);
mFontSize = (ListPreference) findPreference(PREF_FONT_SIZE);
// Initialize the preference list
mPreferenceList.add(mLocale);
mPreferenceList.add(mFontSize);
mPreferenceList.add(mPreset);
refreshPreferenceViewEnabled(mCaptioningManager.isEnabled());
mCustom = (PreferenceCategory) findPreference(PREF_CUSTOM);
mShowingCustom = true;
@@ -304,6 +272,7 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
mWindowOpacity.setOnValueChangedListener(this);
mEdgeType.setOnValueChangedListener(this);
mSwitch.setOnPreferenceChangeListener(this);
mTypeface.setOnPreferenceChangeListener(this);
mFontSize.setOnPreferenceChangeListener(this);
mLocale.setOnPreferenceChangeListener(this);
@@ -338,6 +307,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
final String rawLocale = mCaptioningManager.getRawLocale();
mLocale.setValue(rawLocale == null ? "" : rawLocale);
mSwitch.setChecked(mCaptioningManager.isEnabled());
}
/**
@@ -431,16 +402,22 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
if (mTypeface == preference) {
Settings.Secure.putString(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE, (String) value);
refreshPreviewText();
} else if (mFontSize == preference) {
Settings.Secure.putFloat(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE,
Float.parseFloat((String) value));
refreshPreviewText();
} else if (mLocale == preference) {
Settings.Secure.putString(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE, (String) value);
refreshPreviewText();
} else if (mSwitch == preference) {
Settings.Secure.putInt(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, (boolean) value ? 1 : 0);
refreshPreferenceViewEnabled((boolean) value);
}
refreshPreviewText();
return true;
}
}

View File

@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
@@ -132,9 +134,10 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
if (info.getComponentName().equals(assignedComponentName)) {
final CharSequence assignedServiceName = info.getResolveInfo().loadLabel(
context.getPackageManager());
return context.getString(
R.string.accessibility_screen_magnification_navbar_configuration_warning,
assignedServiceName);
final int messageId = isGestureNavigateEnabled(context)
? R.string.accessibility_screen_magnification_gesture_navigation_warning
: R.string.accessibility_screen_magnification_navbar_configuration_warning;
return context.getString(messageId, assignedServiceName);
}
}
}
@@ -158,6 +161,12 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
}
private static boolean isGestureNavigateEnabled(Context context) {
return context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode)
== NAV_BAR_MODE_GESTURAL;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
@@ -173,4 +182,4 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
return isApplicable(context.getResources());
}
};
}
}

View File

@@ -31,6 +31,7 @@ import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppStorageSettings;
import com.android.settings.applications.FetchPackageStorageAsyncLoader;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
@@ -48,9 +49,12 @@ public class AppStoragePreferenceController extends AppInfoPreferenceControllerB
@Override
public void updateState(Preference preference) {
final boolean isExternal =
(mParent.getAppEntry().info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
preference.setSummary(getStorageSummary(mLastResult, isExternal));
final ApplicationsState.AppEntry entry = mParent.getAppEntry();
if (entry != null && entry.info != null) {
final boolean isExternal =
(entry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
preference.setSummary(getStorageSummary(mLastResult, isExternal));
}
}
@Override

View File

@@ -172,11 +172,11 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
if (mUserId == UserHandle.USER_NULL) {
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(titleResId),
null, null, challenge);
null, null, challenge, true /* foregroundOnly */);
} else {
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(titleResId),
null, null, challenge, mUserId);
null, null, challenge, mUserId, true /* foregroundOnly */);
}
if (!launchedConfirmationActivity) {
// This shouldn't happen, as we should only end up at this step if a lock thingy is

View File

@@ -47,6 +47,8 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
private boolean mHasPassword;
private boolean mBiometricUnlockDisabledByAdmin;
private TextView mErrorText;
protected boolean mConfirmingCredentials;
protected boolean mNextClicked;
/**
* @return true if the biometric is disabled by a device administrator
@@ -149,10 +151,12 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
if (!mHasPassword) {
// No password registered, launch into enrollment wizard.
mConfirmingCredentials = true;
launchChooseLock();
} else if (mToken == null) {
// It's possible to have a token but mLaunchedConfirmLock == false, since
// ChooseLockGeneric can pass us a token.
mConfirmingCredentials = true;
launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
}
}
@@ -182,6 +186,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
@Override
protected void onNextButtonClick(View view) {
mNextClicked = true;
if (checkMaxEnrolled() == 0) {
// Lock thingy is already set up, launch directly to the next page
launchNextEnrollingActivity(mToken);
@@ -249,12 +254,14 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
mConfirmingCredentials = false;
return;
} else {
setResult(resultCode, data);
finish();
}
} else if (requestCode == CONFIRM_REQUEST) {
mConfirmingCredentials = false;
if (resultCode == RESULT_OK && data != null) {
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);

View File

@@ -60,6 +60,8 @@ public class FaceEnrollAccessibilityToggle extends LinearLayout {
}
mSwitch = findViewById(R.id.toggle);
mSwitch.setChecked(false);
mSwitch.setClickable(false);
mSwitch.setFocusable(false);
}
public boolean isChecked() {

View File

@@ -16,7 +16,6 @@
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;
@@ -50,8 +49,6 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
private static final String TAG = "FaceEducation";
private static final int ON = 1;
private static final int OFF = 0;
// 8 seconds.
private static final long FACE_ENROLL_EDUCATION_DELAY = 8000;
private FaceManager mFaceManager;
private FaceEnrollAccessibilityToggle mSwitchDiversity;
@@ -61,6 +58,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
private Handler mHandler;
private Intent mResultIntent;
private TextView mDescriptionText;
private boolean mNextClicked;
private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
new CompoundButton.OnCheckedChangeListener() {
@@ -101,14 +99,26 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
mDescriptionText = findViewById(R.id.sud_layout_description);
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()
);
if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
mFooterBarMixin.setSecondaryButton(
new FooterButton.Builder(this)
.setText(R.string.skip_label)
.setListener(this::onSkipButtonClick)
.setButtonType(FooterButton.ButtonType.SKIP)
.setTheme(R.style.SudGlifButton_Secondary)
.build()
);
} else {
mFooterBarMixin.setSecondaryButton(
new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_introduction_cancel)
.setListener(this::onSkipButtonClick)
.setButtonType(FooterButton.ButtonType.CANCEL)
.setTheme(R.style.SudGlifButton_Secondary)
.build()
);
}
final FooterButton footerButton = new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_education_start)
@@ -121,24 +131,15 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
final AccessibilityManager accessibilityManager = getApplicationContext().getSystemService(
AccessibilityManager.class);
if (accessibilityManager != null) {
accessibilityEnabled = accessibilityManager.isEnabled();
// Add additional check for touch exploration. This prevents other accessibility
// features such as Live Transcribe from defaulting to the accessibility setup.
accessibilityEnabled = accessibilityManager.isEnabled()
&& accessibilityManager.isTouchExplorationEnabled();
}
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 && !accessibilityEnabled) {
Settings.Secure.putIntForUser(context.getContentResolver(),
FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, ON, mUserId);
footerButton.setEnabled(false);
mHandler.postDelayed(() -> {
footerButton.setEnabled(true);
}, FACE_ENROLL_EDUCATION_DELAY);
}
final Button accessibilityButton = findViewById(R.id.accessibility_button);
accessibilityButton.setOnClickListener(view -> {
footerButton.setEnabled(true);
mSwitchDiversity.setChecked(true);
accessibilityButton.setVisibility(View.GONE);
mSwitchDiversity.setVisibility(View.VISIBLE);
@@ -146,6 +147,9 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
mSwitchDiversity = findViewById(R.id.toggle_diversity);
mSwitchDiversity.setListener(mSwitchDiversityListener);
mSwitchDiversity.setOnClickListener(v -> {
mSwitchDiversity.getSwitch().toggle();
});
if (accessibilityEnabled) {
accessibilityButton.callOnClick();
@@ -157,6 +161,26 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
super.onResume();
mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
mSwitchDiversity.isChecked());
// If the user goes back after enrollment, we should send them back to the intro page
// if they've met the max limit.
final int max = getResources().getInteger(
com.android.internal.R.integer.config_faceMaxTemplatesPerUser);
final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
if (numEnrolledFaces >= max) {
finish();
}
}
@Override
protected void onStop() {
super.onStop();
if (!isChangingConfigurations() && !WizardManagerHelper.isAnySetupWizard(getIntent())
&& !mNextClicked) {
setResult(RESULT_SKIP);
finish();
}
}
@Override
@@ -168,6 +192,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
final String flattenedString = getString(R.string.config_face_enroll);
if (!TextUtils.isEmpty(flattenedString)) {
ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
@@ -175,11 +200,12 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
} else {
intent.setClass(this, FaceEnrollEnrolling.class);
}
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
if (mResultIntent != null) {
intent.putExtras(mResultIntent);
}
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
mNextClicked = true;
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
}

View File

@@ -32,6 +32,7 @@ import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricEnrollSidecar;
import com.android.settings.biometrics.BiometricErrorDialog;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
import com.android.settings.slices.CustomSliceRegistry;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
@@ -184,6 +185,10 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
// TODO: Have this match any animations that UX comes up with
if (remaining == 0) {
// Force the reload of the FaceEnroll slice in case a user has enrolled,
// this will cause the slice to no longer appear.
getApplicationContext().getContentResolver().notifyChange(
CustomSliceRegistry.FACE_ENROLL_SLICE_URI, null);
launchFinish(mToken);
}
}

View File

@@ -77,6 +77,16 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
);
}
@Override
protected void onStop() {
super.onStop();
if (!isChangingConfigurations() && !mConfirmingCredentials && !mNextClicked
&& !WizardManagerHelper.isAnySetupWizard(getIntent())) {
finish();
}
}
@Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(

View File

@@ -52,7 +52,7 @@ public class FaceEnrollSidecar extends BiometricEnrollSidecar {
mFaceManager.setActiveUser(mUserId);
}
mFaceManager.enroll(mToken, mEnrollmentCancel,
mFaceManager.enroll(mUserId, mToken, mEnrollmentCancel,
mEnrollmentCallback, mDisabledFeatures);
}

View File

@@ -19,14 +19,30 @@ package com.android.settings.biometrics.face;
import android.content.Context;
import android.os.UserHandle;
import com.android.settings.R;
import androidx.preference.Preference;
public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceController {
public static final String KEY_FACE_SETTINGS = "face_settings_profile";
private static final String KEY_FACE_SETTINGS = "face_settings_profile";
public FaceProfileStatusPreferenceController(Context context) {
super(context, KEY_FACE_SETTINGS);
}
@Override
public int getAvailabilityStatus() {
// Check if Face for Profile is available.
final int isAvailable = super.getAvailabilityStatus();
if (isAvailable != AVAILABLE) {
return isAvailable;
}
// Make the profile unsearchable so the user preference controller gets highlighted
// when searched for.
return AVAILABLE_UNSEARCHABLE;
}
@Override
protected boolean isUserSupported() {
return mProfileChallengeUserId != UserHandle.USER_NULL
@@ -37,4 +53,11 @@ public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceC
protected int getUserId() {
return mProfileChallengeUserId;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
preference.setTitle(mContext.getResources().getString(
R.string.security_settings_face_profile_preference_title));
}
}

View File

@@ -60,7 +60,6 @@ public class FaceSettings extends DashboardFragment {
private FaceManager mFaceManager;
private int mUserId;
private byte[] mToken;
private FaceSettingsAttentionPreferenceController mAttentionController;
private FaceSettingsRemoveButtonPreferenceController mRemoveController;
private FaceSettingsEnrollButtonPreferenceController mEnrollController;
private List<AbstractPreferenceController> mControllers;
@@ -69,6 +68,8 @@ public class FaceSettings extends DashboardFragment {
private Preference mRemoveButton;
private Preference mEnrollButton;
private boolean mConfirmingPassword;
private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
// Disable the toggles until the user re-enrolls
@@ -117,12 +118,18 @@ public class FaceSettings extends DashboardFragment {
mUserId = getActivity().getIntent().getIntExtra(
Intent.EXTRA_USER_ID, UserHandle.myUserId());
if (mUserManager.getUserInfo(mUserId).isManagedProfile()) {
getActivity().setTitle(getActivity().getResources().getString(
R.string.security_settings_face_profile_preference_title));
}
Preference keyguardPref = findPreference(FaceSettingsKeyguardPreferenceController.KEY);
Preference appPref = findPreference(FaceSettingsAppPreferenceController.KEY);
Preference attentionPref = findPreference(FaceSettingsAttentionPreferenceController.KEY);
Preference confirmPref = findPreference(FaceSettingsConfirmPreferenceController.KEY);
Preference bypassPref =
findPreference(FaceSettingsLockscreenBypassPreferenceController.KEY);
mTogglePreferences = new ArrayList<>(
Arrays.asList(keyguardPref, appPref, attentionPref, confirmPref));
Arrays.asList(keyguardPref, appPref, confirmPref, bypassPref));
mRemoveButton = findPreference(FaceSettingsRemoveButtonPreferenceController.KEY);
mEnrollButton = findPreference(FaceSettingsEnrollButtonPreferenceController.KEY);
@@ -145,24 +152,27 @@ public class FaceSettings extends DashboardFragment {
if (savedInstanceState != null) {
mToken = savedInstanceState.getByteArray(KEY_TOKEN);
}
if (mToken == null) {
final long challenge = mFaceManager.generateChallenge();
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(R.string.security_settings_face_preference_title),
null, null, challenge, mUserId)) {
Log.e(TAG, "Password not set");
finish();
}
}
}
@Override
public void onResume() {
super.onResume();
if (mToken != null) {
mAttentionController.setToken(mToken);
if (mToken == null && !mConfirmingPassword) {
// Generate challenge in onResume instead of onCreate, since FaceSettings can be
// created while Keyguard is showing, in which case the resetLockout revokeChallenge
// will invalidate the too-early created challenge here.
final long challenge = mFaceManager.generateChallenge();
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
mConfirmingPassword = true;
if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(R.string.security_settings_face_preference_title),
null, null, challenge, mUserId, true /* foregroundOnly */)) {
Log.e(TAG, "Password not set");
finish();
}
} else {
mEnrollController.setToken(mToken);
}
@@ -175,6 +185,7 @@ public class FaceSettings extends DashboardFragment {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CONFIRM_REQUEST) {
mConfirmingPassword = false;
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
mFaceManager.setActiveUser(mUserId);
// The pin/pattern/password was set.
@@ -182,7 +193,6 @@ public class FaceSettings extends DashboardFragment {
mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
if (mToken != null) {
mAttentionController.setToken(mToken);
mEnrollController.setToken(mToken);
}
}
@@ -196,16 +206,28 @@ public class FaceSettings extends DashboardFragment {
}
@Override
public void onDestroy() {
super.onDestroy();
if (getActivity().isFinishing()) {
final int result = mFaceManager.revokeChallenge();
if (result < 0) {
Log.w(TAG, "revokeChallenge failed, result: " + result);
public void onStop() {
super.onStop();
if (!mEnrollController.isClicked() && !getActivity().isChangingConfigurations()
&& !mConfirmingPassword) {
// Revoke challenge and finish
if (mToken != null) {
final int result = mFaceManager.revokeChallenge();
if (result < 0) {
Log.w(TAG, "revokeChallenge failed, result: " + result);
}
mToken = null;
}
getActivity().finish();
}
}
@Override
public int getHelpResource() {
return R.string.help_url_face;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
if (!isAvailable(context)) {
@@ -214,9 +236,7 @@ public class FaceSettings extends DashboardFragment {
mControllers = buildPreferenceControllers(context, getSettingsLifecycle());
// There's no great way of doing this right now :/
for (AbstractPreferenceController controller : mControllers) {
if (controller instanceof FaceSettingsAttentionPreferenceController) {
mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
} else if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
mRemoveController = (FaceSettingsRemoveButtonPreferenceController) controller;
mRemoveController.setListener(mRemovalListener);
mRemoveController.setActivity((SettingsActivity) getActivity());
@@ -235,7 +255,6 @@ public class FaceSettings extends DashboardFragment {
controllers.add(new FaceSettingsVideoPreferenceController(context));
controllers.add(new FaceSettingsKeyguardPreferenceController(context));
controllers.add(new FaceSettingsAppPreferenceController(context));
controllers.add(new FaceSettingsAttentionPreferenceController(context));
controllers.add(new FaceSettingsRemoveButtonPreferenceController(context));
controllers.add(new FaceSettingsFooterPreferenceController(context));
controllers.add(new FaceSettingsConfirmPreferenceController(context));

View File

@@ -78,6 +78,19 @@ public class FaceSettingsAppPreferenceController extends FaceSettingsPreferenceC
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
if(mFaceManager == null){
return AVAILABLE_UNSEARCHABLE;
}
// By only allowing this preference controller to be searchable when the feature is turned
// off, it will give preference to the face setup controller.
final boolean hasEnrolledUser = mFaceManager.hasEnrolledTemplates(getUserId());
final boolean appUnlockEnabled = Settings.Secure.getIntForUser(
mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED, OFF, getUserId()) == ON;
if (hasEnrolledUser && !appUnlockEnabled) {
return AVAILABLE;
} else {
return AVAILABLE_UNSEARCHABLE;
}
}
}

View File

@@ -99,7 +99,8 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
}
// Set to disabled until we know the true value.
mPreference.setEnabled(false);
mFaceManager.getFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, mGetFeatureCallback);
mFaceManager.getFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION,
mGetFeatureCallback);
// Ideally returns a cached value.
return true;
@@ -111,8 +112,8 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
mPreference.setEnabled(false);
mPreference.setChecked(isChecked);
mFaceManager.setFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked, mToken,
mSetFeatureCallback);
mFaceManager.setFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked,
mToken, mSetFeatureCallback);
return true;
}

View File

@@ -42,6 +42,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
private byte[] mToken;
private SettingsActivity mActivity;
private Button mButton;
private boolean mIsClicked;
public FaceSettingsEnrollButtonPreferenceController(Context context) {
this(context, KEY);
@@ -63,6 +64,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
@Override
public void onClick(View v) {
mIsClicked = true;
final Intent intent = new Intent();
intent.setClassName("com.android.settings", FaceEnrollIntroduction.class.getName());
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
@@ -83,6 +85,13 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
mToken = token;
}
// Return the click state, then clear its state.
public boolean isClicked() {
final boolean wasClicked = mIsClicked;
mIsClicked = false;
return wasClicked;
}
public void setActivity(SettingsActivity activity) {
mActivity = activity;
}

View File

@@ -18,16 +18,13 @@ package com.android.settings.biometrics.face;
import static android.provider.Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.hardware.face.FaceManager;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.settings.Utils;
import com.android.settings.core.TogglePreferenceController;
/**
* Preference controller for Face settings page controlling the ability to unlock the phone
@@ -87,13 +84,4 @@ public class FaceSettingsKeyguardPreferenceController extends FaceSettingsPrefer
preference.setEnabled(true);
}
}
private boolean adminDisabled() {
DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
return dpm != null &&
(dpm.getKeyguardDisabledFeatures(null, UserHandle.myUserId())
& DevicePolicyManager.KEYGUARD_DISABLE_FACE)
!= 0;
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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
*/
package com.android.settings.biometrics.face;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting;
public class FaceSettingsLockscreenBypassPreferenceController
extends FaceSettingsPreferenceController {
static final String KEY = "security_lockscreen_bypass";
@VisibleForTesting
protected FaceManager mFaceManager;
private UserManager mUserManager;
public FaceSettingsLockscreenBypassPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
mFaceManager = context.getSystemService(FaceManager.class);
}
mUserManager = context.getSystemService(UserManager.class);
}
@Override
public boolean isChecked() {
boolean defaultValue = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_faceAuthDismissesKeyguard);
return Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, defaultValue ? 1 : 0) != 0;
}
@Override
public boolean setChecked(boolean isChecked) {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, isChecked ? 1 : 0);
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (!FaceSettings.isAvailable(mContext)) {
preference.setEnabled(false);
} else if (adminDisabled()) {
preference.setEnabled(false);
} else if (!mFaceManager.hasEnrolledTemplates(getUserId())) {
preference.setEnabled(false);
} else {
preference.setEnabled(true);
}
}
@Override
public int getAvailabilityStatus() {
if (mUserManager.isManagedProfile(UserHandle.myUserId())) {
return UNSUPPORTED_ON_DEVICE;
}
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
return mFaceManager.hasEnrolledTemplates() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
} else {
return UNSUPPORTED_ON_DEVICE;
}
}
}

View File

@@ -16,7 +16,9 @@
package com.android.settings.biometrics.face;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.UserHandle;
import com.android.settings.core.TogglePreferenceController;
@@ -38,4 +40,13 @@ public abstract class FaceSettingsPreferenceController extends TogglePreferenceC
protected int getUserId() {
return mUserId;
}
protected boolean adminDisabled() {
DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
return dpm != null &&
(dpm.getKeyguardDisabledFeatures(null, UserHandle.myUserId())
& DevicePolicyManager.KEYGUARD_DISABLE_FACE)
!= 0;
}
}

View File

@@ -64,7 +64,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
builder.setTitle(R.string.security_settings_face_settings_remove_dialog_title)
.setMessage(R.string.security_settings_face_settings_remove_dialog_details)
.setPositiveButton(R.string.okay, mOnClickListener)
.setPositiveButton(R.string.delete, mOnClickListener)
.setNegativeButton(R.string.cancel, mOnClickListener);
AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);

View File

@@ -26,7 +26,7 @@ import com.android.settings.biometrics.BiometricStatusPreferenceController;
public class FaceStatusPreferenceController extends BiometricStatusPreferenceController {
private static final String KEY_FACE_SETTINGS = "face_settings";
public static final String KEY_FACE_SETTINGS = "face_settings";
protected final FaceManager mFaceManager;

View File

@@ -617,7 +617,7 @@ public class FingerprintSettings extends SubSettings {
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(R.string.security_settings_fingerprint_preference_title),
null, null, challenge, mUserId)) {
null, null, challenge, mUserId, true /* foregroundOnly */)) {
intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName());
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);

View File

@@ -494,12 +494,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle));
controllers.add(new AutofillResetOptionsPreferenceController(context));
controllers.add(new OverlayCategoryPreferenceController(context,
"android.theme.customization.accent_color"));
controllers.add(new OverlayCategoryPreferenceController(context,
"android.theme.customization.font"));
controllers.add(new OverlayCategoryPreferenceController(context,
"android.theme.customization.adaptive_icon_shape"));
controllers.add(new TrustAgentsExtendUnlockPreferenceController(context));
controllers.add(new TrustLostLocksScreenPreferenceController(context));
return controllers;

View File

@@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -28,9 +29,20 @@ import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.TimeZone;
public class MainlineModuleVersionPreferenceController extends BasePreferenceController {
private static final String TAG = "MainlineModuleControl";
private static final List<String> VERSION_NAME_DATE_PATTERNS = Arrays.asList("yyyy-MM-dd",
"yyyy-MM");
@VisibleForTesting
static final Intent MODULE_UPDATE_INTENT =
@@ -81,6 +93,30 @@ public class MainlineModuleVersionPreferenceController extends BasePreferenceCon
@Override
public CharSequence getSummary() {
return mModuleVersion;
if (TextUtils.isEmpty(mModuleVersion)) {
return mModuleVersion;
}
final Optional<Date> parsedDate = parseDateFromVersionName(mModuleVersion);
if (!parsedDate.isPresent()) {
Log.w("Could not parse mainline versionName (%s) as date.", mModuleVersion);
return mModuleVersion;
}
return DateFormat.getLongDateFormat(mContext).format(parsedDate.get());
}
private Optional<Date> parseDateFromVersionName(String text) {
for (String pattern : VERSION_NAME_DATE_PATTERNS) {
try {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern,
Locale.getDefault());
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return Optional.of(simpleDateFormat.parse(text));
} catch (ParseException e) {
// ignore and try next pattern
}
}
return Optional.empty();
}
}

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import androidx.preference.Preference;
public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPreferenceController {
public AdaptiveSleepDetailPreferenceController(Context context, String key) {
super(context, key);
}
@@ -42,6 +43,6 @@ public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPrefer
@Override
public void updateState(Preference preference) {
super.updateState(preference);
preference.setEnabled(super.hasSufficientPermissions);
preference.setEnabled(hasSufficientPermission(mContext.getPackageManager()));
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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
*/
package com.android.settings.display;
import static com.android.settings.display.AdaptiveSleepPreferenceController.hasSufficientPermission;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
public class AdaptiveSleepPermissionPreferenceController extends BasePreferenceController {
final static String PREF_NAME = "adaptive_sleep_permission";
private final Intent mIntent;
public AdaptiveSleepPermissionPreferenceController(Context context, String key) {
super(context, key);
final String packageName = context.getPackageManager().getAttentionServicePackageName();
mIntent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
mIntent.setData(Uri.parse("package:" + packageName));
}
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
return AVAILABLE_UNSEARCHABLE;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
mContext.startActivity(mIntent);
return true;
}
return super.handlePreferenceTreeClick(preference);
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
preference.setVisible(!hasSufficientPermission(mContext.getPackageManager()));
}
}
}

View File

@@ -25,28 +25,20 @@ import com.android.settings.core.TogglePreferenceController;
public class AdaptiveSleepPreferenceController extends TogglePreferenceController {
private final String SYSTEM_KEY = ADAPTIVE_SLEEP;
private final int DEFAULT_VALUE = 0;
final boolean hasSufficientPermissions;
public static final String PREF_NAME = "adaptive_sleep";
private static final String SYSTEM_KEY = ADAPTIVE_SLEEP;
private static final int DEFAULT_VALUE = 0;
public AdaptiveSleepPreferenceController(Context context, String key) {
super(context, key);
final PackageManager packageManager = mContext.getPackageManager();
final String attentionPackage = packageManager.getAttentionServicePackageName();
hasSufficientPermissions = attentionPackage != null && packageManager.checkPermission(
Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
}
@Override
public boolean isChecked() {
return hasSufficientPermissions && Settings.System.getInt(mContext.getContentResolver(),
SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
return hasSufficientPermission(mContext.getPackageManager()) && Settings.System.getInt(
mContext.getContentResolver(), SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
}
@Override
public boolean setChecked(boolean isChecked) {
Settings.System.putInt(mContext.getContentResolver(), SYSTEM_KEY,
@@ -57,10 +49,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_adaptive_sleep_available)
? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
return isControllerAvailable(mContext);
}
@Override
@@ -69,4 +58,17 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
? R.string.adaptive_sleep_summary_on
: R.string.adaptive_sleep_summary_off);
}
public static int isControllerAvailable(Context context) {
return context.getResources().getBoolean(
com.android.internal.R.bool.config_adaptive_sleep_available)
? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
}
static boolean hasSufficientPermission(PackageManager packageManager) {
final String attentionPackage = packageManager.getAttentionServicePackageName();
return attentionPackage != null && packageManager.checkPermission(
Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
}
}

View File

@@ -16,11 +16,16 @@
package com.android.settings.display;
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF;
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_INTERACTED;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -34,14 +39,28 @@ import java.util.List;
public class AdaptiveSleepSettings extends DashboardFragment {
private static final String TAG = "AdaptiveSleepSettings";
private Context mContext;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final FooterPreference footerPreference =
mFooterPreferenceMixin.createFooterPreference();
mContext = getContext();
footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp);
footerPreference.setTitle(R.string.adaptive_sleep_privacy);
Preference permissionPreference = findPreference(
AdaptiveSleepPermissionPreferenceController.PREF_NAME);
if (permissionPreference != null) {
permissionPreference.setVisible(false);
}
mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE)
.edit()
.putBoolean(PREF_KEY_INTERACTED, true)
.apply();
}
@Override

View File

@@ -213,5 +213,13 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
sir.xmlResId = R.xml.color_mode_settings;
return Arrays.asList(sir);
}
@Override
protected boolean isPageSearchEnabled(Context context) {
final int[] availableColorModes = context.getResources().getIntArray(
com.android.internal.R.array.config_availableColorModes);
return availableColorModes != null && availableColorModes.length > 0
&& !ColorDisplayManager.areAccessibilityTransformsEnabled(context);
}
};
}

View File

@@ -1,62 +0,0 @@
/*
* 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
*/
package com.android.settings.gestures;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
/**
* Dialog to notify user that gesture navigation is not available because of unsupported launcher.
*/
public class GestureNavigationNotAvailableDialog extends InstrumentedDialogFragment {
private static final String TAG = "GestureNavigationNotAvailableDialog";
public static void show(SystemNavigationGestureSettings parent) {
if (!parent.isAdded()) {
return;
}
final GestureNavigationNotAvailableDialog dialog =
new GestureNavigationNotAvailableDialog();
dialog.setTargetFragment(parent, 0);
dialog.show(parent.getFragmentManager(), TAG);
}
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_GESTURE_NAV_NOT_AVAILABLE_DLG;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity();
final String defaultHomeAppName = SystemNavigationPreferenceController
.getDefaultHomeAppName(context);
final String message = getString(R.string.gesture_not_supported_dialog_message,
defaultHomeAppName);
return new AlertDialog.Builder(context)
.setMessage(message)
.setPositiveButton(R.string.okay, null)
.create();
}
}

View File

@@ -22,7 +22,6 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVE
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE;
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_INFO;
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_SETTING;
import android.accessibilityservice.AccessibilityServiceInfo;
@@ -160,17 +159,9 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
RadioButtonPreferenceWithExtraWidget p = (RadioButtonPreferenceWithExtraWidget) pref;
if (info.getKey() == KEY_SYSTEM_NAV_GESTURAL) {
if (SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(
getContext())) {
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING);
p.setExtraWidgetOnClickListener((v) -> GestureNavigationBackSensitivityDialog
.show(this, getBackSensitivity(getContext(), mOverlayManager)));
} else {
p.setEnabled(false);
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_INFO);
p.setExtraWidgetOnClickListener((v) ->
GestureNavigationNotAvailableDialog.show(this));
}
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING);
p.setExtraWidgetOnClickListener((v) -> GestureNavigationBackSensitivityDialog
.show(this, getBackSensitivity(getContext(), mOverlayManager)));
} else {
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE);
}
@@ -219,12 +210,6 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
@Override
protected boolean setDefaultKey(String key) {
final Context c = getContext();
if (key == KEY_SYSTEM_NAV_GESTURAL &&
!SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(c)) {
// This should not happen since the preference is disabled. Return to be safe.
return false;
}
setCurrentSystemNavigationMode(c, mOverlayManager, key);
setIllustrationVideo(mVideoPreference, key);
if (TextUtils.equals(KEY_SYSTEM_NAV_GESTURAL, key) && (

View File

@@ -22,14 +22,11 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import java.util.ArrayList;
public class SystemNavigationPreferenceController extends BasePreferenceController {
static final String PREF_KEY_SYSTEM_NAVIGATION = "gesture_system_navigation";
@@ -101,31 +98,4 @@ public class SystemNavigationPreferenceController extends BasePreferenceControll
return NAV_BAR_MODE_GESTURAL == context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode);
}
static boolean isGestureNavSupportedByDefaultLauncher(Context context) {
final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
if (cn == null) {
// There is no default home app set for the current user, don't make any changes yet.
return true;
}
ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString(
com.android.internal.R.string.config_recentsComponentName));
return recentsComponentName.getPackageName().equals(cn.getPackageName());
}
static String getDefaultHomeAppName(Context context) {
final PackageManager pm = context.getPackageManager();
final ComponentName cn = pm.getHomeActivities(new ArrayList<>());
if (cn != null) {
try {
ApplicationInfo ai = pm.getApplicationInfo(cn.getPackageName(), 0);
if (ai != null) {
return pm.getApplicationLabel(ai).toString();
}
} catch (final PackageManager.NameNotFoundException e) {
// Do nothing
}
}
return "";
}
}

View File

@@ -64,12 +64,28 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
.setCardName(contextualNotificationChannelSliceUri)
.setCardCategory(ContextualCard.Category.POSSIBLE)
.build();
final String contextualAdaptiveSleepSliceUri =
CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI.toString();
final ContextualCard contextualAdaptiveSleepCard =
ContextualCard.newBuilder()
.setSliceUri(contextualAdaptiveSleepSliceUri)
.setCardName(contextualAdaptiveSleepSliceUri)
.setCardCategory(ContextualCard.Category.DEFAULT)
.build();
final ContextualCard contextualFaceSettingsCard =
ContextualCard.newBuilder()
.setSliceUri(CustomSliceRegistry.FACE_ENROLL_SLICE_URI.toString())
.setCardName(CustomSliceRegistry.FACE_ENROLL_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.DEFAULT)
.build();
final ContextualCardList cards = ContextualCardList.newBuilder()
.addCard(wifiCard)
.addCard(connectedDeviceCard)
.addCard(lowStorageCard)
.addCard(batteryFixCard)
.addCard(notificationChannelCard)
.addCard(contextualAdaptiveSleepCard)
.addCard(contextualFaceSettingsCard)
.build();
return cards;

View File

@@ -0,0 +1,156 @@
/*
* 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
*/
package com.android.settings.homepage.contextualcards.slices;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.display.AdaptiveSleepPreferenceController.PREF_NAME;
import static com.android.settings.display.AdaptiveSleepPreferenceController.isControllerAvailable;
import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.display.AdaptiveSleepSettings;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBuilderUtils;
import com.google.common.annotations.VisibleForTesting;
import java.util.concurrent.TimeUnit;
public class ContextualAdaptiveSleepSlice implements CustomSliceable {
private static final String TAG = "ContextualAdaptiveSleepSlice";
private static final long DEFAULT_SETUP_TIME = 0;
private Context mContext;
@VisibleForTesting
static final long DEFERRED_TIME_DAYS = TimeUnit.DAYS.toMillis(14);
@VisibleForTesting
static final String PREF_KEY_SETUP_TIME = "adaptive_sleep_setup_time";
public static final String PREF_KEY_INTERACTED = "adaptive_sleep_interacted";
public static final String PREF = "adaptive_sleep_slice";
public ContextualAdaptiveSleepSlice(Context context) {
mContext = context;
}
@Override
public Slice getSlice() {
final long setupTime = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getLong(
PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
if (setupTime == DEFAULT_SETUP_TIME) {
// Set the first setup time.
mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE)
.edit()
.putLong(PREF_KEY_SETUP_TIME, System.currentTimeMillis())
.apply();
return null;
}
// Display the contextual card only if all the following 3 conditions hold:
// 1. The Screen Attention is enabled in Settings.
// 2. The device is not recently set up.
// 3. Current user hasn't opened Screen Attention's settings page before.
if (isSettingsAvailable() && !isUserInteracted() && !isRecentlySetup()) {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_adaptive_sleep);
final CharSequence title = mContext.getText(R.string.adaptive_sleep_title);
final CharSequence subtitle = mContext.getText(
R.string.adaptive_sleep_contextual_slice_summary);
final SliceAction pAction = SliceAction.createDeeplink(getPrimaryAction(),
icon,
ListBuilder.ICON_IMAGE,
title);
final ListBuilder listBuilder = new ListBuilder(mContext,
CONTEXTUAL_ADAPTIVE_SLEEP_URI,
ListBuilder.INFINITY)
.setAccentColor(COLOR_NOT_TINTED)
.addRow(new ListBuilder.RowBuilder()
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setTitle(title)
.setSubtitle(subtitle)
.setPrimaryAction(pAction));
return listBuilder.build();
} else {
return null;
}
}
@Override
public Uri getUri() {
return CONTEXTUAL_ADAPTIVE_SLEEP_URI;
}
@Override
public Intent getIntent() {
final CharSequence screenTitle = mContext.getText(R.string.adaptive_sleep_title);
final Uri contentUri = new Uri.Builder().appendPath(PREF_NAME).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
AdaptiveSleepSettings.class.getName(), PREF_NAME, screenTitle.toString(),
SettingsEnums.SLICE).setClassName(mContext.getPackageName(),
SubSettings.class.getName()).setData(contentUri);
}
private PendingIntent getPrimaryAction() {
final Intent intent = getIntent();
return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
}
/**
* @return {@code true} if the current user has opened the Screen Attention settings page
* before, otherwise {@code false}.
*/
private boolean isUserInteracted() {
return mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getBoolean(
PREF_KEY_INTERACTED, false);
}
/**
* The device is recently set up means its first settings-open time is within 2 weeks ago.
*
* @return {@code true} if the device is recently set up, otherwise {@code false}.
*/
private boolean isRecentlySetup() {
final long endTime = System.currentTimeMillis() - DEFERRED_TIME_DAYS;
final long firstSetupTime = mContext.getSharedPreferences(PREF,
Context.MODE_PRIVATE).getLong(PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
return firstSetupTime > endTime;
}
/**
* Check whether the screen attention settings is enabled. Contextual card will only appear
* when the screen attention settings is available.
*
* @return {@code true} if screen attention settings is enabled, otherwise {@code false}
*/
@VisibleForTesting
boolean isSettingsAvailable() {
return isControllerAvailable(mContext) == AVAILABLE_UNSEARCHABLE;
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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
*/
package com.android.settings.homepage.contextualcards.slices;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricManager;
import android.hardware.face.FaceManager;
import android.net.Uri;
import android.os.UserHandle;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.biometrics.face.FaceStatusPreferenceController;
import com.android.settings.security.SecuritySettings;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBuilderUtils;
public class FaceSetupSlice implements CustomSliceable {
private final Context mContext;
public FaceSetupSlice(Context context) {
mContext = context;
}
@Override
public Slice getSlice() {
final FaceManager faceManager = Utils.getFaceManagerOrNull(mContext);
if (faceManager == null || faceManager.hasEnrolledTemplates(UserHandle.myUserId())) {
return null;
}
final CharSequence title = mContext.getText(
R.string.security_settings_face_settings_enroll);
final ListBuilder listBuilder = new ListBuilder(mContext,
CustomSliceRegistry.FACE_ENROLL_SLICE_URI, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_face_24dp);
return listBuilder
.addRow(buildRowBuilder(title,
mContext.getText(R.string.security_settings_face_settings_context_subtitle),
icon, mContext, getIntent()))
.build();
}
@Override
public Uri getUri() {
return CustomSliceRegistry.FACE_ENROLL_SLICE_URI;
}
@Override
public Intent getIntent() {
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
SecuritySettings.class.getName(),
FaceStatusPreferenceController.KEY_FACE_SETTINGS,
mContext.getText(R.string.security_settings_face_settings_enroll).toString(),
SettingsEnums.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
private static RowBuilder buildRowBuilder(CharSequence title, CharSequence subTitle,
IconCompat icon, Context context, Intent intent) {
final SliceAction primarySliceAction = SliceAction.createDeeplink(
PendingIntent.getActivity(context, 0, intent, 0), icon, ListBuilder.ICON_IMAGE,
title);
return new RowBuilder()
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setTitle(title)
.setSubtitle(subTitle)
.setPrimaryAction(primarySliceAction);
}
}

View File

@@ -130,7 +130,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
}
private void update() {
if (mPreference == null) {
if (mPreference == null || mPreference.isDisabledByAdmin()) {
return;
}
refreshSummary(mPreference);

View File

@@ -55,7 +55,7 @@ public class TetherProvisioningActivity extends Activity {
final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
final int subId = SubscriptionManager.getActiveDataSubscriptionId();
if (tetherSubId != subId) {
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
return;
@@ -67,6 +67,7 @@ public class TetherProvisioningActivity extends Activity {
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(provisionApp[0], provisionApp[1]);
intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
if (DEBUG) {
Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]);
}

View File

@@ -16,7 +16,13 @@
package com.android.settings.network.telephony;
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
@@ -25,8 +31,12 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
@@ -37,17 +47,27 @@ import com.android.settings.R;
*/
public class EnabledNetworkModePreferenceController extends
TelephonyBasePreferenceController implements
ListPreference.OnPreferenceChangeListener {
ListPreference.OnPreferenceChangeListener, LifecycleObserver {
private CarrierConfigManager mCarrierConfigManager;
private ContentObserver mPreferredNetworkModeObserver;
private TelephonyManager mTelephonyManager;
private boolean mIsGlobalCdma;
@VisibleForTesting
boolean mShow4GForLTE;
private Preference mPreference;
public EnabledNetworkModePreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
mPreferredNetworkModeObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
if (mPreference != null) {
updateState(mPreference);
}
}
};
}
@Override
@@ -78,6 +98,24 @@ public class EnabledNetworkModePreferenceController extends
return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@OnLifecycleEvent(ON_START)
public void onStart() {
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + mSubId), true,
mPreferredNetworkModeObserver);
}
@OnLifecycleEvent(ON_STOP)
public void onStop() {
mContext.getContentResolver().unregisterContentObserver(mPreferredNetworkModeObserver);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
@@ -102,7 +140,7 @@ public class EnabledNetworkModePreferenceController extends
return false;
}
public void init(int subId) {
public void init(Lifecycle lifecycle, int subId) {
mSubId = subId;
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
@@ -115,6 +153,7 @@ public class EnabledNetworkModePreferenceController extends
? carrierConfig.getBoolean(
CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL)
: false;
lifecycle.addObserver(this);
}
private int getPreferredNetworkMode() {

View File

@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.view.Menu;
@@ -76,6 +77,13 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
}
};
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
updateSubscriptions(null);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -86,13 +94,18 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
setContentView(R.layout.mobile_network_settings_container);
}
setActionBar(findViewById(R.id.mobile_action_bar));
mPhoneChangeReceiver = new PhoneChangeReceiver(this, () -> {
if (mCurSubscriptionId != SUB_ID_NULL) {
// When the radio changes (ex: CDMA->GSM), refresh the fragment.
// This is very rare.
mPhoneChangeReceiver = new PhoneChangeReceiver(this, new PhoneChangeReceiver.Client() {
@Override
public void onPhoneChange() {
// When the radio or carrier config changes (ex: CDMA->GSM), refresh the fragment.
switchFragment(new MobileNetworkSettings(), mCurSubscriptionId,
true /* forceUpdate */);
}
@Override
public int getSubscriptionId() {
return mCurSubscriptionId;
}
});
mSubscriptionManager = getSystemService(SubscriptionManager.class);
mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList(true);
@@ -243,14 +256,12 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
@VisibleForTesting
static class PhoneChangeReceiver extends BroadcastReceiver {
private static final IntentFilter RADIO_TECHNOLOGY_CHANGED_FILTER = new IntentFilter(
TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
private Context mContext;
private Client mClient;
interface Client {
void onPhoneChange();
int getSubscriptionId();
}
public PhoneChangeReceiver(Context context, Client client) {
@@ -259,7 +270,10 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
}
public void register() {
mContext.registerReceiver(this, RADIO_TECHNOLOGY_CHANGED_FILTER);
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
mContext.registerReceiver(this, intentFilter);
}
public void unregister() {
@@ -268,9 +282,17 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
@Override
public void onReceive(Context context, Intent intent) {
if (!isInitialStickyBroadcast()) {
mClient.onPhoneChange();
if (isInitialStickyBroadcast()) {
return;
}
if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
if (!intent.hasExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX) ||
intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1)
!= mClient.getSubscriptionId()) {
return;
}
}
mClient.onPhoneChange();
}
}
}

View File

@@ -150,7 +150,7 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment {
use(CarrierPreferenceController.class).init(mSubId);
use(DataUsagePreferenceController.class).init(mSubId);
use(PreferredNetworkModePreferenceController.class).init(mSubId);
use(EnabledNetworkModePreferenceController.class).init(mSubId);
use(EnabledNetworkModePreferenceController.class).init(getLifecycle(), mSubId);
use(DataServiceSetupPreferenceController.class).init(mSubId);
if (!FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2)) {
use(EuiccPreferenceController.class).init(mSubId);

View File

@@ -61,16 +61,12 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
PhoneAccountHandle mSimCallManager;
private PhoneCallStateListener mPhoneStateListener;
private Preference mPreference;
private boolean mEditableWfcRoamingMode;
private boolean mUseWfcHomeModeForRoaming;
public WifiCallingPreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
mEditableWfcRoamingMode = true;
mUseWfcHomeModeForRoaming = false;
}
@Override
@@ -129,9 +125,18 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
preference.setTitle(title);
int resId = com.android.internal.R.string.wifi_calling_off_summary;
if (mImsManager.isWfcEnabledByUser()) {
boolean wfcRoamingEnabled = mEditableWfcRoamingMode && !mUseWfcHomeModeForRoaming;
boolean useWfcHomeModeForRoaming = false;
if (mCarrierConfigManager != null) {
final PersistableBundle carrierConfig =
mCarrierConfigManager.getConfigForSubId(mSubId);
if (carrierConfig != null) {
useWfcHomeModeForRoaming = carrierConfig.getBoolean(
CarrierConfigManager
.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL);
}
}
final boolean isRoaming = mTelephonyManager.isNetworkRoaming();
int wfcMode = mImsManager.getWfcMode(isRoaming && wfcRoamingEnabled);
int wfcMode = mImsManager.getWfcMode(isRoaming && !useWfcHomeModeForRoaming);
switch (wfcMode) {
case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
@@ -159,16 +164,6 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
mSimCallManager = mContext.getSystemService(TelecomManager.class)
.getSimCallManagerForSubscription(mSubId);
if (mCarrierConfigManager != null) {
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
if (carrierConfig != null) {
mEditableWfcRoamingMode = carrierConfig.getBoolean(
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
mUseWfcHomeModeForRoaming = carrierConfig.getBoolean(
CarrierConfigManager
.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL);
}
}
}
private class PhoneCallStateListener extends PhoneStateListener {

View File

@@ -55,7 +55,7 @@ public abstract class RingtonePreferenceControllerBase extends AbstractPreferenc
final CharSequence summary;
if (ringtoneUri == null) {
summary = null;
summary = mContext.getString(com.android.internal.R.string.ringtone_silent);
} else {
summary = Ringtone.getTitle(
mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);

View File

@@ -47,6 +47,7 @@ public final class ChooseLockSettingsHelper {
public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
public static final String EXTRA_KEY_FOR_FACE = "for_face";
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
/**
* Intent extra for passing the requested min password complexity to later steps in the set new
@@ -105,7 +106,8 @@ public final class ChooseLockSettingsHelper {
null /* header */,
null /* description */,
false /* returnCredentials */,
false /* external */);
false /* external */,
false /* foregroundOnly */);
}
/**
@@ -124,7 +126,8 @@ public final class ChooseLockSettingsHelper {
null /* header */,
null /* description */,
returnCredentials /* returnCredentials */,
false /* external */);
false /* external */,
false /* foregroundOnly */);
}
/**
@@ -148,7 +151,8 @@ public final class ChooseLockSettingsHelper {
false /* external */,
false /* hasChallenge */,
0 /* challenge */,
Utils.enforceSameOwner(mActivity, userId) /* userId */);
Utils.enforceSameOwner(mActivity, userId) /* userId */,
false /* foregroundOnly */);
}
/**
@@ -162,12 +166,13 @@ public final class ChooseLockSettingsHelper {
* @param external specifies whether this activity is launched externally, meaning that it will
* get a dark theme, allow fingerprint authentication and it will forward
* activity result.
* @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
* @return true if one exists and we launched an activity to confirm it
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external) {
boolean returnCredentials, boolean external, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -177,7 +182,8 @@ public final class ChooseLockSettingsHelper {
external /* external */,
false /* hasChallenge */,
0 /* challenge */,
Utils.getCredentialOwnerUserId(mActivity) /* userId */);
Utils.getCredentialOwnerUserId(mActivity) /* userId */,
foregroundOnly /* foregroundOnly */);
}
/**
@@ -207,7 +213,8 @@ public final class ChooseLockSettingsHelper {
external /* external */,
false /* hasChallenge */,
0 /* challenge */,
Utils.enforceSameOwner(mActivity, userId) /* userId */);
Utils.enforceSameOwner(mActivity, userId) /* userId */,
false /* foregroundOnly */);
}
/**
@@ -217,12 +224,13 @@ public final class ChooseLockSettingsHelper {
* @param header header of the confirmation screen; shown as large text
* @param description description of the confirmation screen
* @param challenge a challenge to be verified against the device credential.
* @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
* @return true if one exists and we launched an activity to confirm it
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
long challenge) {
long challenge, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -232,7 +240,8 @@ public final class ChooseLockSettingsHelper {
false /* external */,
true /* hasChallenge */,
challenge /* challenge */,
Utils.getCredentialOwnerUserId(mActivity) /* userId */);
Utils.getCredentialOwnerUserId(mActivity) /* userId */,
foregroundOnly /* foregroundOnly */);
}
/**
@@ -243,12 +252,13 @@ public final class ChooseLockSettingsHelper {
* @param description description of the confirmation screen
* @param challenge a challenge to be verified against the device credential.
* @param userId The userId for whom the lock should be confirmed.
* @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
* @return true if one exists and we launched an activity to confirm it
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
long challenge, int userId) {
long challenge, int userId, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -258,7 +268,8 @@ public final class ChooseLockSettingsHelper {
false /* external */,
true /* hasChallenge */,
challenge /* challenge */,
Utils.enforceSameOwner(mActivity, userId) /* userId */);
Utils.enforceSameOwner(mActivity, userId) /* userId */,
foregroundOnly);
}
/**
@@ -287,7 +298,8 @@ public final class ChooseLockSettingsHelper {
external /* external */,
true /* hasChallenge */,
challenge /* challenge */,
Utils.enforceSameOwner(mActivity, userId) /* userId */);
Utils.enforceSameOwner(mActivity, userId) /* userId */,
false /* foregroundOnly */);
}
/**
@@ -316,7 +328,7 @@ public final class ChooseLockSettingsHelper {
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean hasChallenge,
long challenge, int userId) {
long challenge, int userId, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -328,7 +340,8 @@ public final class ChooseLockSettingsHelper {
challenge /* challenge */,
userId /* userId */,
null /* alternateButton */,
null /* extras */);
null /* extras */,
foregroundOnly /* foregroundOnly */);
}
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@@ -346,7 +359,8 @@ public final class ChooseLockSettingsHelper {
challenge /* challenge */,
userId /* userId */,
null /* alternateButton */,
extras /* extras */);
extras /* extras */,
false /* foregroundOnly */);
}
public boolean launchFrpConfirmationActivity(int request, @Nullable CharSequence header,
@@ -362,13 +376,15 @@ public final class ChooseLockSettingsHelper {
0 /* challenge */,
LockPatternUtils.USER_FRP /* userId */,
alternateButton /* alternateButton */,
null /* extras */);
null /* extras */,
false /* foregroundOnly */);
}
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean hasChallenge,
long challenge, int userId, @Nullable CharSequence alternateButton, Bundle extras) {
long challenge, int userId, @Nullable CharSequence alternateButton, Bundle extras,
boolean foregroundOnly) {
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
boolean launched = false;
@@ -378,7 +394,8 @@ public final class ChooseLockSettingsHelper {
returnCredentials || hasChallenge
? ConfirmLockPattern.InternalActivity.class
: ConfirmLockPattern.class, returnCredentials, external,
hasChallenge, challenge, userId, alternateButton, extras);
hasChallenge, challenge, userId, alternateButton, extras,
foregroundOnly);
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
@@ -390,7 +407,8 @@ public final class ChooseLockSettingsHelper {
returnCredentials || hasChallenge
? ConfirmLockPassword.InternalActivity.class
: ConfirmLockPassword.class, returnCredentials, external,
hasChallenge, challenge, userId, alternateButton, extras);
hasChallenge, challenge, userId, alternateButton, extras,
foregroundOnly);
break;
}
return launched;
@@ -399,7 +417,8 @@ public final class ChooseLockSettingsHelper {
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
CharSequence message, Class<?> activityClass, boolean returnCredentials,
boolean external, boolean hasChallenge, long challenge,
int userId, @Nullable CharSequence alternateButton, Bundle extras) {
int userId, @Nullable CharSequence alternateButton, Bundle extras,
boolean foregroundOnly) {
final Intent intent = new Intent();
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
@@ -414,6 +433,7 @@ public final class ChooseLockSettingsHelper {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
intent.putExtra(Intent.EXTRA_USER_ID, userId);
intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly);
if (extras != null) {
intent.putExtras(extras);
}

View File

@@ -172,6 +172,10 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
mBiometricManager.onConfirmDeviceCredentialError(
BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
getString(com.android.internal.R.string.biometric_error_user_canceled));
if (getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, false)) {
finish();
}
}
}

View File

@@ -111,7 +111,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
int titleResource = mForFingerprint ?
int titleResource = isForBiometric() ?
R.string.lock_settings_picker_title : R.string.setup_lock_settings_picker_title;
if (getActivity() != null) {
getActivity().setTitle(titleResource);
@@ -125,7 +125,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
@Override
protected void addHeaderView() {
if (mForFingerprint || mForFace) {
if (isForBiometric()) {
setHeaderView(R.layout.setup_choose_lock_generic_biometrics_header);
} else {
setHeaderView(R.layout.setup_choose_lock_generic_header);
@@ -183,7 +183,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
@Override
protected void addPreferences() {
if (mForFingerprint) {
if (isForBiometric()) {
super.addPreferences();
} else {
addPreferencesFromResource(R.xml.setup_security_settings_picker);
@@ -240,6 +240,10 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
return intent;
}
private boolean isForBiometric() {
return mForFingerprint || mForFace;
}
}
public static class InternalActivity extends ChooseLockGeneric.InternalActivity {
@@ -261,5 +265,4 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
}
}
}
}

View File

@@ -96,18 +96,23 @@ public final class EnableContentCaptureWithServiceSettingsPreferenceController
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();
if (userHandles.size() == 1) {
final Intent intent = pref.getIntent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivityAsUser(intent, userHandles.get(0));
} else {
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()
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivityAsUser(intent, user);
})
.show();
}
}
}

View File

@@ -26,6 +26,7 @@ import android.util.ArrayMap;
import androidx.annotation.VisibleForTesting;
import com.android.settings.display.AdaptiveSleepPreferenceController;
import com.android.settings.flashlight.FlashlightSlice;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
@@ -34,7 +35,9 @@ import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSli
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
import com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice;
import com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice;
import com.android.settings.homepage.contextualcards.slices.FaceSetupSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
import com.android.settings.location.LocationSlice;
@@ -64,6 +67,16 @@ public class CustomSliceRegistry {
.appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
.build();
/**
* Uri for Contextual Adaptive Sleep Slice
*/
public static final Uri CONTEXTUAL_ADAPTIVE_SLEEP_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
.appendPath(AdaptiveSleepPreferenceController.PREF_NAME)
.build();
/**
* Uri for Battery Fix Slice.
*/
@@ -150,6 +163,15 @@ public class CustomSliceRegistry {
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath("enhanced_4g_lte")
.build();
/**
* Slice Uri for Face Enrollment
*/
public static final Uri FACE_ENROLL_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath("face_unlock_greeting_card")
.build();
/**
* Backing Uri for the Flashlight Slice.
*/
@@ -328,21 +350,23 @@ public class CustomSliceRegistry {
sUriToSlice.put(BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
sUriToSlice.put(BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
sUriToSlice.put(CONTEXTUAL_ADAPTIVE_SLEEP_URI, ContextualAdaptiveSleepSlice.class);
sUriToSlice.put(CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI,
ContextualNotificationChannelSlice.class);
sUriToSlice.put(CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
sUriToSlice.put(DATA_USAGE_SLICE_URI, DataUsageSlice.class);
sUriToSlice.put(DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
sUriToSlice.put(EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
sUriToSlice.put(FACE_ENROLL_SLICE_URI, FaceSetupSlice.class);
sUriToSlice.put(FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
sUriToSlice.put(LOCATION_SLICE_URI, LocationSlice.class);
sUriToSlice.put(LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
sUriToSlice.put(MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
sUriToSlice.put(NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class);
sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
}
public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {

View File

@@ -17,8 +17,11 @@
package com.android.settings.wifi;
import android.content.Context;
import android.content.res.Resources;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.TogglePreferenceController;
/**
@@ -33,7 +36,7 @@ public class CellularFallbackPreferenceController extends TogglePreferenceContro
@Override
public int getAvailabilityStatus() {
return !avoidBadWifiConfig() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
return avoidBadWifiConfig() ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
}
@Override
@@ -49,12 +52,28 @@ public class CellularFallbackPreferenceController extends TogglePreferenceContro
}
private boolean avoidBadWifiConfig() {
return mContext.getResources().getInteger(
com.android.internal.R.integer.config_networkAvoidBadWifi) == 1;
final int activeDataSubscriptionId = getActiveDataSubscriptionId();
if (activeDataSubscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return true;
}
final Resources resources = getResourcesForSubId(activeDataSubscriptionId);
return resources.getInteger(com.android.internal.R.integer.config_networkAvoidBadWifi) == 1;
}
@VisibleForTesting
int getActiveDataSubscriptionId() {
return SubscriptionManager.getActiveDataSubscriptionId();
}
@VisibleForTesting
Resources getResourcesForSubId(int subscriptionId) {
return SubscriptionManager.getResourcesForSubId(mContext, subscriptionId,
false /* useRootLocale */);
}
private boolean avoidBadWifiCurrentSettings() {
return "1".equals(Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.NETWORK_AVOID_BAD_WIFI));
}
}
}

View File

@@ -682,7 +682,11 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
}
mMacAddressPref.setVisible(true);
mMacAddressPref.setSummary(macAddress);
if (macAddress.equals(WifiInfo.DEFAULT_MAC_ADDRESS)) {
mMacAddressPref.setSummary(R.string.device_info_not_available);
} else {
mMacAddressPref.setSummary(macAddress);
}
}
private String getMacAddress() {

View File

@@ -85,7 +85,7 @@ public class TetherService extends Service {
public void onCreate() {
super.onCreate();
if (DEBUG) Log.d(TAG, "Creating TetherService");
String provisionResponse = getResourceForDefaultDataSubId().getString(
String provisionResponse = getResourceForActiveDataSubId().getString(
com.android.internal.R.string.config_mobile_hotspot_provision_response);
registerReceiver(mReceiver, new IntentFilter(provisionResponse),
android.Manifest.permission.CONNECTIVITY_INTERNAL, null);
@@ -105,7 +105,7 @@ public class TetherService extends Service {
if (intent.hasExtra(EXTRA_SUBID)) {
final int tetherSubId = intent.getIntExtra(EXTRA_SUBID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
if (tetherSubId != subId) {
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
if (!mInProvisionCheck) {
@@ -273,11 +273,13 @@ public class TetherService extends Service {
}
private Intent getProvisionBroadcastIntent(int index) {
String provisionAction = getResourceForDefaultDataSubId().getString(
String provisionAction = getResourceForActiveDataSubId().getString(
com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
Intent intent = new Intent(provisionAction);
int type = mCurrentTethers.get(index);
intent.putExtra(TETHER_CHOICE, type);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
@@ -309,7 +311,7 @@ public class TetherService extends Service {
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
int period = getResourceForDefaultDataSubId().getInteger(
int period = getResourceForActiveDataSubId().getInteger(
com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
long periodMs = period * MS_PER_HOUR;
long firstTime = SystemClock.elapsedRealtime() + periodMs;
@@ -362,7 +364,7 @@ public class TetherService extends Service {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Got provision result " + intent);
String provisionResponse = getResourceForDefaultDataSubId().getString(
String provisionResponse = getResourceForActiveDataSubId().getString(
com.android.internal.R.string.config_mobile_hotspot_provision_response);
if (provisionResponse.equals(intent.getAction())) {
@@ -429,14 +431,14 @@ public class TetherService extends Service {
mUsageStatsManager.setAppInactive(packageName, isInactive);
}
int getDefaultDataSubscriptionId() {
return SubscriptionManager.getDefaultDataSubscriptionId();
int getActiveDataSubscriptionId() {
return SubscriptionManager.getActiveDataSubscriptionId();
}
}
@VisibleForTesting
Resources getResourceForDefaultDataSubId() {
final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
Resources getResourceForActiveDataSubId() {
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
return Utils.getResourcesForSubId(this, subId);
}
}

View File

@@ -26,8 +26,6 @@
<item>@drawable/ic_arrow_back</item>
<item>@drawable/ic_arrow_down_24dp</item>
<item>@drawable/ic_battery_charging_full</item>
<item>@drawable/ic_battery_saver_accent_24dp</item>
<item>@drawable/ic_battery_status_bad_24dp</item>
<item>@drawable/ic_battery_status_good_24dp</item>
<item>@drawable/ic_battery_status_maybe_24dp</item>
<item>@drawable/ic_call_24dp</item>
@@ -38,13 +36,13 @@
<item>@drawable/ic_content_copy_grey600_24dp</item>
<item>@drawable/ic_data_saver</item>
<item>@drawable/ic_delete</item>
<item>@drawable/ic_delete_accent</item>
<item>@drawable/ic_devices_other</item>
<item>@drawable/ic_devices_other_opaque_black</item>
<item>@drawable/ic_do_not_disturb_on_24dp</item>
<item>@drawable/ic_eject_24dp</item>
<item>@drawable/ic_expand_less</item>
<item>@drawable/ic_expand_more_inverse</item>
<item>@drawable/ic_find_in_page_24px</item>
<item>@drawable/ic_folder_vd_theme_24</item>
<item>@drawable/ic_friction_lock_closed</item>
<item>@drawable/ic_gray_scale_24dp</item>
@@ -71,9 +69,13 @@
<item>@drawable/ic_settings_data_usage</item>
<item>@drawable/ic_settings_date_time</item>
<item>@drawable/ic_settings_delete</item>
<item>@drawable/ic_settings_disable</item>
<item>@drawable/ic_settings_display_white</item>
<item>@drawable/ic_settings_enable</item>
<item>@drawable/ic_settings_home</item>
<item>@drawable/ic_settings_language</item>
<item>@drawable/ic_settings_location</item>
<item>@drawable/ic_settings_multiuser</item>
<item>@drawable/ic_settings_night_display</item>
<item>@drawable/ic_settings_open</item>
<item>@drawable/ic_settings_print</item>
@@ -82,15 +84,16 @@
<item>@drawable/ic_settings_sim</item>
<item>@drawable/ic_settings_system_dashboard_white</item>
<item>@drawable/ic_settings_wireless</item>
<item>@drawable/ic_settings_wireless_white</item>
<item>@drawable/ic_storage</item>
<item>@drawable/ic_storage_white</item>
<item>@drawable/ic_suggestion_night_display</item>
<item>@drawable/ic_sync</item>
<item>@drawable/ic_sync_problem_24dp</item>
<item>@drawable/ic_system_update</item>
<item>@drawable/ic_videogame_vd_theme_24</item>
<item>@drawable/ic_volume_ringer_vibrate</item>
<item>@drawable/ic_volume_up_24dp</item>
<item>@drawable/ic_vpn_key</item>
<item>@drawable/ic_wifi_tethering</item>
</array>
</resources>

View File

@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -99,6 +100,16 @@ public class AppStoragePreferenceControllerTest {
verify(preference).setSummary(any());
}
@Test
public void updateState_entryIsNull_shouldNotUpdatePreferenceSummary() {
when(mFragment.getAppEntry()).thenReturn(null);
Preference preference = mock(Preference.class);
mController.updateState(preference);
verify(preference, never()).setSummary(any());
}
@Test
public void getStorageSummary_shouldWorkForExternal() {
final StorageStatsSource.AppStorageStats stats =

View File

@@ -0,0 +1,89 @@
/*
* 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
*/
package com.android.settings.biometrics.face;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.face.FaceManager;
import android.os.UserManager;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
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;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class FaceSettingsLockscreenBypassPreferenceControllerTest {
@Mock
private FaceManager mFaceManager;
private SwitchPreference mPreference;
@Mock
private UserManager mUserManager;
private Context mContext;
private FaceSettingsLockscreenBypassPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPreference = new SwitchPreference(mContext);
mController = new FaceSettingsLockscreenBypassPreferenceController(mContext, "test_key");
ReflectionHelpers.setField(mController, "mFaceManager", mFaceManager);
ReflectionHelpers.setField(mController, "mUserManager", mUserManager);
}
@Test
public void isAvailable_whenHardwareDetected() {
assertThat(mController.isAvailable()).isFalse();
when(mFaceManager.isHardwareDetected()).thenReturn(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_isManagedProfile_shouldReturnUnsupported() {
when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void onPreferenceChange_settingIsUpdated() {
boolean defaultValue = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_faceAuthDismissesKeyguard);
boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, defaultValue ? 1 : 0) != 0;
assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
boolean newState = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 0) != 0;
assertThat(newState).isEqualTo(!state);
}
}

View File

@@ -31,12 +31,9 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.FeatureFlagUtils;
import androidx.preference.Preference;
import com.android.settings.core.FeatureFlags;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -91,7 +88,7 @@ public class MainlineModuleVersionPreferenceControllerTest {
@Test
public void getAvailabilityStatus_hasMainlineModulePackageInfo_available() throws Exception {
setupModulePackage();
setupModulePackage("test version 123");
final MainlineModuleVersionPreferenceController controller =
new MainlineModuleVersionPreferenceController(mContext, "key");
@@ -101,7 +98,7 @@ public class MainlineModuleVersionPreferenceControllerTest {
@Test
public void updateStates_canHandleIntent_setIntentToPreference() throws Exception {
setupModulePackage();
setupModulePackage("test version 123");
when(mPackageManager.resolveActivity(MODULE_UPDATE_INTENT, 0))
.thenReturn(new ResolveInfo());
@@ -115,7 +112,7 @@ public class MainlineModuleVersionPreferenceControllerTest {
@Test
public void updateStates_cannotHandleIntent_setNullToPreference() throws Exception {
setupModulePackage();
setupModulePackage("test version 123");
when(mPackageManager.resolveActivity(MODULE_UPDATE_INTENT, 0))
.thenReturn(null);
@@ -127,9 +124,38 @@ public class MainlineModuleVersionPreferenceControllerTest {
assertThat(mPreference.getIntent()).isNull();
}
private void setupModulePackage() throws Exception {
@Test
public void getSummary_versionIsNull_returnNull() throws Exception {
setupModulePackage(null);
final MainlineModuleVersionPreferenceController controller =
new MainlineModuleVersionPreferenceController(mContext, "key");
assertThat(controller.getSummary()).isNull();
}
@Test
public void getSummary_versionIsMonth_returnMonth() throws Exception {
setupModulePackage("2019-05");
final MainlineModuleVersionPreferenceController controller =
new MainlineModuleVersionPreferenceController(mContext, "key");
assertThat(controller.getSummary()).isEqualTo("May 01, 2019");
}
@Test
public void getSummary_versionIsDate_returnDate() throws Exception {
setupModulePackage("2019-05-13");
final MainlineModuleVersionPreferenceController controller =
new MainlineModuleVersionPreferenceController(mContext, "key");
assertThat(controller.getSummary()).isEqualTo("May 13, 2019");
}
private void setupModulePackage(String version) throws Exception {
final String provider = "test.provider";
final String version = "test version 123";
final PackageInfo info = new PackageInfo();
info.versionName = version;
when(mContext.getString(

View File

@@ -0,0 +1,83 @@
/*
* 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
*/
package com.android.settings.display;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import androidx.preference.Preference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class AdaptiveSleepPermissionPreferenceControllerTest {
private final static String PACKAGE_NAME = "package_name";
private AdaptiveSleepPermissionPreferenceController mController;
@Mock
private PackageManager mPackageManager;
@Mock
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Context context = Mockito.spy(RuntimeEnvironment.application);
doReturn(mPackageManager).when(context).getPackageManager();
doReturn(PACKAGE_NAME).when(mPackageManager).getAttentionServicePackageName();
doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
Manifest.permission.CAMERA, PACKAGE_NAME);
mController = new AdaptiveSleepPermissionPreferenceController(context, "test_key");
doReturn(mController.getPreferenceKey()).when(mPreference).getKey();
}
@Test
public void getAvailabilityStatus_returnAvailableUnsearchable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
public void updateStates_permissionGranted_preferenceInvisible() {
mController.updateState(mPreference);
verify(mPreference).setVisible(false);
}
@Test
public void updateStates_permissionRevoked_preferenceVisible() {
doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
Manifest.permission.CAMERA, PACKAGE_NAME);
mController.updateState(mPreference);
verify(mPreference).setVisible(true);
}
}

View File

@@ -24,7 +24,6 @@ import static com.android.settings.gestures.SystemNavigationPreferenceController
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
@@ -181,46 +180,4 @@ public class SystemNavigationPreferenceControllerTest {
assertThat(TextUtils.equals(mController.getSummary(), mContext.getText(
com.android.settings.R.string.swipe_up_to_switch_apps_title))).isTrue();
}
@Test
public void testIsGestureNavSupportedByDefaultLauncher_noDefaultLauncher() {
when(mMockPackageManager.getHomeActivities(any())).thenReturn(null);
assertThat(SystemNavigationPreferenceController
.isGestureNavSupportedByDefaultLauncher(mMockContext)).isTrue();
}
@Test
public void testIsGestureNavSupportedByDefaultLauncher_supported() {
when(mMockPackageManager.getHomeActivities(any())).thenReturn(
ComponentName.unflattenFromString(TEST_RECENTS_COMPONENT_NAME));
assertThat(SystemNavigationPreferenceController
.isGestureNavSupportedByDefaultLauncher(mMockContext)).isTrue();
}
@Test
public void testIsGestureNavSupportedByDefaultLauncher_notSupported() {
when(mMockPackageManager.getHomeActivities(any())).thenReturn(
new ComponentName("unsupported", "launcher"));
assertThat(SystemNavigationPreferenceController
.isGestureNavSupportedByDefaultLauncher(mMockContext)).isFalse();
}
@Test
public void testGetDefaultHomeAppName_noDefaultLauncher() {
when(mMockPackageManager.getHomeActivities(any())).thenReturn(null);
assertThat(SystemNavigationPreferenceController
.getDefaultHomeAppName(mMockContext)).isEqualTo("");
}
@Test
public void testGetDefaultHomeAppName_defaultLauncherExists() throws Exception {
when(mMockPackageManager.getHomeActivities(any())).thenReturn(
new ComponentName("supported", "launcher"));
ApplicationInfo info = new ApplicationInfo();
when(mMockPackageManager.getApplicationInfo("supported", 0)).thenReturn(info);
when(mMockPackageManager.getApplicationLabel(info)).thenReturn("Test Home App");
assertThat(SystemNavigationPreferenceController
.getDefaultHomeAppName(mMockContext)).isEqualTo("Test Home App");
}
}

View File

@@ -0,0 +1,115 @@
/*
* 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
*/
package com.android.settings.homepage.contextualcards.slices;
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.DEFERRED_TIME_DAYS;
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF;
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_SETUP_TIME;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
import androidx.slice.widget.SliceLiveData;
import com.android.settings.slices.CustomSliceRegistry;
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;
@RunWith(RobolectricTestRunner.class)
public class ContextualAdaptiveSleepSliceTest {
private static final String pkgName = "adaptive_sleep";
private Context mContext;
private ContextualAdaptiveSleepSlice mContextualAdaptiveSleepSlice;
@Mock
private PackageManager mPackageManager;
@Mock
private SharedPreferences mSharedPreferences;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
mContext = spy(RuntimeEnvironment.application);
mContextualAdaptiveSleepSlice = spy(new ContextualAdaptiveSleepSlice(mContext));
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mSharedPreferences).when(mContext).getSharedPreferences(eq(PREF), anyInt());
doReturn(true).when(mContextualAdaptiveSleepSlice).isSettingsAvailable();
doReturn(pkgName).when(mPackageManager).getAttentionServicePackageName();
doReturn(-DEFERRED_TIME_DAYS).when(mSharedPreferences).getLong(eq(PREF_KEY_SETUP_TIME),
anyLong());
}
@Test
public void getUri_shouldReturnContextualAdaptiveSleepSliceUri() {
final Uri uri = mContextualAdaptiveSleepSlice.getUri();
assertThat(uri).isEqualTo(CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI);
}
@Test
public void getSlice_ShowIfFeatureIsAvailable() {
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
assertThat(slice).isNotNull();
}
@Test
public void getSlice_DoNotShowIfFeatureIsUnavailable() {
doReturn(false).when(mContextualAdaptiveSleepSlice).isSettingsAvailable();
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
assertThat(slice).isNull();
}
@Test
public void getSlice_ShowIfNotRecentlySetup() {
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
assertThat(slice).isNotNull();
}
@Test
public void getSlice_DoNotShowIfRecentlySetup() {
doReturn(System.currentTimeMillis()).when(mSharedPreferences).getLong(
eq(PREF_KEY_SETUP_TIME), anyLong());
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
assertThat(slice).isNull();
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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
*/
package com.android.settings.homepage.contextualcards.slices;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
import android.os.UserHandle;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
import androidx.slice.widget.SliceLiveData;
import com.android.settings.R;
import com.android.settings.Utils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class FaceSetupSliceTest {
private Context mContext;
private PackageManager mPackageManager;
@Before
public void setUp() {
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
mContext = spy(RuntimeEnvironment.application);
mPackageManager = mock(PackageManager.class);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
}
@Test
public void getSlice_noFaceManager_shouldReturnNull() {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(false);
final FaceSetupSlice setupSlice = new FaceSetupSlice(mContext);
assertThat(setupSlice.getSlice()).isNull();
}
@Test
public void getSlice_faceEnrolled_shouldReturnNull() {
final FaceManager faceManager = mock(FaceManager.class);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
when(faceManager.hasEnrolledTemplates(UserHandle.myUserId())).thenReturn(true);
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(faceManager);
final FaceSetupSlice setupSlice = new FaceSetupSlice(mContext);
assertThat(setupSlice.getSlice()).isNull();
}
@Test
public void getSlice_faceNotEnrolled_shouldReturnNonNull() {
final FaceManager faceManager = mock(FaceManager.class);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
when(faceManager.hasEnrolledTemplates(UserHandle.myUserId())).thenReturn(false);
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(faceManager);
final FaceSetupSlice setupSlice = new FaceSetupSlice(mContext);
assertThat(setupSlice.getSlice()).isNotNull();
}
}

View File

@@ -42,6 +42,7 @@ import android.text.TextUtils;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.widget.AddPreference;
import com.android.settingslib.RestrictedLockUtils;
import org.junit.After;
import org.junit.Before;
@@ -373,4 +374,12 @@ public class MobileNetworkSummaryControllerTest {
verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
assertThat(captor.getValue()).isTrue();
}
@Test
public void onResume_disabledByAdmin_prefStaysDisabled() {
mPreference.setDisabledByAdmin(new RestrictedLockUtils.EnforcedAdmin());
mController.displayPreference(mPreferenceScreen);
mController.onResume();
verify(mPreference, never()).setEnabled(eq(true));
}
}

View File

@@ -16,6 +16,8 @@
package com.android.settings.network.telephony;
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
@@ -23,19 +25,25 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.net.Uri;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +56,7 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class EnabledNetworkModePreferenceControllerTest {
private static final int SUB_ID = 2;
public static final String KEY = "enabled_network";
@Mock
private TelephonyManager mTelephonyManager;
@@ -60,11 +69,14 @@ public class EnabledNetworkModePreferenceControllerTest {
private EnabledNetworkModePreferenceController mController;
private ListPreference mPreference;
private Context mContext;
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
mContext = spy(RuntimeEnvironment.application);
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class);
@@ -79,8 +91,8 @@ public class EnabledNetworkModePreferenceControllerTest {
mPreference = new ListPreference(mContext);
mPreference.setEntries(R.array.enabled_networks_choices);
mPreference.setEntryValues(R.array.enabled_networks_values);
mController = new EnabledNetworkModePreferenceController(mContext, "enabled_network");
mController.init(SUB_ID);
mController = new EnabledNetworkModePreferenceController(mContext, KEY);
mController.init(mLifecycle, SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
}
@@ -106,7 +118,7 @@ public class EnabledNetworkModePreferenceControllerTest {
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL,
true);
mController.init(SUB_ID);
mController.init(mLifecycle, SUB_ID);
assertThat(mController.mShow4GForLTE).isTrue();
}
@@ -161,4 +173,31 @@ public class EnabledNetworkModePreferenceControllerTest {
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, 0)).isNotEqualTo(
TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA);
}
@Test
public void preferredNetworkModeNotification_preferenceUpdates() {
PreferenceScreen screen = mock(PreferenceScreen.class);
doReturn(mPreference).when(screen).findPreference(KEY);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA);
mController.displayPreference(screen);
mController.updateState(mPreference);
mLifecycle.handleLifecycleEvent(ON_START);
assertThat(Integer.parseInt(mPreference.getValue())).isEqualTo(
TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA);
assertThat(mPreference.getSummary()).isEqualTo("3G");
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
TelephonyManager.NETWORK_MODE_GSM_ONLY);
final Uri uri = Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID);
mContext.getContentResolver().notifyChange(uri, null);
assertThat(Integer.parseInt(mPreference.getValue())).isEqualTo(
TelephonyManager.NETWORK_MODE_GSM_ONLY);
assertThat(mPreference.getSummary()).isEqualTo("2G");
}
}

View File

@@ -22,7 +22,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,6 +34,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -40,6 +44,8 @@ import android.view.View;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.view.menu.ContextMenuBuilder;
import com.android.settings.R;
import com.android.settings.core.FeatureFlags;
import com.android.settings.development.featureflags.FeatureFlagPersistent;
import com.android.settings.network.SubscriptionUtil;
import com.google.android.material.bottomnavigation.BottomNavigationView;
@@ -159,19 +165,56 @@ public class MobileNetworkActivityTest {
@Test
public void phoneChangeReceiver_ignoresStickyBroadcastFromBeforeRegistering() {
Activity activity = Robolectric.setupActivity(Activity.class);
final int[] onChangeCallbackCount = {0};
MobileNetworkActivity.PhoneChangeReceiver.Client client = mock(
MobileNetworkActivity.PhoneChangeReceiver.Client.class);
MobileNetworkActivity.PhoneChangeReceiver receiver =
new MobileNetworkActivity.PhoneChangeReceiver(activity, () -> {
onChangeCallbackCount[0]++;
});
new MobileNetworkActivity.PhoneChangeReceiver(activity, client);
Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
activity.sendStickyBroadcast(intent);
receiver.register();
assertThat(onChangeCallbackCount[0]).isEqualTo(0);
verify(client, never()).onPhoneChange();
activity.sendStickyBroadcast(intent);
assertThat(onChangeCallbackCount[0]).isEqualTo(1);
verify(client, times(1)).onPhoneChange();
}
@Test
public void phoneChangeReceiver_ignoresCarrierConfigChangeForWrongSubscriptionId() {
Activity activity = Robolectric.setupActivity(Activity.class);
MobileNetworkActivity.PhoneChangeReceiver.Client client = mock(
MobileNetworkActivity.PhoneChangeReceiver.Client.class);
doReturn(2).when(client).getSubscriptionId();
MobileNetworkActivity.PhoneChangeReceiver receiver =
new MobileNetworkActivity.PhoneChangeReceiver(activity, client);
receiver.register();
Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, 3);
activity.sendBroadcast(intent);
verify(client, never()).onPhoneChange();
}
@Test
public void phoneChangeReceiver_dispatchesCarrierConfigChangeForCorrectSubscriptionId() {
Activity activity = Robolectric.setupActivity(Activity.class);
MobileNetworkActivity.PhoneChangeReceiver.Client client = mock(
MobileNetworkActivity.PhoneChangeReceiver.Client.class);
doReturn(2).when(client).getSubscriptionId();
MobileNetworkActivity.PhoneChangeReceiver receiver =
new MobileNetworkActivity.PhoneChangeReceiver(activity, client);
receiver.register();
Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, 2);
activity.sendBroadcast(intent);
verify(client).onPhoneChange();
}
@@ -207,4 +250,19 @@ public class MobileNetworkActivityTest {
assertThat(bundle.getInt(Settings.EXTRA_SUB_ID)).isEqualTo(PREV_SUB_ID);
}
@Test
public void onNewIntent_newSubscriptionId_fragmentReplaced() {
FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
mSubscriptionInfos.add(mSubscriptionInfo);
mSubscriptionInfos.add(mSubscriptionInfo2);
SubscriptionUtil.setAvailableSubscriptionsForTesting(mSubscriptionInfos);
mMobileNetworkActivity.mCurSubscriptionId = PREV_SUB_ID;
final Intent newIntent = new Intent();
newIntent.putExtra(Settings.EXTRA_SUB_ID, CURRENT_SUB_ID);
mMobileNetworkActivity.onNewIntent(newIntent);
assertThat(mMobileNetworkActivity.mCurSubscriptionId).isEqualTo(CURRENT_SUB_ID);
}
}

View File

@@ -127,10 +127,10 @@ public class WifiCallingPreferenceControllerTest {
}
@Test
public void updateState_wfcNonRoaming() {
public void updateState_nonRoaming_wfcCellularPreferred() {
assertNull(mController.mSimCallManager);
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
// update the config value by calling init again.
mCarrierConfig.putBoolean(
CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, true);
mController.init(SUB_ID);
mController.mImsManager = mImsManager;
@@ -147,9 +147,10 @@ public class WifiCallingPreferenceControllerTest {
}
@Test
public void updateState_wfcRoaming() {
public void updateState_roaming_wfcWifiPreferred() {
assertNull(mController.mSimCallManager);
// useWfcHomeModeForRoaming is false by default. In order to check wfc in roaming mode. We
// need the device roaming, and not using home mode in roaming network.
when(mImsManager.getWfcMode(true)).thenReturn(
ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED);
when(mImsManager.getWfcMode(false)).thenReturn(

View File

@@ -18,36 +18,54 @@ package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.telephony.SubscriptionManager;
import org.junit.Before;
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;
@RunWith(RobolectricTestRunner.class)
public class CellularFallbackPreferenceControllerTest {
private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
private CellularFallbackPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new CellularFallbackPreferenceController(mContext, KEY_CELLULAR_FALLBACK);
mController = spy(new CellularFallbackPreferenceController(RuntimeEnvironment.application,
KEY_CELLULAR_FALLBACK));
}
@Test
public void isAvailable_invalidActiveSubscriptionId_shouldReturnFalse() {
doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.when(mController).getActiveDataSubscriptionId();
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_avoidBadWifiConfigIsFalse_shouldReturnTrue() {
when(mContext.getResources().getInteger(
final Resources resources = mock(Resources.class);
doReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
.when(mController).getActiveDataSubscriptionId();
doReturn(resources).when(mController).getResourcesForSubId(anyInt());
when(resources.getInteger(
com.android.internal.R.integer.config_networkAvoidBadWifi))
.thenReturn(0);
@@ -56,10 +74,15 @@ public class CellularFallbackPreferenceControllerTest {
@Test
public void isAvailable_avoidBadWifiConfigIsTrue_shouldReturnFalse() {
when(mContext.getResources().getInteger(
final Resources resources = mock(Resources.class);
doReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
.when(mController).getActiveDataSubscriptionId();
doReturn(resources).when(mController).getResourcesForSubId(anyInt());
when(resources.getInteger(
com.android.internal.R.integer.config_networkAvoidBadWifi))
.thenReturn(1);
assertThat(mController.isAvailable()).isFalse();
}
}
}

View File

@@ -114,7 +114,7 @@ public class WifiDetailPreferenceControllerTest {
private static final int TX_LINK_SPEED = 123;
private static final int RX_LINK_SPEED = 54;
private static final String SSID = "ssid";
private static final String MAC_ADDRESS = WifiInfo.DEFAULT_MAC_ADDRESS;
private static final String MAC_ADDRESS = "01:23:45:67:89:ab";
private static final String RANDOMIZED_MAC_ADDRESS = "RANDOMIZED_MAC_ADDRESS";
private static final String FACTORY_MAC_ADDRESS = "FACTORY_MAC_ADDRESS";
private static final String SECURITY = "None";

View File

@@ -458,7 +458,7 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
}
@Override
int getDefaultDataSubscriptionId() {
int getActiveDataSubscriptionId() {
return INVALID_SUBSCRIPTION_ID;
}
}