Snap for 9485425 from 6c703e12ae to tm-qpr3-release

Change-Id: Ifd7bb36c6cf4b5260be6df92aaa11704bf5e8fbf
This commit is contained in:
Android Build Coastguard Worker
2023-01-13 00:26:10 +00:00
83 changed files with 1963 additions and 228 deletions

View File

@@ -525,6 +525,86 @@
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;sfps_enrollment_fp_captured_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="54"
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;sfps_enrollment_fp_error_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="55"
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;sfps_enrollment_progress_bar_bg_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="56"
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;sfps_enrollment_progress_bar_fill_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="57"
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;sfps_enrollment_progress_bar_error_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="58"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -589,6 +669,86 @@
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;sfps_enrollment_fp_captured_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="205"
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;sfps_enrollment_fp_error_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="206"
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;sfps_enrollment_progress_bar_bg_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="207"
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;sfps_enrollment_progress_bar_fill_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="208"
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;sfps_enrollment_progress_bar_error_color&quot;>#ffffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="209"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -4829,6 +4989,38 @@
column="45"/>
</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;item name=&quot;android:colorPrimary&quot;>@color/material_grey_100&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
line="233"
column="45"/>
</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;item name=&quot;android:titleTextColor&quot;>@color/material_blue_700&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
line="235"
column="45"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -4845,4 +5037,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=" android:progressBackgroundTint=&quot;@color/sfps_enrollment_progress_bar_bg_color&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/sfps_enroll_enrolling.xml"
line="71"
column="20"/>
</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:progressBackgroundTint=&quot;@color/sfps_enrollment_progress_bar_bg_color&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/sfps_enroll_enrolling.xml"
line="71"
column="20"/>
</issue>
</issues>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2022 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.
-->
<!-- Used in phone portrait and tablet, as referenced in alias.xml. -->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_lock">
<!-- takes up all space above button bar at bottom -->
<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
android:id="@+id/topLayout"
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<TextView
android:id="@+id/headerText"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minLines="2"
android:gravity="center"
android:paddingStart="?attr/sudMarginStart"
android:paddingEnd="?attr/sudMarginEnd"
android:fontFamily="@*android:string/config_headlineFontFamily" />
<com.google.android.setupdesign.view.FillContentLayout
style="@style/LockPatternContainerStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1">
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"/>
</com.google.android.setupdesign.view.FillContentLayout>
<TextView android:id="@+id/footerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="24dp"
android:textSize="14sp"
android:visibility="gone"/>
<Button
android:id="@+id/screen_lock_options"
style="@style/SudGlifButton.Tertiary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/setup_lock_settings_options_button_label"
android:visibility="gone"/>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_enterprise">
<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
android:id="@+id/topLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="24dp">
<Button
android:id="@+id/cancelButton"
style="@style/SudGlifButton.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="?attr/sudMarginStart"
android:layout_marginEnd="?attr/sudMarginEnd"
android:layout_marginBottom="80dp"
android:text="@string/cancel" />
<Button
android:id="@+id/forgotButton"
style="@style/SudGlifButton.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="?attr/sudMarginStart"
android:layout_marginEnd="?attr/sudMarginEnd"
android:layout_gravity="center"
android:visibility="gone" />
</LinearLayout>
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<com.google.android.setupdesign.view.FillContentLayout
style="@style/LockPatternContainerStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1">
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
</com.google.android.setupdesign.view.FillContentLayout>
<TextView
style="@style/TextAppearance.ErrorText"
android:accessibilityLiveRegion="polite"
android:id="@+id/errorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingStart="?attr/sudMarginStart"
android:paddingEnd="?attr/sudMarginEnd"
android:layout_marginTop="12dp"
android:gravity="center_vertical"/>
</LinearLayout>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_lock">
<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
android:id="@+id/topLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<com.google.android.setupdesign.view.FillContentLayout
style="@style/LockPatternContainerStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1">
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
</com.google.android.setupdesign.view.FillContentLayout>
<TextView
style="@style/TextAppearance.ErrorText"
android:accessibilityLiveRegion="polite"
android:id="@+id/errorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginStart="?attr/sudMarginStart"
android:layout_marginEnd="?attr/sudMarginEnd"
android:gravity="center_vertical"/>
<Button
android:id="@+id/cancelButton"
style="@style/SudGlifButton.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="?attr/sudMarginStart"
android:layout_marginEnd="?attr/sudMarginEnd"
android:layout_marginBottom="80dp"
android:text="@string/cancel" />
</LinearLayout>
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -51,13 +51,12 @@
style="@style/LockPatternContainerStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:minHeight="@dimen/choose_lockscreen_min_height"
android:layout_weight="1">
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="@dimen/biometric_auth_pattern_view_size"
android:layout_height="@dimen/biometric_auth_pattern_view_size"
android:layout_gravity="center"/>
</com.google.android.setupdesign.view.FillContentLayout>
@@ -66,7 +65,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="50dip"
android:minHeight="24dp"
android:textSize="14sp"
android:visibility="gone"/>

View File

@@ -67,13 +67,12 @@
style="@style/LockPatternContainerStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:minHeight="@dimen/choose_lockscreen_min_height"
android:layout_weight="1">
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="@dimen/biometric_auth_pattern_view_size"
android:layout_height="@dimen/biometric_auth_pattern_view_size"
android:layout_gravity="center" />
</com.google.android.setupdesign.view.FillContentLayout>

View File

@@ -39,13 +39,12 @@
style="@style/LockPatternContainerStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:minHeight="@dimen/choose_lockscreen_min_height"
android:layout_weight="1">
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="@dimen/biometric_auth_pattern_view_size"
android:layout_height="@dimen/biometric_auth_pattern_view_size"
android:layout_gravity="center" />
</com.google.android.setupdesign.view.FillContentLayout>

File diff suppressed because one or more lines are too long

View File

@@ -28,4 +28,8 @@
<!-- Display, Screen zoom -->
<dimen name="screen_zoom_preview_height">160dp</dimen>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">248dp</dimen>
<dimen name="biometric_auth_pattern_view_max_size">348dp</dimen>
</resources>

View File

@@ -0,0 +1,28 @@
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<resources>
<style name="LockPatternContainerStyle">
<item name="android:maxHeight">@dimen/biometric_auth_pattern_view_max_size</item>
<item name="android:maxWidth">@dimen/biometric_auth_pattern_view_max_size</item>
<item name="android:minHeight">@dimen/biometric_auth_pattern_view_size</item>
<item name="android:minWidth">@dimen/biometric_auth_pattern_view_size</item>
<item name="android:gravity">center</item>
<item name="android:paddingBottom">0dp</item>
<item name="android:paddingHorizontal">0dp</item>
<item name="android:paddingTop">0dp</item>
</style>
</resources>

View File

@@ -25,4 +25,7 @@
<!-- Suggestion cards-->
<dimen name="suggestion_card_padding_bottom_one_card">22dp</dimen>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">298dp</dimen>
</resources>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">248dp</dimen>
<dimen name="biometric_auth_pattern_view_max_size">248dp</dimen>
</resources>

21
res/values-sw392dp/dimens.xml Executable file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">298dp</dimen>
</resources>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">248dp</dimen>
<dimen name="biometric_auth_pattern_view_max_size">348dp</dimen>
</resources>

21
res/values-sw410dp/dimens.xml Executable file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
</resources>

View File

@@ -25,4 +25,8 @@
<!-- Padding for screen pinning -->
<dimen name="screen_pinning_padding_start">128dp</dimen>
<dimen name="screen_pinning_padding_end">128dp</dimen>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">298dp</dimen>
</resources>

View File

@@ -55,4 +55,7 @@
<dimen name="screen_pinning_padding_end">40dp</dimen>
<dimen name="settings_panel_width">560dp</dimen>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
</resources>

View File

@@ -38,4 +38,8 @@
<dimen name="wifi_assistant_padding_start_end">24dp</dimen>
<dimen name="wifi_assistant_padding">25dp</dimen>
<dimen name="wifi_assistant_text_padding">24dp</dimen>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
</resources>

View File

@@ -283,6 +283,19 @@
<!-- ComponentName to launch a vendor-specific enrollment activity if available -->
<string name="config_face_enroll" translatable="false"></string>
<!-- ComponentName to launch a vendor-specific posture guidance activity if available -->
<string name="config_face_enroll_guidance_page" translatable="false"></string>
<!-- Whether to support posture listening for face auth, default is 0(DEVICE_POSTURE_UNKNOWN)
means setting will try listening on device posture changes.
0 : DEVICE_POSTURE_UNKNOWN
1 : DEVICE_POSTURE_CLOSED
2 : DEVICE_POSTURE_HALF_OPENED
3 : DEVICE_POSTURE_OPENED
4 : DEVICE_POSTURE_FLIPPED
-->
<integer name="config_face_enroll_supported_posture">0</integer>
<!-- Whether to show the "less secure" info section on the face enroll intro screen -->
<bool name="config_face_intro_show_less_secure">false</bool>
@@ -292,6 +305,9 @@
<!-- Whether to use the Lottie animation for the face education enrollment screen -->
<bool name="config_face_education_use_lottie">false</bool>
<!-- Whether to support enrollment during setup wizard flow -->
<bool name="config_suw_support_face_enroll">true</bool>
<!-- App intent -->
<string name="config_account_intent_uri" translatable="false"></string>

View File

@@ -242,6 +242,10 @@
<item name="face_preview_scale" format="float" type="dimen">1.0</item>
<dimen name="face_enroll_intro_illustration_margin_bottom">0dp</dimen>
<!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
<dimen name="biometric_auth_pattern_view_max_size">@dimen/biometric_auth_pattern_view_size</dimen>
<!-- Confirm device credentials -->
<dimen name="confirm_credentials_security_method_margin">48dp</dimen>
<dimen name="confirm_credentials_layout_width">@dimen/match_parent</dimen>

View File

@@ -1407,6 +1407,8 @@
<string name="security_settings_fingerprint_enroll_touch_dialog_title">Whoops, that\u2019s not the sensor</string>
<!-- Dialog message for dialog which shows when user touches the icon on the screen, instead of the sensor at the back [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_touch_dialog_message">Touch the sensor on the back of your phone. Use your index finger.</string>
<!-- Dialog message for dialog which shows when finger cannot be processed in enrollment. [CHAR LIMIT=45] -->
<string name="security_settings_fingerprint_enroll_error_unable_to_process_dialog_title">Enrollment was not completed</string>
<!-- Dialog message for dialog which shows when finger cannot be enrolled. [CHAR LIMIT=45] -->
<string name="security_settings_fingerprint_enroll_error_dialog_title">Fingerprint setup timed out</string>
<!-- Dialog message for dialog which shows when finger cannot be enrolled due to being idle too long. -->

View File

@@ -432,10 +432,11 @@
</style>
<style name="LockPatternContainerStyle">
<item name="android:maxHeight">620dp</item>
<item name="android:maxWidth">620dp</item>
<item name="android:minHeight">0dp</item>
<item name="android:minWidth">0dp</item>
<item name="android:gravity">center</item>
<item name="android:maxHeight">@dimen/biometric_auth_pattern_view_max_size</item>
<item name="android:maxWidth">@dimen/biometric_auth_pattern_view_max_size</item>
<item name="android:minHeight">@dimen/biometric_auth_pattern_view_size</item>
<item name="android:minWidth">@dimen/biometric_auth_pattern_view_size</item>
<item name="android:paddingBottom">0dp</item>
<item name="android:paddingHorizontal">0dp</item>
<item name="android:paddingTop">0dp</item>

View File

@@ -26,7 +26,8 @@
<com.android.settingslib.widget.IllustrationPreference
android:key="bubbles_illustration"
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_bubbles"/>
app:lottie_rawRes="@raw/lottie_bubbles"
settings:controller="com.android.settings.notification.BubbleNotificationIllustrationPreferenceController"/>
<com.android.settingslib.widget.MainSwitchPreference
android:key="global_notification_bubbles"

View File

@@ -36,6 +36,7 @@ import androidx.window.embedding.SplitRule;
import com.android.settings.Settings;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.biometrics.face.FaceEnrollIntroductionInternal;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal;
@@ -228,6 +229,8 @@ public class ActivityEmbeddingRulesController {
addActivityFilter(activityFilters, FingerprintEnrollIntroduction.class);
addActivityFilter(activityFilters, FingerprintEnrollIntroductionInternal.class);
addActivityFilter(activityFilters, FingerprintEnrollEnrolling.class);
addActivityFilter(activityFilters, FaceEnrollIntroductionInternal.class);
addActivityFilter(activityFilters, Settings.FaceSettingsInternalActivity.class);
addActivityFilter(activityFilters, AvatarPickerActivity.class);
mSplitController.registerRule(new ActivityRule(activityFilters, true /* alwaysExpand */));
}

View File

@@ -48,6 +48,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.core.InstrumentedActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockPattern;
import com.android.settings.password.ChooseLockSettingsHelper;
@@ -215,11 +216,16 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
mIsFaceEnrollable =
faceManager.getEnrolledFaces(mUserId).size() < maxEnrolls;
// exclude face enrollment from setup wizard if configured as a convenience
// isSetupWizard is always false for unicorn enrollment, so if consent is
// required check if setup has completed instead.
final boolean isSettingUp = isSetupWizard || (mParentalOptionsRequired
final boolean parentalConsent = isSetupWizard || (mParentalOptionsRequired
&& !WizardManagerHelper.isUserSetupComplete(this));
if (parentalConsent && isMultiSensor && mIsFaceEnrollable) {
// Exclude face enrollment from setup wizard if feature config not supported
// in setup wizard flow, we still allow user enroll faces through settings.
mIsFaceEnrollable = FeatureFactory.getFactory(getApplicationContext())
.getFaceFeatureProvider()
.isSetupWizardSupported(getApplicationContext());
Log.d(TAG, "config_suw_support_face_enroll: " + mIsFaceEnrollable);
}
}
}
if (mHasFeatureFingerprint) {

View File

@@ -38,7 +38,10 @@ import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
import com.android.settings.core.InstrumentedActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
import com.android.systemui.unfold.updates.FoldProvider;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
@@ -60,8 +63,10 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
public static final String EXTRA_KEY_SENSOR_ID = "sensor_id";
public static final String EXTRA_KEY_CHALLENGE = "challenge";
public static final String EXTRA_KEY_MODALITY = "sensor_modality";
public static final String EXTRA_KEY_NEXT_LAUNCHED = "next_launched";
public static final String EXTRA_FINISHED_ENROLL_FACE = "finished_enrolling_face";
public static final String EXTRA_FINISHED_ENROLL_FINGERPRINT = "finished_enrolling_fingerprint";
public static final String EXTRA_LAUNCHED_POSTURE_GUIDANCE = "launched_posture_guidance";
/**
* Used by the choose fingerprint wizard to indicate the wizard is
@@ -115,14 +120,25 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
* example, when starting fingerprint enroll after face enroll.
*/
public static final int ENROLL_NEXT_BIOMETRIC_REQUEST = 6;
public static final int REQUEST_POSTURE_GUIDANCE = 7;
protected boolean mLaunchedConfirmLock;
protected boolean mLaunchedPostureGuidance;
protected boolean mNextLaunched;
protected byte[] mToken;
protected int mUserId;
protected int mSensorId;
@BiometricUtils.DevicePostureInt
protected int mDevicePostureState;
protected long mChallenge;
protected boolean mFromSettingsSummary;
protected FooterBarMixin mFooterBarMixin;
@Nullable
protected ScreenSizeFoldProvider mScreenSizeFoldProvider;
@Nullable
protected Intent mPostureGuidanceIntent = null;
@Nullable
protected FoldProvider.FoldCallback mFoldCallback = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -139,16 +155,23 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
}
mFromSettingsSummary = getIntent().getBooleanExtra(EXTRA_FROM_SETTINGS_SUMMARY, false);
if (savedInstanceState != null && mToken == null) {
mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM);
mToken = savedInstanceState.getByteArray(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
mFromSettingsSummary =
savedInstanceState.getBoolean(EXTRA_FROM_SETTINGS_SUMMARY, false);
mChallenge = savedInstanceState.getLong(EXTRA_KEY_CHALLENGE);
mSensorId = savedInstanceState.getInt(EXTRA_KEY_SENSOR_ID);
if (savedInstanceState != null) {
if (mToken == null) {
mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM);
mToken = savedInstanceState.getByteArray(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
mFromSettingsSummary =
savedInstanceState.getBoolean(EXTRA_FROM_SETTINGS_SUMMARY, false);
mChallenge = savedInstanceState.getLong(EXTRA_KEY_CHALLENGE);
mSensorId = savedInstanceState.getInt(EXTRA_KEY_SENSOR_ID);
}
mLaunchedPostureGuidance = savedInstanceState.getBoolean(
EXTRA_LAUNCHED_POSTURE_GUIDANCE);
mNextLaunched = savedInstanceState.getBoolean(EXTRA_KEY_NEXT_LAUNCHED);
}
mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
mPostureGuidanceIntent = FeatureFactory.getFactory(getApplicationContext())
.getFaceFeatureProvider().getPostureGuidanceIntent(getApplicationContext());
}
@Override
@@ -159,6 +182,8 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
outState.putBoolean(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
outState.putLong(EXTRA_KEY_CHALLENGE, mChallenge);
outState.putInt(EXTRA_KEY_SENSOR_ID, mSensorId);
outState.putBoolean(EXTRA_LAUNCHED_POSTURE_GUIDANCE, mLaunchedPostureGuidance);
outState.putBoolean(EXTRA_KEY_NEXT_LAUNCHED, mNextLaunched);
}
@Override
@@ -184,6 +209,12 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
@Override
protected void onStop() {
super.onStop();
if (mScreenSizeFoldProvider != null && mFoldCallback != null) {
mScreenSizeFoldProvider.unregisterCallback(mFoldCallback);
}
mScreenSizeFoldProvider = null;
mFoldCallback = null;
if (!isChangingConfigurations() && shouldFinishWhenBackgrounded()
&& !BiometricUtils.isAnyMultiBiometricFlow(this)) {
setResult(RESULT_TIMEOUT);
@@ -191,6 +222,17 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
}
}
protected boolean launchPostureGuidance() {
if (mPostureGuidanceIntent == null || mLaunchedPostureGuidance) {
return false;
}
BiometricUtils.copyMultiBiometricExtras(getIntent(), mPostureGuidanceIntent);
startActivityForResult(mPostureGuidanceIntent, REQUEST_POSTURE_GUIDANCE);
mLaunchedPostureGuidance = true;
overridePendingTransition(0 /* no enter anim */, 0 /* no exit anim */);
return mLaunchedPostureGuidance;
}
protected boolean shouldFinishWhenBackgrounded() {
return !WizardManagerHelper.isAnySetupWizard(getIntent());
}

View File

@@ -155,6 +155,8 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
if (savedInstanceState != null) {
mConfirmingCredentials = savedInstanceState.getBoolean(KEY_CONFIRMING_CREDENTIALS);
mHasScrolledToBottom = savedInstanceState.getBoolean(KEY_SCROLLED_TO_BOTTOM);
mLaunchedPostureGuidance = savedInstanceState.getBoolean(
EXTRA_LAUNCHED_POSTURE_GUIDANCE);
}
Intent intent = getIntent();
@@ -273,6 +275,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
finish();
}
}
mNextLaunched = true;
}
private void launchChooseLock() {

View File

@@ -16,6 +16,7 @@
package com.android.settings.biometrics;
import android.annotation.IntDef;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
@@ -47,17 +48,53 @@ import com.android.settings.password.SetupChooseLockGeneric;
import com.google.android.setupcompat.util.WizardManagerHelper;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Common biometric utilities.
*/
public class BiometricUtils {
private static final String TAG = "BiometricUtils";
// Note: Theis IntDef must align SystemUI DevicePostureInt
@IntDef(prefix = {"DEVICE_POSTURE_"}, value = {
DEVICE_POSTURE_UNKNOWN,
DEVICE_POSTURE_CLOSED,
DEVICE_POSTURE_HALF_OPENED,
DEVICE_POSTURE_OPENED,
DEVICE_POSTURE_FLIPPED
})
@Retention(RetentionPolicy.SOURCE)
public @interface DevicePostureInt {}
// NOTE: These constants **must** match those defined for Jetpack Sidecar. This is because we
// use the Device State -> Jetpack Posture map in DevicePostureControllerImpl to translate
// between the two.
public static final int DEVICE_POSTURE_UNKNOWN = 0;
public static final int DEVICE_POSTURE_CLOSED = 1;
public static final int DEVICE_POSTURE_HALF_OPENED = 2;
public static final int DEVICE_POSTURE_OPENED = 3;
public static final int DEVICE_POSTURE_FLIPPED = 4;
public static int sAllowEnrollPosture = DEVICE_POSTURE_UNKNOWN;
/**
* Request was sent for starting another enrollment of a previously
* enrolled biometric of the same type.
*/
public static int REQUEST_ADD_ANOTHER = 7;
/**
* Gatekeeper credential not match exception, it throws if VerifyCredentialResponse is not
* matched in requestGatekeeperHat().
*/
public static class GatekeeperCredentialNotMatchException extends IllegalStateException {
public GatekeeperCredentialNotMatchException(String s) {
super(s);
}
};
/**
* Given the result from confirming or choosing a credential, request Gatekeeper to generate
* a HardwareAuthToken with the Gatekeeper Password together with a biometric challenge.
@@ -67,6 +104,8 @@ public class BiometricUtils {
* @param userId User ID that the credential/biometric operation applies to
* @param challenge Unique biometric challenge from FingerprintManager/FaceManager
* @return
* @throws GatekeeperCredentialNotMatchException if Gatekeeper response is not match
* @throws IllegalStateException if Gatekeeper Password is missing
*/
public static byte[] requestGatekeeperHat(@NonNull Context context, @NonNull Intent result,
int userId, long challenge) {
@@ -84,7 +123,7 @@ public class BiometricUtils {
final VerifyCredentialResponse response = utils.verifyGatekeeperPasswordHandle(gkPwHandle,
challenge, userId);
if (!response.isMatched()) {
throw new IllegalStateException("Unable to request Gatekeeper HAT");
throw new GatekeeperCredentialNotMatchException("Unable to request Gatekeeper HAT");
}
return response.getGatekeeperHAT();
}
@@ -270,6 +309,51 @@ public class BiometricUtils {
|| isMultiBiometricFingerprintEnrollmentFlow(activity);
}
/**
* Used to check if the activity is showing a posture guidance to user.
*
* @param devicePosture the device posture state
* @param isLaunchedPostureGuidance True launching a posture guidance to user
* @return True if the activity is showing posture guidance to user
*/
public static boolean isPostureGuidanceShowing(@DevicePostureInt int devicePosture,
boolean isLaunchedPostureGuidance) {
return !isPostureAllowEnrollment(devicePosture) && isLaunchedPostureGuidance;
}
/**
* Used to check if current device posture state is allow to enroll biometrics.
* For compatibility, we don't restrict enrollment if device do not config.
*
* @param devicePosture True if current device posture allow enrollment
* @return True if current device posture state allow enrollment
*/
public static boolean isPostureAllowEnrollment(@DevicePostureInt int devicePosture) {
return (sAllowEnrollPosture == DEVICE_POSTURE_UNKNOWN)
|| (devicePosture == sAllowEnrollPosture);
}
/**
* Used to check if the activity should show a posture guidance to user.
*
* @param devicePosture the device posture state
* @param isLaunchedPostureGuidance True launching a posture guidance to user
* @return True if posture disallow enroll and posture guidance not showing, false otherwise.
*/
public static boolean shouldShowPostureGuidance(@DevicePostureInt int devicePosture,
boolean isLaunchedPostureGuidance) {
return !isPostureAllowEnrollment(devicePosture) && !isLaunchedPostureGuidance;
}
/**
* Sets allowed device posture for face enrollment.
*
* @param devicePosture the allowed posture state {@link DevicePostureInt} for enrollment
*/
public static void setDevicePosturesAllowEnroll(@DevicePostureInt int devicePosture) {
sAllowEnrollPosture = devicePosture;
}
public static void copyMultiBiometricExtras(@NonNull Intent fromIntent,
@NonNull Intent toIntent) {
PendingIntent pendingIntent = (PendingIntent) fromIntent.getExtra(

View File

@@ -16,24 +16,35 @@
package com.android.settings.biometrics.face;
import static com.android.settings.biometrics.BiometricUtils.isPostureAllowEnrollment;
import static com.android.settings.biometrics.BiometricUtils.isPostureGuidanceShowing;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
import android.hardware.face.FaceManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.CompoundButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.SetupSkipDialog;
import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
import com.android.systemui.unfold.updates.FoldProvider;
import com.airbnb.lottie.LottieAnimationView;
import com.google.android.setupcompat.template.FooterBarMixin;
@@ -41,18 +52,19 @@ import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.view.IllustrationVideoView;
/**
* Provides animated education for users to know how to enroll a face with appropriate posture.
*/
public class FaceEnrollEducation extends BiometricEnrollBase {
private static final String TAG = "FaceEducation";
private FaceManager mFaceManager;
private FaceEnrollAccessibilityToggle mSwitchDiversity;
private boolean mIsUsingLottie;
private IllustrationVideoView mIllustrationDefault;
private LottieAnimationView mIllustrationLottie;
private View mIllustrationAccessibility;
private Intent mResultIntent;
private boolean mNextClicked;
private boolean mAccessibilityEnabled;
private final CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
@@ -154,6 +166,34 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
}
}
@Override
protected void onStart() {
super.onStart();
if (getPostureGuidanceIntent() == null) {
Log.d(TAG, "Device do not support posture guidance");
return;
}
BiometricUtils.setDevicePosturesAllowEnroll(
getResources().getInteger(R.integer.config_face_enroll_supported_posture));
if (getPostureCallback() == null) {
mFoldCallback = isFolded -> {
mDevicePostureState = isFolded ? BiometricUtils.DEVICE_POSTURE_CLOSED
: BiometricUtils.DEVICE_POSTURE_OPENED;
if (BiometricUtils.shouldShowPostureGuidance(mDevicePostureState,
mLaunchedPostureGuidance) && !mNextLaunched) {
launchPostureGuidance();
}
};
}
if (mScreenSizeFoldProvider == null) {
mScreenSizeFoldProvider = new ScreenSizeFoldProvider(getApplicationContext());
mScreenSizeFoldProvider.registerCallback(mFoldCallback, getMainExecutor());
}
}
@Override
protected void onResume() {
super.onResume();
@@ -172,7 +212,8 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
@Override
protected boolean shouldFinishWhenBackgrounded() {
return super.shouldFinishWhenBackgrounded() && !mNextClicked;
return super.shouldFinishWhenBackgrounded() && !mNextLaunched
&& !isPostureGuidanceShowing(mDevicePostureState, mLaunchedPostureGuidance);
}
@Override
@@ -206,13 +247,14 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
FaceEnrollAccessibilityDialog dialog = FaceEnrollAccessibilityDialog.newInstance();
dialog.setPositiveButtonListener((dialog1, which) -> {
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
mNextClicked = true;
mNextLaunched = true;
});
dialog.show(getSupportFragmentManager(), FaceEnrollAccessibilityDialog.class.getName());
} else {
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
mNextClicked = true;
mNextLaunched = true;
}
}
protected void onSkipButtonClick(View view) {
@@ -223,15 +265,29 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
}
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mScreenSizeFoldProvider != null && getPostureCallback() != null) {
mScreenSizeFoldProvider.onConfigurationChange(newConfig);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_POSTURE_GUIDANCE) {
mLaunchedPostureGuidance = false;
if (resultCode == RESULT_CANCELED || resultCode == RESULT_SKIP) {
onSkipButtonClick(getCurrentFocus());
}
return;
}
mResultIntent = data;
boolean hasEnrolledFace = false;
if (data != null) {
hasEnrolledFace = data.getBooleanExtra(EXTRA_FINISHED_ENROLL_FACE, false);
}
if (resultCode == RESULT_TIMEOUT) {
if (resultCode == RESULT_TIMEOUT || !isPostureAllowEnrollment(mDevicePostureState)) {
setResult(resultCode, data);
finish();
} else if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST
@@ -243,6 +299,26 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
finish();
}
}
mNextLaunched = false;
super.onActivityResult(requestCode, resultCode, data);
}
@VisibleForTesting
@Nullable
protected Intent getPostureGuidanceIntent() {
return mPostureGuidanceIntent;
}
@VisibleForTesting
@Nullable
protected FoldProvider.FoldCallback getPostureCallback() {
return mFoldCallback;
}
@VisibleForTesting
@BiometricUtils.DevicePostureInt
protected int getDevicePostureState() {
return mDevicePostureState;
}
@Override
@@ -262,8 +338,10 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
private void showDefaultIllustration() {
if (mIsUsingLottie) {
mIllustrationLottie.setAnimation(R.raw.face_education_lottie);
mIllustrationLottie.setVisibility(View.VISIBLE);
mIllustrationLottie.playAnimation();
mIllustrationLottie.setProgress(0f);
} else {
mIllustrationDefault.setVisibility(View.VISIBLE);
mIllustrationDefault.start();

View File

@@ -18,9 +18,12 @@ package com.android.settings.biometrics.face;
import static android.app.admin.DevicePolicyResources.Strings.Settings.FACE_UNLOCK_DISABLED;
import static com.android.settings.biometrics.BiometricUtils.GatekeeperCredentialNotMatchException;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.content.res.Configuration;
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;
@@ -36,6 +39,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -43,11 +47,12 @@ import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.BiometricEnrollIntroduction;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.MultiBiometricEnrollHelper;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.SetupSkipDialog;
import com.android.settings.utils.SensorPrivacyManagerHelper;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
import com.android.systemui.unfold.updates.FoldProvider;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -61,7 +66,6 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceEnrollIntroduction";
private FaceManager mFaceManager;
private FaceFeatureProvider mFaceFeatureProvider;
@Nullable private FooterButton mPrimaryFooterButton;
@Nullable private FooterButton mSecondaryFooterButton;
@Nullable private SensorPrivacyManager mSensorPrivacyManager;
@@ -98,6 +102,12 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
}
}
@Override
protected boolean shouldFinishWhenBackgrounded() {
return super.shouldFinishWhenBackgrounded() && !BiometricUtils.isPostureGuidanceShowing(
mDevicePostureState, mLaunchedPostureGuidance);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -142,9 +152,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
infoMessageRequireEyes.setText(getInfoMessageRequireEyes());
}
mFaceManager = Utils.getFaceManagerOrNull(this);
mFaceFeatureProvider = FeatureFactory.getFactory(getApplicationContext())
.getFaceFeatureProvider();
mFaceManager = getFaceManager();
// This path is an entry point for SetNewPasswordController, e.g.
// adb shell am start -a android.app.action.SET_NEW_PASSWORD
@@ -154,11 +162,22 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
// We either block on generateChallenge, or need to gray out the "next" button until
// the challenge is ready. Let's just do this for now.
mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId,
challenge);
mSensorId = sensorId;
mChallenge = challenge;
mFooterBarMixin.getPrimaryButton().setEnabled(true);
if (isFinishing()) {
// Do nothing if activity is finishing
Log.w(TAG, "activity finished before challenge callback launched.");
return;
}
try {
mToken = requestGatekeeperHat(challenge);
mSensorId = sensorId;
mChallenge = challenge;
mFooterBarMixin.getPrimaryButton().setEnabled(true);
} catch (GatekeeperCredentialNotMatchException e) {
// Let BiometricEnrollBase#onCreate() to trigger confirmLock()
getIntent().removeExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE);
recreate();
}
});
}
}
@@ -172,8 +191,82 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
Log.v(TAG, "cameraPrivacyEnabled : " + cameraPrivacyEnabled);
}
@VisibleForTesting
@Nullable
protected FaceManager getFaceManager() {
return Utils.getFaceManagerOrNull(this);
}
@VisibleForTesting
@Nullable
protected Intent getPostureGuidanceIntent() {
return mPostureGuidanceIntent;
}
@VisibleForTesting
@Nullable
protected FoldProvider.FoldCallback getPostureCallback() {
return mFoldCallback;
}
@VisibleForTesting
@BiometricUtils.DevicePostureInt
protected int getDevicePostureState() {
return mDevicePostureState;
}
@VisibleForTesting
@Nullable
protected byte[] requestGatekeeperHat(long challenge) {
return BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mScreenSizeFoldProvider != null && getPostureCallback() != null) {
mScreenSizeFoldProvider.onConfigurationChange(newConfig);
}
}
@Override
protected void onStart() {
super.onStart();
if (getPostureGuidanceIntent() == null) {
Log.d(TAG, "Device do not support posture guidance");
return;
}
BiometricUtils.setDevicePosturesAllowEnroll(
getResources().getInteger(R.integer.config_face_enroll_supported_posture));
if (getPostureCallback() == null) {
mFoldCallback = isFolded -> {
mDevicePostureState = isFolded ? BiometricUtils.DEVICE_POSTURE_CLOSED
: BiometricUtils.DEVICE_POSTURE_OPENED;
if (BiometricUtils.shouldShowPostureGuidance(mDevicePostureState,
mLaunchedPostureGuidance) && !mNextLaunched) {
launchPostureGuidance();
}
};
}
if (mScreenSizeFoldProvider == null) {
mScreenSizeFoldProvider = new ScreenSizeFoldProvider(getApplicationContext());
mScreenSizeFoldProvider.registerCallback(mFoldCallback, getMainExecutor());
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_POSTURE_GUIDANCE) {
mLaunchedPostureGuidance = false;
if (resultCode == RESULT_CANCELED || resultCode == RESULT_SKIP) {
onSkipButtonClick(getCurrentFocus());
}
return;
}
// If user has skipped or finished enrolling, don't restart enrollment.
final boolean isEnrollRequest = requestCode == BIOMETRIC_FIND_SENSOR_REQUEST
|| requestCode == ENROLL_NEXT_BIOMETRIC_REQUEST;
@@ -184,10 +277,12 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
hasEnrolledFace = data.getBooleanExtra(EXTRA_FINISHED_ENROLL_FACE, false);
}
if (resultCode == RESULT_CANCELED && hasEnrolledFace) {
setResult(resultCode, data);
finish();
return;
if (resultCode == RESULT_CANCELED) {
if (hasEnrolledFace || !BiometricUtils.isPostureAllowEnrollment(mDevicePostureState)) {
setResult(resultCode, data);
finish();
return;
}
}
if (isEnrollRequest && isResultSkipOrFinished || hasEnrolledFace) {

View File

@@ -17,9 +17,19 @@
package com.android.settings.biometrics.face;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.Nullable;
/** Feature provider for face unlock */
public interface FaceFeatureProvider {
/** Returns specified intent config by resource R.string.config_face_enroll_guidance_page. */
@Nullable
Intent getPostureGuidanceIntent(Context context);
/** Returns true if attention checking is supported. */
boolean isAttentionSupported(Context context);
/** Returns true if setup wizard supported face enrollment. */
boolean isSetupWizardSupported(Context context);
}

View File

@@ -16,13 +16,48 @@
package com.android.settings.biometrics.face;
import android.content.ComponentName;
import android.content.Context;
import android.provider.Settings;
import android.content.Intent;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.R;
public class FaceFeatureProviderImpl implements FaceFeatureProvider {
/**
* Returns the guidance page intent if device support {@link FoldingFeature}, and we want to
* guide user enrolling faces with specific device posture.
*
* @param context the application context
* @return the posture guidance intent, otherwise null if device not support
*/
@Nullable
@Override
public Intent getPostureGuidanceIntent(Context context) {
final String flattenedString = context.getString(R.string.config_face_enroll_guidance_page);
final Intent intent;
if (!TextUtils.isEmpty(flattenedString)) {
ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
if (componentName != null) {
intent = new Intent();
intent.setComponent(componentName);
return intent;
}
}
return null;
}
@Override
public boolean isAttentionSupported(Context context) {
return true;
}
@Override
public boolean isSetupWizardSupported(@NonNull Context context) {
return true;
}
}

View File

@@ -40,18 +40,20 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class FingerprintErrorDialog extends InstrumentedDialogFragment {
public static final String KEY_ERROR_MSG = "error_msg";
public static final String KEY_ERROR_TITLE = "error_title";
public static final String KEY_ERROR_ID = "error_id";
public static final String KEY_UDFPS = "is_udfps";
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
CharSequence errorString = getArguments().getCharSequence(KEY_ERROR_MSG);
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final CharSequence errorString = getArguments().getCharSequence(KEY_ERROR_MSG);
final CharSequence errorTitle = getArguments().getCharSequence(KEY_ERROR_TITLE);
final int errMsgId = getArguments().getInt(KEY_ERROR_ID);
final boolean canAssumeUdfps = getArguments().getBoolean(KEY_UDFPS, false);
boolean wasTimeout = errMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT;
final boolean wasTimeout = errMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT;
builder.setTitle(R.string.security_settings_fingerprint_enroll_error_dialog_title)
builder.setTitle(errorTitle)
.setMessage(errorString)
.setCancelable(false)
.setPositiveButton(
@@ -60,7 +62,7 @@ public class FingerprintErrorDialog extends InstrumentedDialogFragment {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Activity activity = getActivity();
final Activity activity = getActivity();
if (wasTimeout && !canAssumeUdfps) {
activity.setResult(RESULT_TIMEOUT);
} else {
@@ -76,8 +78,8 @@ public class FingerprintErrorDialog extends InstrumentedDialogFragment {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Activity activity = getActivity();
Intent intent = activity.getIntent();
final Activity activity = getActivity();
final Intent intent = activity.getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
intent.putExtra(KEY_STATE_CANCELED, false);
activity.startActivity(intent);
@@ -90,13 +92,13 @@ public class FingerprintErrorDialog extends InstrumentedDialogFragment {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Activity activity = getActivity();
final Activity activity = getActivity();
activity.setResult(RESULT_TIMEOUT);
activity.finish();
}
});
}
AlertDialog dialog = builder.create();
final AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
@@ -111,11 +113,13 @@ public class FingerprintErrorDialog extends InstrumentedDialogFragment {
return;
}
CharSequence errMsg = host.getText(getErrorMessage(errMsgId));
final CharSequence errTitle = host.getText(getErrorTitle(errMsgId));
if (!canAssumeUdfps
&& errMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) {
errMsg = host.getText(getErrorMessage(BiometricConstants.BIOMETRIC_ERROR_CANCELED));
}
final FingerprintErrorDialog dialog = newInstance(errMsg, errMsgId, canAssumeUdfps);
final FingerprintErrorDialog dialog = newInstance(errMsg, errTitle,
errMsgId, canAssumeUdfps);
dialog.show(fragmentManager, FingerprintErrorDialog.class.getName());
}
@@ -133,11 +137,22 @@ public class FingerprintErrorDialog extends InstrumentedDialogFragment {
}
}
private static FingerprintErrorDialog newInstance(CharSequence msg, int msgId,
boolean canAssumeUdfps) {
FingerprintErrorDialog dialog = new FingerprintErrorDialog();
Bundle args = new Bundle();
private static int getErrorTitle(int errMsgId) {
switch (errMsgId) {
case FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
return R.string
.security_settings_fingerprint_enroll_error_unable_to_process_dialog_title;
default:
return R.string.security_settings_fingerprint_enroll_error_dialog_title;
}
}
private static FingerprintErrorDialog newInstance(CharSequence msg, CharSequence title,
int msgId, boolean canAssumeUdfps) {
final FingerprintErrorDialog dialog = new FingerprintErrorDialog();
final Bundle args = new Bundle();
args.putCharSequence(KEY_ERROR_MSG, msg);
args.putCharSequence(KEY_ERROR_TITLE, title);
args.putInt(KEY_ERROR_ID, msgId);
args.putBoolean(KEY_UDFPS, canAssumeUdfps);
dialog.setArguments(args);

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2023 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.notification;
import android.content.Context;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.IllustrationPreference;
import com.android.settingslib.widget.LottieColorUtils;
/**
* Controller for the illustration shown for the feature level settings screen for bubbles.
*/
public class BubbleNotificationIllustrationPreferenceController extends BasePreferenceController {
public BubbleNotificationIllustrationPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
IllustrationPreference illustrationPreference = screen.findPreference(getPreferenceKey());
illustrationPreference.setOnBindListener(animationView -> {
LottieColorUtils.applyDynamicColors(mContext, animationView);
});
}
}

View File

@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -34,7 +35,6 @@ import androidx.preference.PreferenceScreen;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Set;
@@ -109,9 +109,9 @@ public class NotificationVolumePreferenceController extends
public void onResume() {
super.onResume();
mReceiver.register(true);
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
ActivityThread.currentApplication().getMainExecutor(),
this::onDeviceConfigChange);
Binder.withCleanCallingIdentity(()
-> DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
ActivityThread.currentApplication().getMainExecutor(), this::onDeviceConfigChange));
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
@@ -119,7 +119,8 @@ public class NotificationVolumePreferenceController extends
public void onPause() {
super.onPause();
mReceiver.register(false);
DeviceConfig.removeOnPropertiesChangedListener(this::onDeviceConfigChange);
Binder.withCleanCallingIdentity(() ->
DeviceConfig.removeOnPropertiesChangedListener(this::onDeviceConfigChange));
}
@Override
@@ -127,8 +128,7 @@ public class NotificationVolumePreferenceController extends
boolean separateNotification = isSeparateNotificationConfigEnabled();
return mContext.getResources().getBoolean(R.bool.config_show_notification_volume)
&& !mHelper.isSingleVolume()
&& (separateNotification || !Utils.isVoiceCapable(mContext))
&& !mHelper.isSingleVolume() && separateNotification
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}

View File

@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -33,7 +34,6 @@ import androidx.lifecycle.OnLifecycleEvent;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Set;
@@ -85,8 +85,9 @@ public class RingVolumePreferenceController extends
super.onResume();
mReceiver.register(true);
readSeparateNotificationVolumeConfig();
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
ActivityThread.currentApplication().getMainExecutor(), this::onDeviceConfigChange);
Binder.withCleanCallingIdentity(()
-> DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
ActivityThread.currentApplication().getMainExecutor(), this::onDeviceConfigChange));
updateEffectsSuppressor();
selectPreferenceIconState();
@@ -100,7 +101,8 @@ public class RingVolumePreferenceController extends
public void onPause() {
super.onPause();
mReceiver.register(false);
DeviceConfig.removeOnPropertiesChangedListener(this::onDeviceConfigChange);
Binder.withCleanCallingIdentity(() ->
DeviceConfig.removeOnPropertiesChangedListener(this::onDeviceConfigChange));
}
@Override
@@ -111,8 +113,7 @@ public class RingVolumePreferenceController extends
@Override
public int getAvailabilityStatus() {
boolean separateNotification = isSeparateNotificationConfigEnabled();
return !separateNotification && Utils.isVoiceCapable(mContext) && !mHelper.isSingleVolume()
return !separateNotification && !mHelper.isSingleVolume()
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@@ -124,7 +125,6 @@ public class RingVolumePreferenceController extends
@Override
protected boolean hintsMatch(int hints) {
boolean notificationSeparated = isSeparateNotificationConfigEnabled();
return (hints & NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS) != 0
|| (hints & NotificationListenerService.HINT_HOST_DISABLE_EFFECTS) != 0
|| ((hints & NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS)

View File

@@ -21,6 +21,7 @@ import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioManager;
import android.os.Binder;
import android.os.ServiceManager;
import android.os.Vibrator;
import android.provider.DeviceConfig;
@@ -118,9 +119,10 @@ public abstract class RingerModeAffectedVolumePreferenceController extends
}
protected boolean isSeparateNotificationConfigEnabled() {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
return Binder.withCleanCallingIdentity(()
-> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION,
CONFIG_SEPARATE_NOTIFICATION_DEFAULT_VAL);
CONFIG_SEPARATE_NOTIFICATION_DEFAULT_VAL));
}
/**

View File

@@ -33,7 +33,6 @@ import androidx.lifecycle.OnLifecycleEvent;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Set;
@@ -111,8 +110,7 @@ public class SeparateRingVolumePreferenceController extends
@Override
public int getAvailabilityStatus() {
boolean separateNotification = isSeparateNotificationConfigEnabled();
return separateNotification && Utils.isVoiceCapable(mContext) && !mHelper.isSingleVolume()
return separateNotification && !mHelper.isSingleVolume()
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}

View File

@@ -215,6 +215,7 @@ public class ChooseLockPattern extends SettingsActivity {
private FooterButton mNextButton;
@VisibleForTesting protected LockscreenCredential mChosenPattern;
private ColorStateList mDefaultHeaderColorList;
private View mSudContent;
/**
* The patten used during the help screen to show how to draw a pattern.
@@ -537,6 +538,10 @@ public class ChooseLockPattern extends SettingsActivity {
);
mSkipOrClearButton = mixin.getSecondaryButton();
mNextButton = mixin.getPrimaryButton();
// TODO(b/243008023) Workaround for Glif layout on 2 panel choose lock settings.
mSudContent = layout.findViewById(R.id.sud_layout_content);
mSudContent.setPadding(mSudContent.getPaddingLeft(), 0, mSudContent.getPaddingRight(),
0);
return layout;
}

View File

@@ -100,6 +100,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
private CountDownTimer mCountdownTimer;
private GlifLayout mGlifLayout;
private View mSudContent;
// caller-supplied text for various prompts
private CharSequence mHeaderText;
@@ -129,7 +130,10 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
mGlifLayout = view.findViewById(R.id.setup_wizard_layout);
mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
mErrorTextView = (TextView) view.findViewById(R.id.errorText);
// TODO(b/243008023) Workaround for Glif layout on 2 panel choose lock settings.
mSudContent = mGlifLayout.findViewById(R.id.sud_layout_content);
mSudContent.setPadding(mSudContent.getPaddingLeft(), 0, mSudContent.getPaddingRight(),
0);
mIsManagedProfile = UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId);
// make it so unhandled touch events within the unlock screen go to the

View File

@@ -20,10 +20,10 @@ import static com.android.settings.testutils.ApplicationTestUtils.buildInfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -39,7 +39,6 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,6 +48,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowApplication;
import java.util.Arrays;
import java.util.Collections;
@RunWith(RobolectricTestRunner.class)
public final class AppWithAdminGrantedPermissionsCounterTest {
@@ -129,7 +129,7 @@ public final class AppWithAdminGrantedPermissionsCounterTest {
verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MAIN_USER_ID));
verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(),
eq(MANAGED_PROFILE_ID));
verify(mPackageManager, atLeast(0)).getInstallReason(anyObject(), anyObject());
verify(mPackageManager, atLeast(0)).getInstallReason(any(), any());
verifyNoMoreInteractions(mPackageManager);
}
@@ -166,9 +166,9 @@ public final class AppWithAdminGrantedPermissionsCounterTest {
}
private void configureInstallTimePermissions() throws RemoteException {
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_1_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_1_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_2_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_2_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mPackageManagerService.checkUidPermission(PERMISSION_1, APP_3_UID))
.thenReturn(PackageManager.PERMISSION_DENIED);
@@ -178,9 +178,9 @@ public final class AppWithAdminGrantedPermissionsCounterTest {
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mPackageManagerService.checkUidPermission(PERMISSION_2, APP_4_UID))
.thenReturn(PackageManager.PERMISSION_GRANTED);
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_5_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_5_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_6_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_6_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
}
@@ -189,15 +189,15 @@ public final class AppWithAdminGrantedPermissionsCounterTest {
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION_2))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_2), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_2), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_3), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_3), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_4), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_4), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_5), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_5), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_6), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_6), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
}

View File

@@ -20,10 +20,10 @@ import static com.android.settings.testutils.ApplicationTestUtils.buildInfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -122,19 +122,19 @@ public final class AppWithAdminGrantedPermissionsListerTest {
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION_2))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_2), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_2), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_3), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_3), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_4), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_4), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_5), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_5), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
// Grant install-time permissions as appropriate.
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_1_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_1_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_2_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_2_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mPackageManagerService.checkUidPermission(PERMISSION_1, APP_3_UID))
.thenReturn(PackageManager.PERMISSION_DENIED);
@@ -144,7 +144,7 @@ public final class AppWithAdminGrantedPermissionsListerTest {
.thenReturn(PackageManager.PERMISSION_DENIED);
when(mPackageManagerService.checkUidPermission(PERMISSION_2, APP_4_UID))
.thenReturn(PackageManager.PERMISSION_GRANTED);
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_5_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_5_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
// app3 and app5 were installed by enterprise policy.
@@ -168,11 +168,11 @@ public final class AppWithAdminGrantedPermissionsListerTest {
buildInfo(APP_6_UID, APP_6, 0 /* flags */, Build.VERSION_CODES.M)));
// Grant run-time permissions as appropriate.
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_6), anyObject()))
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_6), any()))
.thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
// Grant install-time permissions as appropriate.
when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_6_UID)))
when(mPackageManagerService.checkUidPermission(any(), eq(APP_6_UID)))
.thenReturn(PackageManager.PERMISSION_DENIED);
// app6 was not installed by enterprise policy.
@@ -202,7 +202,7 @@ public final class AppWithAdminGrantedPermissionsListerTest {
verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MAIN_USER_ID));
verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(),
eq(MANAGED_PROFILE_ID));
verify(mPackageManager, atLeast(0)).getInstallReason(anyObject(), anyObject());
verify(mPackageManager, atLeast(0)).getInstallReason(any(), any());
verifyNoMoreInteractions(mPackageManager);
}

View File

@@ -20,11 +20,11 @@ import static com.android.settings.testutils.ApplicationTestUtils.buildInfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -170,7 +170,7 @@ public final class InstalledAppListerTest {
verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MAIN_USER_ID));
verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MANAGED_PROFILE_ID));
verify(mPackageManager, atLeast(0))
.queryIntentActivitiesAsUser(anyObject(), anyInt(), anyInt());
.queryIntentActivitiesAsUser(any(), anyInt(), anyInt());
}
public static boolean checkAppFound(List<UserAppInfo> mInstalledAppList, String appId,

View File

@@ -20,7 +20,7 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;

View File

@@ -24,7 +24,7 @@ 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.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.Manifest;
@@ -142,6 +142,6 @@ public class DefaultAssistPreferenceControllerTest {
controller.getSettingIntent(null);
verifyZeroInteractions(assistUtils);
verifyNoInteractions(assistUtils);
}
}

View File

@@ -0,0 +1,225 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.biometrics.face;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.util.DisplayMetrics.DENSITY_XXXHIGH;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_NEXT_LAUNCHED;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_LAUNCHED_POSTURE_GUIDANCE;
import static com.android.settings.biometrics.BiometricUtils.DEVICE_POSTURE_CLOSED;
import static com.android.settings.biometrics.BiometricUtils.DEVICE_POSTURE_OPENED;
import static com.android.settings.biometrics.BiometricUtils.DEVICE_POSTURE_UNKNOWN;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.hardware.face.FaceManager;
import android.view.View;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowUtils.class})
public class FaceEnrollEducationTest {
@Mock
private FaceManager mFaceManager;
private Context mContext;
private ActivityController<TestFaceEnrollEducation> mActivityController;
private TestFaceEnrollEducation mActivity;
private FakeFeatureFactory mFakeFeatureFactory;
public static class TestFaceEnrollEducation extends FaceEnrollEducation {
@Override
protected boolean launchPostureGuidance() {
return super.launchPostureGuidance();
}
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowUtils.setFaceManager(mFaceManager);
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
}
@After
public void tearDown() {
ShadowUtils.reset();
}
private void setupActivityForPosture() {
final Intent testIntent = new Intent();
// Set the challenge token so the confirm screen will not be shown
testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
testIntent.putExtra(EXTRA_KEY_NEXT_LAUNCHED, false);
testIntent.putExtra(EXTRA_LAUNCHED_POSTURE_GUIDANCE, false);
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
testIntent);
mContext = spy(ApplicationProvider.getApplicationContext());
mActivityController = Robolectric.buildActivity(
TestFaceEnrollEducation.class, testIntent);
mActivity = spy(mActivityController.create().get());
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
}
private void setupActivity() {
final Intent testIntent = new Intent();
// Set the challenge token so the confirm screen will not be shown
testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
null /* Simulate no posture intent */);
mContext = spy(ApplicationProvider.getApplicationContext());
mActivityController = Robolectric.buildActivity(
TestFaceEnrollEducation.class, testIntent);
mActivity = spy(mActivityController.create().get());
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
}
private GlifLayout getGlifLayout() {
return mActivity.findViewById(R.id.setup_wizard_layout);
}
@Test
public void testFaceEnrollEducation_hasHeader() {
setupActivity();
CharSequence headerText = getGlifLayout().getHeaderText();
assertThat(headerText.toString()).isEqualTo(
mContext.getString(R.string.security_settings_face_enroll_education_title));
}
@Test
public void testFaceEnrollEducation_hasDescription() {
setupActivity();
CharSequence desc = getGlifLayout().getDescriptionText();
assertThat(desc.toString()).isEqualTo(
mContext.getString(R.string.security_settings_face_enroll_education_message));
}
@Test
public void testFaceEnrollEducation_showFooterPrimaryButton() {
setupActivity();
FooterBarMixin footer = getGlifLayout().getMixin(FooterBarMixin.class);
FooterButton footerButton = footer.getPrimaryButton();
assertThat(footerButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(footerButton.getText().toString()).isEqualTo(
mContext.getString(R.string.security_settings_face_enroll_education_start));
}
@Test
public void testFaceEnrollEducation_showFooterSecondaryButton() {
setupActivity();
FooterBarMixin footer = getGlifLayout().getMixin(FooterBarMixin.class);
FooterButton footerButton = footer.getSecondaryButton();
assertThat(footerButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(footerButton.getText().toString()).isEqualTo(mContext.getString(
R.string.security_settings_face_enroll_introduction_cancel));
}
@Test
public void testFaceEnrollEducation_defaultNeverLaunchPostureGuidance() {
setupActivity();
assertThat(mActivity.launchPostureGuidance()).isFalse();
assertThat(mActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_UNKNOWN);
}
@Test
public void testFaceEnrollEducation_onStartNeverRegisterPostureChangeCallback() {
setupActivity();
mActivity.onStart();
assertThat(mActivity.getPostureGuidanceIntent()).isNull();
assertThat(mActivity.getPostureCallback()).isNull();
assertThat(mActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_UNKNOWN);
}
@Test
public void testFaceEnrollEducationWithPosture_onStartRegisteredPostureChangeCallback() {
setupActivityForPosture();
mActivity.onStart();
assertThat(mActivity.getPostureGuidanceIntent()).isNotNull();
assertThat(mActivity.getPostureCallback()).isNotNull();
}
@Test
public void testFaceEnrollEducationWithPosture_onFoldedUpdated_unFolded() {
final Configuration newConfig = new Configuration();
newConfig.smallestScreenWidthDp = DENSITY_XXXHIGH;
setupActivityForPosture();
mActivity.onStart();
assertThat(mActivity.getPostureGuidanceIntent()).isNotNull();
assertThat(mActivity.getPostureCallback()).isNotNull();
mActivity.onConfigurationChanged(newConfig);
assertThat(mActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_OPENED);
}
@Test
public void testFaceEnrollEducationWithPosture_onFoldedUpdated_folded() {
final Configuration newConfig = new Configuration();
newConfig.smallestScreenWidthDp = DENSITY_DEFAULT;
setupActivityForPosture();
mActivity.onStart();
assertThat(mActivity.getPostureGuidanceIntent()).isNotNull();
assertThat(mActivity.getPostureCallback()).isNotNull();
mActivity.onConfigurationChanged(newConfig);
assertThat(mActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_CLOSED);
}
}

View File

@@ -0,0 +1,403 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.biometrics.face;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.util.DisplayMetrics.DENSITY_XXXHIGH;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_NEXT_LAUNCHED;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_LAUNCHED_POSTURE_GUIDANCE;
import static com.android.settings.biometrics.BiometricUtils.DEVICE_POSTURE_CLOSED;
import static com.android.settings.biometrics.BiometricUtils.DEVICE_POSTURE_OPENED;
import static com.android.settings.biometrics.BiometricUtils.DEVICE_POSTURE_UNKNOWN;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.hardware.face.Face;
import android.hardware.face.FaceManager;
import android.os.UserHandle;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
import com.google.android.setupdesign.view.BottomScrollView;
import org.junit.After;
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.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowLockPatternUtils.class,
ShadowUserManager.class,
ShadowUtils.class,
ShadowDevicePolicyManager.class,
ShadowSensorPrivacyManager.class
})
public class FaceEnrollIntroductionTest {
@Mock
private FaceManager mFaceManager;
@Mock
private LockPatternUtils mLockPatternUtils;
private Context mContext;
private ActivityController<? extends Activity> mController;
private TestFaceEnrollIntroduction mActivity;
private FaceEnrollIntroduction mSpyActivity;
private FakeFeatureFactory mFakeFeatureFactory;
private ShadowUserManager mUserManager;
enum GateKeeperAction { CALL_SUPER, RETURN_BYTE_ARRAY, THROW_CREDENTIAL_NOT_MATCH }
public static class TestFaceEnrollIntroduction extends FaceEnrollIntroduction {
private int mRecreateCount = 0;
public int getRecreateCount() {
return mRecreateCount;
}
@Override
public void recreate() {
mRecreateCount++;
// Do nothing
}
public boolean getConfirmingCredentials() {
return mConfirmingCredentials;
}
public FaceManager mOverrideFaceManager = null;
@NonNull
public GateKeeperAction mGateKeeperAction = GateKeeperAction.CALL_SUPER;
@Nullable
@Override
public byte[] requestGatekeeperHat(long challenge) {
switch (mGateKeeperAction) {
case RETURN_BYTE_ARRAY:
return new byte[]{1};
case THROW_CREDENTIAL_NOT_MATCH:
throw new BiometricUtils.GatekeeperCredentialNotMatchException("test");
case CALL_SUPER:
default:
return super.requestGatekeeperHat(challenge);
}
}
@Nullable
@Override
protected FaceManager getFaceManager() {
return mOverrideFaceManager;
}
@Override
protected boolean launchPostureGuidance() {
return super.launchPostureGuidance();
}
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowUtils.setFaceManager(mFaceManager);
mUserManager = ShadowUserManager.getShadow();
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
when(mFakeFeatureFactory.securityFeatureProvider.getLockPatternUtils(any(Context.class)))
.thenReturn(mLockPatternUtils);
}
@After
public void tearDown() {
ShadowUtils.reset();
}
private void setupActivity() {
final Intent testIntent = new Intent();
// Set the challenge token so the confirm screen will not be shown
testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
null /* Simulate no posture intent */);
mContext = spy(ApplicationProvider.getApplicationContext());
mUserManager.addUserProfile(new UserHandle(0));
mController = Robolectric.buildActivity(
TestFaceEnrollIntroduction.class, testIntent);
mActivity = (TestFaceEnrollIntroduction) spy(mController.get());
mActivity.mOverrideFaceManager = mFaceManager;
when(mActivity.getPostureGuidanceIntent()).thenReturn(null);
when(mContext.getApplicationContext()).thenReturn(mContext);
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mLockPatternUtils.getActivePasswordQuality(Mockito.anyInt())).thenReturn(
PASSWORD_QUALITY_NUMERIC);
mController.create();
}
private void setupActivityForPosture() {
final Intent testIntent = new Intent();
// Set the challenge token so the confirm screen will not be shown
testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
testIntent.putExtra(EXTRA_KEY_NEXT_LAUNCHED, false);
testIntent.putExtra(EXTRA_LAUNCHED_POSTURE_GUIDANCE, false);
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
testIntent);
mContext = spy(ApplicationProvider.getApplicationContext());
mUserManager.addUserProfile(new UserHandle(0));
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, testIntent);
mSpyActivity = (FaceEnrollIntroduction) spy(mController.get());
when(mSpyActivity.getPostureGuidanceIntent()).thenReturn(testIntent);
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mLockPatternUtils.getActivePasswordQuality(Mockito.anyInt())).thenReturn(
PASSWORD_QUALITY_NUMERIC);
mController.create();
}
private void setupActivityWithGenerateChallenge(@NonNull Intent intent) {
doAnswer(invocation -> {
final FaceManager.GenerateChallengeCallback callback =
invocation.getArgument(1);
callback.onGenerateChallengeResult(0, 0, 1L);
return null;
}).when(mFaceManager).generateChallenge(anyInt(), any());
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, intent);
mActivity = (TestFaceEnrollIntroduction) mController.get();
mActivity.mOverrideFaceManager = mFaceManager;
}
private GlifLayout getGlifLayout(Activity activity) {
return activity.findViewById(R.id.setup_wizard_layout);
}
private void setFaceManagerToHave(int numEnrollments) {
List<Face> faces = new ArrayList<>();
for (int i = 0; i < numEnrollments; i++) {
faces.add(new Face("Face " + i /* name */, 1 /*faceId */, 1 /* deviceId */));
}
when(mFaceManager.getEnrolledFaces(anyInt())).thenReturn(faces);
}
@Test
public void intro_CheckCanEnroll() {
setFaceManagerToHave(0 /* numEnrollments */);
setupActivityWithGenerateChallenge(new Intent());
mController.create();
int result = mActivity.checkMaxEnrolled();
assertThat(result).isEqualTo(0);
}
@Test
public void intro_CheckMaxEnrolled() {
setFaceManagerToHave(1 /* numEnrollments */);
setupActivityWithGenerateChallenge(new Intent());
mController.create();
int result = mActivity.checkMaxEnrolled();
assertThat(result).isEqualTo(R.string.face_intro_error_max);
}
@Test
public void testOnCreate() {
setupActivityWithGenerateChallenge(new Intent());
mController.create();
}
@Test
public void testOnCreateToGenerateChallenge() {
setupActivityWithGenerateChallenge(
new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
mActivity.mGateKeeperAction = GateKeeperAction.RETURN_BYTE_ARRAY;
mController.create();
}
@Test
public void testGenerateChallengeFailThenRecreate() {
setupActivityWithGenerateChallenge(
new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
mActivity.mGateKeeperAction = GateKeeperAction.THROW_CREDENTIAL_NOT_MATCH;
mController.create();
// Make sure recreate() is called on original activity
assertThat(mActivity.getRecreateCount()).isEqualTo(1);
// Simulate recreate() action
setupActivityWithGenerateChallenge(mActivity.getIntent());
mController.create();
// Verify confirmLock()
assertThat(mActivity.getConfirmingCredentials()).isTrue();
ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
ShadowActivity.IntentForResult startedActivity =
shadowActivity.getNextStartedActivityForResult();
assertWithMessage("Next activity 1").that(startedActivity).isNotNull();
}
@Test
public void testFaceEnrollIntroduction_hasHeader() {
setupActivity();
TextView headerTextView = getGlifLayout(mActivity).findViewById(R.id.suc_layout_title);
assertThat(headerTextView).isNotNull();
assertThat(headerTextView.getText().toString()).isNotEmpty();
}
@Test
public void testFaceEnrollIntroduction_hasDescription() {
setupActivity();
CharSequence desc = getGlifLayout(mActivity).getDescriptionText();
assertThat(desc.toString()).isEqualTo(
mContext.getString(R.string.security_settings_face_enroll_introduction_message));
}
@Test
public void testFaceEnrollEducation_hasBottomScrollView() {
setupActivity();
BottomScrollView scrollView = getGlifLayout(mActivity).findViewById(R.id.sud_scroll_view);
assertThat(scrollView).isNotNull();
assertThat(scrollView.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void testFaceEnrollIntroduction_showFooterPrimaryButton() {
setupActivity();
FooterBarMixin footer = getGlifLayout(mActivity).getMixin(FooterBarMixin.class);
FooterButton footerButton = footer.getPrimaryButton();
assertThat(footerButton).isNotNull();
assertThat(footerButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(footerButton.getText().toString()).isEqualTo(
mContext.getString(R.string.security_settings_face_enroll_introduction_agree));
}
@Test
public void testFaceEnrollIntroduction_notShowFooterSecondaryButton() {
setupActivity();
FooterBarMixin footer = getGlifLayout(mActivity).getMixin(FooterBarMixin.class);
FooterButton footerButton = footer.getSecondaryButton();
assertThat(footerButton.getVisibility()).isEqualTo(View.INVISIBLE);
}
@Test
public void testFaceEnrollIntroduction_defaultNeverLaunchPostureGuidance() {
setupActivity();
assertThat(mActivity.launchPostureGuidance()).isFalse();
assertThat(mActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_UNKNOWN);
}
@Test
public void testFaceEnrollIntroduction_onStartNeverRegisterPostureChangeCallback() {
setupActivity();
mActivity.onStart();
assertThat(mActivity.getPostureGuidanceIntent()).isNull();
assertThat(mActivity.getPostureCallback()).isNull();
assertThat(mActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_UNKNOWN);
}
@Test
public void testFaceEnrollIntroduction_onStartRegisteredPostureChangeCallback() {
setupActivityForPosture();
mSpyActivity.onStart();
assertThat(mSpyActivity.getPostureGuidanceIntent()).isNotNull();
assertThat(mSpyActivity.getPostureCallback()).isNotNull();
}
@Test
public void testFaceEnrollIntroduction_onFoldedUpdated_unFolded() {
final Configuration newConfig = new Configuration();
newConfig.smallestScreenWidthDp = DENSITY_XXXHIGH;
setupActivityForPosture();
mSpyActivity.onStart();
assertThat(mSpyActivity.getPostureGuidanceIntent()).isNotNull();
assertThat(mSpyActivity.getPostureCallback()).isNotNull();
mSpyActivity.onConfigurationChanged(newConfig);
assertThat(mSpyActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_OPENED);
}
@Test
public void testFaceEnrollEducation_onFoldedUpdated_folded() {
final Configuration newConfig = new Configuration();
newConfig.smallestScreenWidthDp = DENSITY_DEFAULT;
setupActivityForPosture();
mSpyActivity.onStart();
assertThat(mSpyActivity.getPostureGuidanceIntent()).isNotNull();
assertThat(mSpyActivity.getPostureCallback()).isNotNull();
mSpyActivity.onConfigurationChanged(newConfig);
assertThat(mSpyActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_CLOSED);
}
}

View File

@@ -25,11 +25,11 @@ import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrol
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;

View File

@@ -21,8 +21,8 @@ import static android.bluetooth.BluetoothDevice.BOND_NONE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

View File

@@ -40,7 +40,7 @@ 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.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -268,7 +268,7 @@ public class DashboardFeatureProviderImplTest {
mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
null /* keys */, tile, "123", Preference.DEFAULT_ORDER);
verifyZeroInteractions(tile);
verifyNoInteractions(tile);
}
@Test

View File

@@ -19,14 +19,14 @@ package com.android.settings.datausage;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

View File

@@ -19,16 +19,15 @@ import static android.net.NetworkPolicy.CYCLE_NONE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.nullable;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -133,9 +132,9 @@ public class BillingCycleSettingsTest {
mDataLimit, mDataWarning, mEnableDataLimit, mEnableDataWarning);
doReturn("some-string").when(billingCycleSettings).getString(anyInt(), anyInt());
when(mNetworkPolicyEditor.getPolicyCycleDay(anyObject())).thenReturn(CYCLE_NONE + 1);
when(mNetworkPolicyEditor.getPolicyLimitBytes(anyObject())).thenReturn(2000L);
when(mNetworkPolicyEditor.getPolicyWarningBytes(anyObject())).thenReturn(1000L);
when(mNetworkPolicyEditor.getPolicyCycleDay(any())).thenReturn(CYCLE_NONE + 1);
when(mNetworkPolicyEditor.getPolicyLimitBytes(any())).thenReturn(2000L);
when(mNetworkPolicyEditor.getPolicyWarningBytes(any())).thenReturn(1000L);
billingCycleSettings.updatePrefs();

View File

@@ -18,7 +18,7 @@ package com.android.settings.datausage.lib;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

View File

@@ -24,7 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.app.time.Capabilities;
@@ -99,7 +99,7 @@ public class LocationTimeZoneDetectionPreferenceControllerTest {
mController.setChecked(true);
// Verify the TimeManager was not called.
verifyZeroInteractions(mTimeManager);
verifyNoInteractions(mTimeManager);
}
@Test

View File

@@ -23,8 +23,8 @@ import static com.android.settings.deviceinfo.firmwareversion.MainlineModuleVers
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

View File

@@ -18,10 +18,10 @@ package com.android.settings.enterprise;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -79,7 +79,7 @@ public abstract class AdminGrantedPermissionsPreferenceControllerTestBase {
}
}).when(mFeatureFactory.applicationFeatureProvider)
.calculateNumberOfAppsWithAdminGrantedPermissions(eq(mPermissions),
eq(async), anyObject());
eq(async), any());
}
@Test

View File

@@ -18,7 +18,7 @@ package com.android.settings.enterprise;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
@@ -74,7 +74,7 @@ public class EnterpriseInstalledPackagesPreferenceControllerTest {
return null;
}
}).when(mFeatureFactory.applicationFeatureProvider)
.calculateNumberOfPolicyInstalledApps(eq(async), anyObject());
.calculateNumberOfPolicyInstalledApps(eq(async), any());
}
@Test

View File

@@ -30,7 +30,7 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
@@ -859,7 +859,7 @@ public class AdvancedPowerUsageDetailTest {
mFragment.onRadioButtonClicked(mOptimizePreference);
mFragment.onPause();
verifyZeroInteractions(mMetricsFeatureProvider);
verifyNoInteractions(mMetricsFeatureProvider);
}
@Test
@@ -870,7 +870,7 @@ public class AdvancedPowerUsageDetailTest {
mFragment.notifyBackupManager();
verifyZeroInteractions(mBackupManager);
verifyNoInteractions(mBackupManager);
}
@Test
@@ -893,6 +893,6 @@ public class AdvancedPowerUsageDetailTest {
mFragment.onPause();
verifyZeroInteractions(mBackupManager);
verifyNoInteractions(mBackupManager);
}
}

View File

@@ -34,7 +34,7 @@ import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import android.app.AppOpsManager;
import android.app.backup.BackupDataInputStream;
@@ -254,7 +254,7 @@ public final class BatteryBackupHelperTest {
mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
verifyZeroInteractions(mBackupDataInputStream);
verifyNoInteractions(mBackupDataInputStream);
}
@Test
@@ -292,13 +292,13 @@ public final class BatteryBackupHelperTest {
@Test
public void restoreOptimizationMode_nullBytesData_skipRestore() throws Exception {
mBatteryBackupHelper.restoreOptimizationMode(new byte[0]);
verifyZeroInteractions(mBatteryOptimizeUtils);
verifyNoInteractions(mBatteryOptimizeUtils);
mBatteryBackupHelper.restoreOptimizationMode("invalid data format".getBytes());
verifyZeroInteractions(mBatteryOptimizeUtils);
verifyNoInteractions(mBatteryOptimizeUtils);
mBatteryBackupHelper.restoreOptimizationMode(DELIMITER.getBytes());
verifyZeroInteractions(mBatteryOptimizeUtils);
verifyNoInteractions(mBatteryOptimizeUtils);
}
@Test

View File

@@ -23,7 +23,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.app.Activity;
@@ -267,7 +267,7 @@ public class BatteryHeaderPreferenceControllerTest {
mController.updateHeaderByBatteryTips(null, mBatteryInfo);
verifyZeroInteractions(mBatteryUsageProgressBarPref);
verifyNoInteractions(mBatteryUsageProgressBarPref);
}
@Test
@@ -277,7 +277,7 @@ public class BatteryHeaderPreferenceControllerTest {
mController.updateHeaderByBatteryTips(lowBatteryTip, null);
verifyZeroInteractions(mBatteryUsageProgressBarPref);
verifyNoInteractions(mBatteryUsageProgressBarPref);
}
@Test

View File

@@ -25,16 +25,16 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
@@ -183,8 +183,8 @@ public class BatteryOptimizeUtilsTest {
mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
TimeUnit.SECONDS.sleep(1);
verifyZeroInteractions(mMockBackend);
verifyZeroInteractions(mMockBatteryUtils);
verifyNoInteractions(mMockBackend);
verifyNoInteractions(mMockBatteryUtils);
}
@Test
@@ -247,7 +247,7 @@ public class BatteryOptimizeUtilsTest {
AppOpsManager.MODE_ALLOWED, /* allowListed */ false,
/* isSystemOrDefaultApp */ false);
verifyZeroInteractions(mMockBatteryUtils);
verifyNoInteractions(mMockBatteryUtils);
final InOrder inOrder = inOrder(mMockBackend);
inOrder.verify(mMockBackend).refreshList();
@@ -261,7 +261,7 @@ public class BatteryOptimizeUtilsTest {
AppOpsManager.MODE_ALLOWED, /* allowListed */ true,
/* isSystemOrDefaultApp */ true);
verifyZeroInteractions(mMockBatteryUtils);
verifyNoInteractions(mMockBatteryUtils);
final InOrder inOrder = inOrder(mMockBackend);
inOrder.verify(mMockBackend).refreshList();

View File

@@ -18,7 +18,7 @@ package com.android.settings.fuelgauge.batteryusage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

View File

@@ -19,7 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;

View File

@@ -16,16 +16,15 @@
package com.android.settings.network;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -162,7 +161,7 @@ public class TetherPreferenceControllerTest {
mController.onResume();
verifyZeroInteractions(mPreference);
verifyNoInteractions(mPreference);
Settings.Global.putInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);

View File

@@ -96,12 +96,16 @@ public class RingVolumePreferenceControllerTest {
assertThat(mController.isAvailable()).isFalse();
}
/**
* Devices that are not voice capable should still show Ring volume, because it is used by apps
* that make calls outside the cell network.
*/
@Test
public void isAvailable_notVoiceCapable_shouldReturnFalse() {
public void isAvailable_notSingleVolume_notVoiceCapable_shouldReturnTrue() {
when(mHelper.isSingleVolume()).thenReturn(false);
when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
assertThat(mController.isAvailable()).isTrue();
}
@Test

View File

@@ -27,8 +27,10 @@ import android.content.Context;
import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Vibrator;
import android.provider.DeviceConfig;
import android.telephony.TelephonyManager;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import org.junit.Before;
@@ -87,6 +89,19 @@ public class SeparateRingVolumePreferenceControllerTest {
assertThat(mController.isAvailable()).isFalse();
}
/**
* Maintain that the device does not need to be voice capable to display this slider
*/
@Test
public void isAvailable_ringNotificationSeparated_isNotVoiceCapable_shouldReturnTrue() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "true", false);
when(mHelper.isSingleVolume()).thenReturn(false);
when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void getAudioStream_shouldReturnRing() {
assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_RING);

View File

@@ -18,6 +18,7 @@ package com.android.settings.notification.zen;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -42,10 +43,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.internal.util.reflection.FieldSetter;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
@@ -192,16 +193,26 @@ public class ZenModeAutomaticRulesPreferenceControllerTest {
rule.setEnabled(false);
rMap.put(testId, rule);
mockGetAutomaticZenRules(NUM_RULES, rMap);
FieldSetter.setField(mZenRulePreference, ZenRulePreference.class.getDeclaredField("mId"), testId);
setZenRulePreferenceField("mId", testId);
mController.updateState(mockPref);
verify(mZenRulePreference, times(1)).updatePreference(any());
verify(mockPref, never()).removeAll();
assertEquals(NUM_RULES, mController.mZenRulePreferences.size());
}
private void setZenRulePreferenceField(String name, Object value) {
try {
Field field = ZenRulePreference.class.getDeclaredField("mId");
field.setAccessible(true);
field.set(mZenRulePreference, value);
} catch (ReflectiveOperationException e) {
fail("Unable to set mZenRulePreference field: " + name);
}
}
private void mockGetAutomaticZenRules(int numRules, Map<String, AutomaticZenRule> rules) {
Map.Entry<String, AutomaticZenRule>[] arr = new Map.Entry[numRules];
rules.entrySet().toArray(arr);
when(mBackend.getAutomaticZenRules()).thenReturn(arr);
}
}
}

View File

@@ -26,7 +26,7 @@ import static com.android.settings.notification.zen.ZenModePriorityConversations
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -146,4 +146,4 @@ public class ZenModePriorityConversationsPreferenceControllerTest {
}
return null;
}
}
}

View File

@@ -30,8 +30,8 @@ import static com.android.settings.notification.zen.ZenPrioritySendersHelper.KEY
import static com.android.settings.notification.zen.ZenPrioritySendersHelper.KEY_NONE;
import static com.android.settings.notification.zen.ZenPrioritySendersHelper.UNKNOWN;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;

View File

@@ -18,7 +18,7 @@ package com.android.settings.notification.zen;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

View File

@@ -21,8 +21,8 @@ import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -72,7 +72,7 @@ public class PrintJobMessagePreferenceControllerTest {
mPreference = new Preference(mContext);
when(mContext.getSystemService(Context.PRINT_SERVICE)).thenReturn(mPrintManager);
when(mPrintManager.getGlobalPrintManagerForUser(anyInt())).thenReturn(mPrintManager);
when(mPrintManager.getPrintJob(anyObject())).thenReturn(mPrintJob);
when(mPrintManager.getPrintJob(any())).thenReturn(mPrintJob);
when(mPrintJob.getInfo()).thenReturn(mPrintJobInfo);
mController = new PrintJobMessagePreferenceController(mContext, PREF_KEY);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
@@ -93,7 +93,7 @@ public class PrintJobMessagePreferenceControllerTest {
@Test
public void updateUi_visiblePreference() {
when(mPrintJobInfo.getStatus(anyObject())).thenReturn("TestPrint");
when(mPrintJobInfo.getStatus(any())).thenReturn("TestPrint");
mLifecycle.handleLifecycleEvent(ON_START);
assertThat(mPreference.isVisible()).isTrue();
@@ -103,7 +103,7 @@ public class PrintJobMessagePreferenceControllerTest {
@Test
public void updateUi_invisiblePreference() {
when(mPrintJobInfo.getStatus(anyObject())).thenReturn(null);
when(mPrintJobInfo.getStatus(any())).thenReturn(null);
mLifecycle.handleLifecycleEvent(ON_START);
assertThat(mPreference.isVisible()).isFalse();

View File

@@ -21,8 +21,8 @@ import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -75,7 +75,7 @@ public class PrintJobPreferenceControllerTest {
mTestLabel = "PrintTest";
when(mContext.getSystemService(Context.PRINT_SERVICE)).thenReturn(mPrintManager);
when(mPrintManager.getGlobalPrintManagerForUser(anyInt())).thenReturn(mPrintManager);
when(mPrintManager.getPrintJob(anyObject())).thenReturn(mPrintJob);
when(mPrintManager.getPrintJob(any())).thenReturn(mPrintJob);
when(mPrintJob.getInfo()).thenReturn(mPrintJobInfo);
mController = new PrintJobPreferenceController(mContext, PREF_KEY);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);

View File

@@ -21,7 +21,7 @@ import static com.android.settings.search.actionbar.SearchMenuController.MENU_SE
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums;
@@ -91,7 +91,7 @@ public class SearchMenuControllerTest {
SearchMenuController.init(mHost);
mHost.getSettingsLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
verifyZeroInteractions(mMenu);
verifyNoInteractions(mMenu);
}
@Test
@@ -100,7 +100,7 @@ public class SearchMenuControllerTest {
SearchMenuController.init(mHost);
mHost.getSettingsLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
verifyZeroInteractions(mMenu);
verifyNoInteractions(mMenu);
}
@Test
@@ -112,6 +112,6 @@ public class SearchMenuControllerTest {
mHost.getSettingsLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
verifyZeroInteractions(mMenu);
verifyNoInteractions(mMenu);
}
}

View File

@@ -26,7 +26,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -111,7 +111,7 @@ public class HighlightablePreferenceGroupAdapterTest {
ReflectionHelpers.setField(mAdapter, "mHighlightRequested", false);
mAdapter.requestHighlight(mRoot, null /* recyclerView */, mock(AppBarLayout.class));
verifyZeroInteractions(mRoot);
verifyNoInteractions(mRoot);
}
@Test
@@ -125,7 +125,7 @@ public class HighlightablePreferenceGroupAdapterTest {
when(mFragment.getArguments()).thenReturn(null);
when(mFragment.getPreferenceScreen()).thenReturn(screen);
HighlightablePreferenceGroupAdapter.adjustInitialExpandedChildCount(mFragment);
verifyZeroInteractions(screen);
verifyNoInteractions(screen);
}
@Test
@@ -150,7 +150,7 @@ public class HighlightablePreferenceGroupAdapterTest {
HighlightablePreferenceGroupAdapter.adjustInitialExpandedChildCount(mFragment);
verify(mFragment).getInitialExpandedChildCount();
verifyZeroInteractions(screen);
verifyNoInteractions(screen);
}
@Test

View File

@@ -195,7 +195,7 @@ public class NetworkRequestDialogFragmentTest {
}
private List<WifiEntry> createWifiEntryList() {
List<WifiEntry> wifiEntryList = spy(new ArrayList<>());
List<WifiEntry> wifiEntryList = new ArrayList<>();
final WifiEntry wifiEntry1 = mock(WifiEntry.class);
when(wifiEntry1.getSsid()).thenReturn("Test AP 1");

View File

@@ -21,9 +21,9 @@ import static com.android.settings.wifi.calling.DisclaimerItemListAdapter
import static com.android.settings.wifi.calling.DisclaimerItemListAdapter
.DisclaimerItemViewHolder.ID_DISCLAIMER_ITEM_TITLE;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -75,7 +75,7 @@ public class DisclaimerItemListAdapterTest {
mDisclaimerItem = spy(new MockDisclaimerItem(mContext, 0 /* subId */));
mDisclaimerItemList.add(mDisclaimerItem);
when(mLayoutInflater.inflate(anyInt(), anyObject(), anyBoolean())).thenReturn(mView);
when(mLayoutInflater.inflate(anyInt(), any(), anyBoolean())).thenReturn(mView);
when(mViewGroup.getContext()).thenReturn(mContext);
when(mViewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).thenReturn(
mLayoutInflater);

View File

@@ -18,8 +18,8 @@ package com.android.settings.wifi.calling;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

View File

@@ -18,8 +18,8 @@ package com.android.settings.wifi.calling;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

View File

@@ -16,10 +16,9 @@
package com.android.settings.wifi.calling;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
@@ -95,7 +94,7 @@ public class WifiCallingDisclaimerFragmentTest {
doReturn(mActivity).when(mFragment).getActivity();
when(mLayoutInflater.inflate(anyInt(), anyObject(), anyBoolean())).thenReturn(mView);
when(mLayoutInflater.inflate(anyInt(), any(), anyBoolean())).thenReturn(mView);
when(mView.findViewById(R.id.agree_button)).thenReturn(mAgreeButton);
when(mView.findViewById(R.id.disagree_button)).thenReturn(mDisagreeButton);
when(mView.findViewById(R.id.disclaimer_item_list)).thenReturn(mRecyclerView);

View File

@@ -16,17 +16,17 @@
package com.android.settings.wifi.calling;
import static junit.framework.Assert.assertEquals;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -44,7 +44,6 @@ import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsMmTelManager;
import android.view.View;
import android.widget.TextView;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

View File

@@ -17,15 +17,16 @@ package com.android.settings.wifi.details2;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.nullable;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -93,7 +94,6 @@ import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InOrder;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -1255,7 +1255,7 @@ public class WifiDetailPreferenceController2Test {
mMockWifiConfig.creatorUid = doUid;
ComponentName doComponent = new ComponentName(doPackage, "some.Class");
try {
when(mMockPackageManager.getPackageUidAsUser(Matchers.anyString(), Matchers.anyInt()))
when(mMockPackageManager.getPackageUidAsUser(anyString(), anyInt()))
.thenReturn(doUid);
} catch (PackageManager.NameNotFoundException e) {
//do nothing