Snap for 7464903 from b8c610b188 to sc-release

Change-Id: I8f4cdce3aefe00c6eaa4f96f78f7df917fdec7d9
This commit is contained in:
android-build-team Robot
2021-06-17 01:09:30 +00:00
54 changed files with 831 additions and 315 deletions

View File

@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="20dp"
android:paddingStart="30dp"
android:paddingEnd="30dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/RequestManageCredentialsHeaderLandscape">
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/credential_management_app_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@null" />
<TextView
android:id="@+id/credential_management_app_title"
style="@style/RequestManageCredentialsTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/credential_management_app_description"
style="@style/RequestManageCredentialsDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/request_manage_credentials_description" />
</LinearLayout>
</ScrollView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="true">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/apps_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/extended_fab"
style="@style/RequestManageCredentialsFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/request_manage_credentials_more"
android:theme="@style/Theme.CollapsingToolbar.Settings"
app:backgroundTint="?android:attr/colorAccent"
app:elevation="3dp"
app:icon="@drawable/ic_arrow_downward"
app:iconTint="?android:attr/textColorPrimary"
app:layout_anchor="@id/apps_list"
app:layout_anchorGravity="bottom|center" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:id="@+id/button_panel"
style="@style/RequestManageCredentialsButtonPanel"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center|bottom">
<Button
android:id="@+id/dont_allow_button"
style="@style/RequestManageCredentialsDontAllowButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/request_manage_credentials_dont_allow" />
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="invisible" />
<Button
android:id="@+id/allow_button"
style="@style/RequestManageCredentialsAllowButton"
android:theme="@style/RoundedCornerButtonTheme"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/request_manage_credentials_allow" />
</LinearLayout>
</LinearLayout>

View File

@@ -20,7 +20,6 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="60dp"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<TextView
@@ -29,11 +28,13 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:accessibilityLiveRegion="polite"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.TextView" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="12dp"
android:gravity="center_vertical">
<ImageView

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<!-- Layout used by BatterySaverScheduleSeekBarController for the seekbar widget. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="6dp"
android:gravity="center_vertical"
android:orientation="vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:layout_marginStart="18dp"
android:singleLine="true"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
android:textColor="?android:attr/textColorPrimary" />
<com.android.settings.widget.DefaultIndicatorSeekBar
android:id="@*android:id/seekbar"
style="@android:style/Widget.Material.SeekBar.Discrete"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginStart="18dp"
android:layout_marginEnd="9dp" />
</LinearLayout>

View File

@@ -25,28 +25,13 @@
android:clickable="false"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="56dp"
android:gravity="start|center_vertical"
android:orientation="horizontal"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<com.android.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="24dp"
android:layout_height="24dp"/>
</LinearLayout>
<include layout="@layout/settingslib_icon_frame"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp">
android:paddingTop="16dp">
<LinearLayout
android:layout_width="match_parent"
@@ -57,7 +42,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:textAppearance="@*android:style/TextAppearance.Material.Subhead"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorPrimary"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>

View File

@@ -21,8 +21,8 @@
android:gravity="center_vertical"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="56dp"
android:paddingEnd="8dp"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="16dp"
android:paddingBottom="8dp">
@@ -30,12 +30,11 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_alignParentTop="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorPrimary" />
<SeekBar
@@ -43,21 +42,19 @@
android:layout_below="@android:id/title"
android:layout_gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_marginTop="-20dp"
android:layout_marginBottom="-28dp"
android:layout_height="48dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
style="@android:style/Widget.Material.SeekBar.Discrete" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@*android:id/seekbar"
android:paddingBottom="8dp"
android:orientation="horizontal">
<TextView
android:id="@android:id/text1"
android:layout_marginStart="16dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start|top"
@@ -66,7 +63,6 @@
<TextView
android:id="@android:id/text2"
android:layout_marginEnd="16dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="end|top"

View File

@@ -25,28 +25,13 @@
android:clickable="false"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="44dp"
android:gravity="start|center_vertical"
android:orientation="horizontal"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<com.android.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="24dp"
android:layout_height="24dp"/>
</LinearLayout>
<include layout="@layout/settingslib_icon_frame"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp">
android:paddingTop="16dp">
<LinearLayout
android:layout_width="match_parent"
@@ -56,9 +41,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingStart="12dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.PreferenceTitle.SettingsLib"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<!-- Preference should place its actual preference widget here. -->
@@ -79,7 +63,8 @@
<SeekBar
android:id="@*android:id/seekbar"
android:layout_gravity="center_vertical"
android:paddingStart="12dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:layout_width="match_parent"
android:layout_height="48dp"/>
@@ -87,7 +72,6 @@
android:id="@+id/suppression_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="12dp"
android:layout_gravity="center_vertical|start"
android:textAlignment="viewStart"
android:singleLine="true"

View File

@@ -15,49 +15,55 @@
-->
<!-- Layout used by SeekBarPreference for the seekbar widget style. -->
<RelativeLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:clickable="false"
android:orientation="horizontal">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:paddingStart="56dp"
android:paddingEnd="8dp"
android:singleLine="true"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
android:textColor="?android:attr/textColorPrimary" />
<include layout="@layout/settingslib_icon_frame"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@android:id/title"
android:layout_below="@android:id/title"
android:maxLines="4"
android:paddingStart="56dp"
android:paddingEnd="8dp"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary" />
<com.android.settings.widget.DefaultIndicatorSeekBar
android:id="@*android:id/seekbar"
style="@android:style/Widget.Material.SeekBar.Discrete"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_below="@android:id/summary"
android:paddingStart="56dp"
android:paddingEnd="12dp" />
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="16dp">
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@android:id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorPrimary"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="end|center_vertical"
android:paddingStart="12dp"
android:orientation="vertical"/>
</LinearLayout>
<SeekBar
android:id="@*android:id/seekbar"
android:layout_gravity="center_vertical"
android:layout_width="match_parent"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:layout_height="48dp"/>
</LinearLayout>
</LinearLayout>

View File

File diff suppressed because one or more lines are too long

View File

View File

View File

View File

View File

View File

View File

@@ -46,6 +46,7 @@
<style name="SettingsSeekBarPreference" parent="@style/Preference.Material">
<item name="android:layout">@layout/preference_widget_seekbar_settings</item>
<item name="iconSpaceReserved">@bool/settingslib_config_icon_space_reserved</item>
</style>
<style name="SyncSwitchPreference" parent="@style/SettingsSwitchPreference.SettingsLib">

View File

@@ -28,6 +28,14 @@
settings:searchable="false"
settings:controller="com.android.settings.gestures.SystemNavigationPreferenceController"/>
<Preference
android:fragment="com.android.settings.gestures.OneHandedSettings"
android:key="gesture_system_navigation_one_handed_accessibility"
android:persistent="false"
android:title="@string/one_handed_title"
settings:searchable="false"
settings:controller="com.android.settings.gestures.OneHandedEnablePreferenceController"/>
<SwitchPreference
android:key="toggle_power_button_ends_call_preference"
android:persistent="false"
@@ -39,4 +47,4 @@
android:persistent="false"
android:title="@string/accelerometer_title"
settings:controller="com.android.settings.accessibility.LockScreenRotationPreferenceController"/>
</PreferenceScreen>
</PreferenceScreen>

View File

@@ -25,6 +25,7 @@
<com.android.settingslib.widget.IllustrationPreference
android:key="bubbles_illustration"
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_bubbles"/>
<com.android.settingslib.widget.MainSwitchPreference

View File

@@ -17,21 +17,20 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/double_tap_power_for_camera_title">
<com.android.settings.widget.VideoPreference
<com.android.settingslib.widget.IllustrationPreference
android:key="gesture_double_tap_power_video"
app:animation="@raw/gesture_double_tap"
app:preview="@drawable/gesture_double_tap"
app:controller="com.android.settings.widget.VideoPreferenceController" />
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_quick_open_camera"/>
<SwitchPreference
android:key="gesture_double_tap_power"
android:title="@string/double_tap_power_for_camera_title"
android:summary="@string/double_tap_power_for_camera_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.DoubleTapPowerPreferenceController"
app:allowDividerAbove="true" />
app:controller="com.android.settings.gestures.DoubleTapPowerPreferenceController"/>
</PreferenceScreen>

View File

@@ -17,21 +17,20 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/double_twist_for_camera_mode_title">
<com.android.settings.widget.VideoPreference
<com.android.settingslib.widget.IllustrationPreference
android:key="gesture_double_twist_video"
app:animation="@raw/gesture_twist"
app:preview="@drawable/gesture_twist"
app:controller="com.android.settings.widget.VideoPreferenceController" />
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_flip_camera_for_selfie"/>
<SwitchPreference
android:key="gesture_double_twist"
android:title="@string/double_twist_for_camera_mode_title"
android:summary="@string/double_twist_for_camera_mode_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.DoubleTwistPreferenceController"
app:allowDividerAbove="true" />
app:controller="com.android.settings.gestures.DoubleTwistPreferenceController" />
</PreferenceScreen>

View File

@@ -18,16 +18,14 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:persistent="false"
android:title="@string/one_handed_title">
<com.android.settingslib.widget.LayoutPreference
<com.android.settingslib.widget.IllustrationPreference
android:key="one_handed_header"
android:layout="@layout/one_handed_header"
android:persistent="false"
android:selectable="false"
settings:allowDividerBelow="false"
settings:searchable="false"/>
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_one_hand_mode"/>
<com.android.settingslib.widget.MainSwitchPreference
android:key="gesture_one_handed_mode_enabled_main_switch"

View File

@@ -17,21 +17,21 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/ambient_display_pickup_title">
<com.android.settings.widget.VideoPreference
<com.android.settingslib.widget.IllustrationPreference
android:key="gesture_pick_up_video"
app:animation="@raw/gesture_ambient_lift"
app:preview="@drawable/gesture_ambient_lift"
app:controller="com.android.settings.widget.VideoPreferenceController" />
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_lift_to_check_phone"/>
<SwitchPreference
android:key="gesture_pick_up"
android:title="@string/ambient_display_pickup_title"
android:summary="@string/ambient_display_pickup_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.PickupGesturePreferenceController"
app:allowDividerAbove="true" />
app:controller="com.android.settings.gestures.PickupGesturePreferenceController" />
</PreferenceScreen>

View File

@@ -17,14 +17,14 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/gesture_prevent_ringing_screen_title">
<com.android.settings.widget.VideoPreference
<com.android.settingslib.widget.IllustrationPreference
android:key="gesture_prevent_ringing_video"
app:animation="@raw/gesture_prevent_ringing"
app:preview="@drawable/gesture_prevent_ringing"
app:controller="com.android.settings.widget.VideoPreferenceController" />
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_prevent_ringing"/>
<com.android.settingslib.widget.MainSwitchPreference
android:key="gesture_prevent_ringing_switch" />

View File

@@ -43,19 +43,19 @@
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_lockscreen" />
<Preference
<com.android.settingslib.RestrictedPreference
android:key="fingerprint_settings"
android:title="@string/security_settings_fingerprint_preference_title"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_fingerprint_settings" />
<Preference
<com.android.settingslib.RestrictedPreference
android:key="face_settings"
android:title="@string/security_settings_face_preference_title"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_face_settings" />
<Preference
<com.android.settingslib.RestrictedPreference
android:key="biometric_settings"
android:title="@string/security_settings_biometric_preference_title"
android:summary="@string/summary_placeholder"

View File

@@ -16,22 +16,21 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="gesture_swipe_down_fingerprint_screen"
android:title="@string/fingerprint_gesture_screen_title">
<com.android.settings.widget.VideoPreference
<com.android.settingslib.widget.IllustrationPreference
android:key="gesture_swipe_down_fingerprint_video"
app:animation="@raw/gesture_fingerprint_swipe"
app:preview="@drawable/gesture_fingerprint_swipe"
app:controller="com.android.settings.widget.VideoPreferenceController" />
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_swipe_fingerprint"/>
<SwitchPreference
android:key="gesture_swipe_down_fingerprint"
android:title="@string/fingerprint_swipe_for_notifications_title"
android:summary="@string/fingerprint_swipe_for_notifications_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.SwipeToNotificationPreferenceController"
app:allowDividerAbove="true" />
app:controller="com.android.settings.gestures.SwipeToNotificationPreferenceController" />
</PreferenceScreen>
</PreferenceScreen>

View File

@@ -17,21 +17,20 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/ambient_display_tap_screen_title">
<com.android.settings.widget.VideoPreference
<com.android.settingslib.widget.IllustrationPreference
android:key="gesture_tap_screen_video"
app:animation="@raw/gesture_ambient_tap_screen"
app:preview="@drawable/gesture_ambient_tap_screen"
app:controller="com.android.settings.widget.VideoPreferenceController" />
settings:searchable="false"
app:lottie_rawRes="@raw/lottie_tap_to_check_phone"/>
<SwitchPreference
android:key="gesture_tap"
android:title="@string/ambient_display_tap_screen_title"
android:summary="@string/ambient_display_tap_screen_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.TapScreenGesturePreferenceController"
app:allowDividerAbove="true" />
app:controller="com.android.settings.gestures.TapScreenGesturePreferenceController" />
</PreferenceScreen>

View File

@@ -309,11 +309,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
return controllers;
}
@Override
protected boolean isParalleledControllers() {
return true;
}
void addToCallbackList(Callback callback) {
if (callback != null) {
mCallbacks.add(callback);

View File

@@ -258,21 +258,6 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
}
private void setupForMultiBiometricEnroll() {
final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
final FaceManager faceManager = getSystemService(FaceManager.class);
final List<FingerprintSensorPropertiesInternal> fpProperties =
fingerprintManager.getSensorPropertiesInternal();
final List<FaceSensorPropertiesInternal> faceProperties =
faceManager.getSensorPropertiesInternal();
// This would need to be updated for devices with multiple sensors of the same modality
mIsFaceEnrollable = !faceProperties.isEmpty() &&
faceManager.getEnrolledFaces(mUserId).size()
< faceProperties.get(0).maxEnrollmentsPerUser;
mIsFingerprintEnrollable = !fpProperties.isEmpty() &&
fingerprintManager.getEnrolledFingerprints(mUserId).size()
< fpProperties.get(0).maxEnrollmentsPerUser;
if (!mConfirmingCredentials) {
mConfirmingCredentials = true;
if (!userHasPassword(mUserId)) {
@@ -284,7 +269,33 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
}
private void startMultiBiometricEnroll(Intent data) {
final boolean isSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
final FaceManager faceManager = getSystemService(FaceManager.class);
final List<FingerprintSensorPropertiesInternal> fpProperties =
fingerprintManager.getSensorPropertiesInternal();
final List<FaceSensorPropertiesInternal> faceProperties =
faceManager.getSensorPropertiesInternal();
mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data);
if (isSetupWizard) {
// This would need to be updated for devices with multiple sensors of the same modality
mIsFaceEnrollable = !faceProperties.isEmpty()
&& faceManager.getEnrolledFaces(mUserId).size() == 0;
mIsFingerprintEnrollable = !fpProperties.isEmpty()
&& fingerprintManager.getEnrolledFingerprints(mUserId).size() == 0;
} else {
// This would need to be updated for devices with multiple sensors of the same modality
mIsFaceEnrollable = !faceProperties.isEmpty()
&& faceManager.getEnrolledFaces(mUserId).size()
< faceProperties.get(0).maxEnrollmentsPerUser;
mIsFingerprintEnrollable = !fpProperties.isEmpty()
&& fingerprintManager.getEnrolledFingerprints(mUserId).size()
< fpProperties.get(0).maxEnrollmentsPerUser;
}
mMultiBiometricEnrollHelper = new MultiBiometricEnrollHelper(this, mUserId,
mIsFaceEnrollable, mIsFingerprintEnrollable, mGkPwHandle);
mMultiBiometricEnrollHelper.startNextStep();

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2021 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;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.ParentalControlsUtilsInternal;
import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.RestrictedLockUtils;
/**
* Utilities for things at the cross-section of biometrics and parental controls. For example,
* determining if parental consent is required, determining which strings should be shown, etc.
*/
public class ParentalControlsUtils {
private static final String TAG = "ParentalControlsUtils";
/**
* Public version that enables test paths, see
* {@link android.hardware.biometrics.ParentalControlsUtilsInternal#isTestModeEnabled(Context)}
* @return non-null EnforcedAdmin if parental consent is required
*/
public static RestrictedLockUtils.EnforcedAdmin parentConsentRequired(@NonNull Context context,
@BiometricAuthenticator.Modality int modality) {
final UserHandle userHandle = new UserHandle(UserHandle.myUserId());
if (ParentalControlsUtilsInternal.isTestModeEnabled(context)) {
Log.d(TAG, "Requiring consent for test flow");
return new RestrictedLockUtils.EnforcedAdmin(null /* ComponentName */, userHandle);
}
final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
return parentConsentRequiredInternal(dpm, modality, userHandle);
}
/**
* Internal testable version.
* @return non-null EnforcedAdmin if parental consent is required
*/
@Nullable
@VisibleForTesting
static RestrictedLockUtils.EnforcedAdmin parentConsentRequiredInternal(
@NonNull DevicePolicyManager dpm, @BiometricAuthenticator.Modality int modality,
@NonNull UserHandle userHandle) {
if (ParentalControlsUtilsInternal.parentConsentRequired(dpm, modality,
userHandle)) {
final ComponentName cn =
ParentalControlsUtilsInternal.getSupervisionComponentName(dpm, userHandle);
return new RestrictedLockUtils.EnforcedAdmin(cn, userHandle);
} else {
return null;
}
}
}

View File

@@ -16,15 +16,22 @@
package com.android.settings.biometrics.combination;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.ParentalControlsUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
/**
* Preference controller for biometrics settings page controlling the ability to unlock the phone
@@ -38,6 +45,8 @@ public class CombinedBiometricStatusPreferenceController extends
FingerprintManager mFingerprintManager;
@Nullable
FaceManager mFaceManager;
@VisibleForTesting
RestrictedPreference mPreference;
public CombinedBiometricStatusPreferenceController(Context context) {
this(context, KEY_BIOMETRIC_SETTINGS);
@@ -49,6 +58,12 @@ public class CombinedBiometricStatusPreferenceController extends
mFaceManager = Utils.getFaceManagerOrNull(context);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(KEY_BIOMETRIC_SETTINGS);
}
@Override
protected boolean isDeviceSupported() {
return Utils.hasFingerprintHardware(mContext) && Utils.hasFaceHardware(mContext);
@@ -59,6 +74,24 @@ public class CombinedBiometricStatusPreferenceController extends
return false;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
// This controller currently is shown if fingerprint&face exist on the device. If this
// changes in the future, the modalities passed into the below will need to be updated.
final RestrictedLockUtils.EnforcedAdmin admin = ParentalControlsUtils
.parentConsentRequired(mContext,
BiometricAuthenticator.TYPE_FACE | BiometricAuthenticator.TYPE_FINGERPRINT);
updateStateInternal(admin);
}
@VisibleForTesting
void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
if (enforcedAdmin != null && mPreference != null) {
mPreference.setDisabledByAdmin(enforcedAdmin);
}
}
@Override
protected String getSummaryTextEnrolled() {
// Note that this is currently never called (see the super class)

View File

@@ -17,18 +17,29 @@
package com.android.settings.biometrics.face;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.ParentalControlsUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
public class FaceStatusPreferenceController extends BiometricStatusPreferenceController {
public static final String KEY_FACE_SETTINGS = "face_settings";
protected final FaceManager mFaceManager;
@VisibleForTesting
RestrictedPreference mPreference;
public FaceStatusPreferenceController(Context context) {
this(context, KEY_FACE_SETTINGS);
@@ -39,6 +50,12 @@ public class FaceStatusPreferenceController extends BiometricStatusPreferenceCon
mFaceManager = Utils.getFaceManagerOrNull(context);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(KEY_FACE_SETTINGS);
}
@Override
protected boolean isDeviceSupported() {
return !Utils.isMultipleBiometricsSupported(mContext) && Utils.hasFaceHardware(mContext);
@@ -49,6 +66,21 @@ public class FaceStatusPreferenceController extends BiometricStatusPreferenceCon
return mFaceManager.hasEnrolledTemplates(getUserId());
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
final RestrictedLockUtils.EnforcedAdmin admin = ParentalControlsUtils
.parentConsentRequired(mContext, BiometricAuthenticator.TYPE_FACE);
updateStateInternal(admin);
}
@VisibleForTesting
void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
if (enforcedAdmin != null && mPreference != null) {
mPreference.setDisabledByAdmin(enforcedAdmin);
}
}
@Override
protected String getSummaryTextEnrolled() {
return mContext.getResources()

View File

@@ -17,17 +17,28 @@
package com.android.settings.biometrics.fingerprint;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.fingerprint.FingerprintManager;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.ParentalControlsUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
public class FingerprintStatusPreferenceController extends BiometricStatusPreferenceController {
private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings";
protected final FingerprintManager mFingerprintManager;
@VisibleForTesting
RestrictedPreference mPreference;
public FingerprintStatusPreferenceController(Context context) {
this(context, KEY_FINGERPRINT_SETTINGS);
@@ -38,6 +49,12 @@ public class FingerprintStatusPreferenceController extends BiometricStatusPrefer
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(KEY_FINGERPRINT_SETTINGS);
}
@Override
protected boolean isDeviceSupported() {
return !Utils.isMultipleBiometricsSupported(mContext)
@@ -49,6 +66,21 @@ public class FingerprintStatusPreferenceController extends BiometricStatusPrefer
return mFingerprintManager.hasEnrolledFingerprints(getUserId());
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
final RestrictedLockUtils.EnforcedAdmin admin = ParentalControlsUtils
.parentConsentRequired(mContext, BiometricAuthenticator.TYPE_FINGERPRINT);
updateStateInternal(admin);
}
@VisibleForTesting
void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
if (enforcedAdmin != null && mPreference != null) {
mPreference.setDisabledByAdmin(enforcedAdmin);
}
}
@Override
protected String getSummaryTextEnrolled() {
final int numEnrolled = mFingerprintManager.getEnrolledFingerprints(getUserId()).size();

View File

@@ -49,11 +49,6 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
return TAG;
}
@Override
protected boolean isParalleledControllers() {
return true;
}
@Override
public int getHelpResource() {
return R.string.help_url_connected_devices;

View File

@@ -22,7 +22,6 @@ import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.FeatureFlagUtils;
import android.util.Log;
import androidx.annotation.CallSuper;
@@ -36,7 +35,6 @@ import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.PreferenceControllerListHelper;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.overlay.FeatureFactory;
@@ -360,11 +358,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
* Update state of each preference managed by PreferenceController.
*/
protected void updatePreferenceStates() {
if (isParalleledControllers() && FeatureFlagUtils.isEnabled(getContext(),
FeatureFlags.CONTROLLER_ENHANCEMENT)) {
updatePreferenceStatesInParallel();
return;
}
final PreferenceScreen screen = getPreferenceScreen();
Collection<List<AbstractPreferenceController>> controllerLists =
mPreferenceControllers.values();
@@ -396,6 +389,8 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
* Use parallel method to update state of each preference managed by PreferenceController.
*/
@VisibleForTesting
// To use this parallel approach will cause the side effect of the UI flicker. Such as
// the thumb sliding of the toggle button.
void updatePreferenceStatesInParallel() {
final PreferenceScreen screen = getPreferenceScreen();
final Collection<List<AbstractPreferenceController>> controllerLists =

View File

@@ -402,11 +402,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
return mPreferenceControllers;
}
@Override
protected boolean isParalleledControllers() {
return true;
}
private void registerReceivers() {
LocalBroadcastManager.getInstance(getContext())
.registerReceiver(mEnableAdbReceiver, new IntentFilter(

View File

@@ -90,6 +90,7 @@ public class AdaptiveSleepPreferenceController {
if (enforcedAdmin != null) {
mPreference.setDisabledByAdmin(enforcedAdmin);
} else {
mPreference.setChecked(isChecked());
mPreference.setEnabled(hasSufficientPermission(mPackageManager) && !isCameraLocked()
&& !isPowerSaveMode());
}

View File

@@ -81,6 +81,7 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
@Override
public void onReceive(Context context, Intent intent) {
mAdaptiveSleepBatterySaverPreferenceController.updateVisibility();
mAdaptiveSleepController.updatePreference();
}
};

View File

@@ -55,7 +55,8 @@ public class BatterySaverScheduleSeekBarController implements
public BatterySaverScheduleSeekBarController(Context context) {
mContext = context;
mSeekBarPreference = new SeekBarPreference(context);
mSeekBarPreference.setLayoutResource(R.layout.battery_saver_schedule_percentage_seekbar);
mSeekBarPreference.setLayoutResource(R.layout.preference_widget_seekbar_settings);
mSeekBarPreference.setIconSpaceReserved(false);
mSeekBarPreference.setOnPreferenceChangeListener(this);
mSeekBarPreference.setContinuousUpdates(true);
mSeekBarPreference.setMax(MAX_SEEKBAR_VALUE);

View File

@@ -42,7 +42,10 @@ public abstract class GesturePreferenceController extends TogglePreferenceContro
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (isAvailable()) {
mVideoPreference = screen.findPreference(getVideoPrefKey());
final Preference pref = screen.findPreference(getVideoPrefKey());
if (pref instanceof VideoPreference) {
mVideoPreference = screen.findPreference(getVideoPrefKey());
}
}
}

View File

@@ -30,7 +30,6 @@ import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.VideoPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -52,8 +51,6 @@ public class PreventRingingGesturePreferenceController extends AbstractPreferenc
private final String KEY = "gesture_prevent_ringing_category";
private final Context mContext;
private VideoPreference mVideoPreference;
@VisibleForTesting
PreferenceCategory mPreferenceCategory;
@VisibleForTesting
@@ -85,8 +82,6 @@ public class PreventRingingGesturePreferenceController extends AbstractPreferenc
if (mPreferenceCategory != null) {
mSettingObserver = new SettingObserver(mPreferenceCategory);
}
mVideoPreference = screen.findPreference(getVideoPrefKey());
}
@Override
@@ -142,10 +137,6 @@ public class PreventRingingGesturePreferenceController extends AbstractPreferenc
mSettingObserver.register(mContext.getContentResolver());
mSettingObserver.onChange(false, null);
}
if (mVideoPreference != null) {
mVideoPreference.onViewVisible();
}
}
@Override
@@ -153,10 +144,6 @@ public class PreventRingingGesturePreferenceController extends AbstractPreferenc
if (mSettingObserver != null) {
mSettingObserver.unregister(mContext.getContentResolver());
}
if (mVideoPreference != null) {
mVideoPreference.onViewInvisible();
}
}
private int keyToSetting(String key) {

View File

@@ -95,11 +95,6 @@ public class NetworkDashboardFragment extends DashboardFragment implements
this /* fragment */, this /* mobilePlanHost */);
}
@Override
protected boolean isParalleledControllers() {
return true;
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle, MetricsFeatureProvider metricsFeatureProvider, Fragment fragment,
MobilePlanPreferenceHost mobilePlanHost) {

View File

@@ -54,6 +54,7 @@ import java.util.stream.Stream;
public class SubscriptionUtil {
private static final String TAG = "SubscriptionUtil";
private static final String PROFILE_GENERIC_DISPLAY_NAME = "CARD";
private static List<SubscriptionInfo> sAvailableResultsForTesting;
private static List<SubscriptionInfo> sActiveResultsForTesting;
@@ -257,7 +258,10 @@ public class SubscriptionUtil {
.map(i -> {
DisplayInfo info = new DisplayInfo();
info.subscriptionInfo = i;
info.originalName = i.getDisplayName().toString().trim();
String displayName = i.getDisplayName().toString();
info.originalName = TextUtils.equals(displayName, PROFILE_GENERIC_DISPLAY_NAME)
? context.getResources().getString(R.string.sim_card)
: displayName.trim();
return info;
});

View File

@@ -96,11 +96,6 @@ public class ConfigureNotificationSettings extends DashboardFragment implements
mNotificationAssistantPreferenceController.setBackend(new NotificationBackend());
}
@Override
protected boolean isParalleledControllers() {
return true;
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Application app, Fragment host) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();

View File

@@ -84,12 +84,13 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
}
if (TextUtils.equals(intent.getAction(), WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
showProgressBar();
updateProgressBar();
updatePanelTitle();
return;
}
if (TextUtils.equals(intent.getAction(), WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
updateProgressBar();
updatePanelTitle();
}
}
@@ -110,13 +111,40 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
private int mDefaultDataSubid = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
// Wi-Fi scanning progress bar
protected HandlerInjector mHandlerInjector;
protected boolean mIsProgressBarVisible;
protected final Runnable mHideProgressBarRunnable = () -> {
protected boolean mIsScanningSubTitleShownOnce;
protected Runnable mHideProgressBarRunnable = () -> {
setProgressBarVisible(false);
};
protected Runnable mHideScanningSubTitleRunnable = () -> {
mIsScanningSubTitleShownOnce = true;
updatePanelTitle();
};
/**
* Wrapper for testing compatibility.
*/
@VisibleForTesting
static class HandlerInjector {
protected final Handler mHandler;
HandlerInjector(Context context) {
mHandler = context.getMainThreadHandler();
}
public void postDelay(Runnable runnable) {
mHandler.postDelayed(runnable, 2000 /* delay millis */);
}
public void removeCallbacks(Runnable runnable) {
mHandler.removeCallbacks(runnable);
}
}
private InternetConnectivityPanel(Context context) {
mContext = context.getApplicationContext();
mHandlerInjector = new HandlerInjector(context);
mIsProviderModelEnabled = Utils.isProviderModelEnabled(mContext);
mInternetUpdater = new InternetUpdater(context, null /* Lifecycle */, this);
@@ -150,7 +178,7 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
mTelephonyManager.registerTelephonyCallback(
new HandlerExecutor(new Handler(Looper.getMainLooper())), mTelephonyCallback);
mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter);
showProgressBar();
updateProgressBar();
updatePanelTitle();
}
@@ -165,7 +193,8 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
mConnectivityListener.stop();
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
mContext.unregisterReceiver(mWifiStateReceiver);
mContext.getMainThreadHandler().removeCallbacks(mHideProgressBarRunnable);
mHandlerInjector.removeCallbacks(mHideProgressBarRunnable);
mHandlerInjector.removeCallbacks(mHideScanningSubTitleRunnable);
}
/**
@@ -246,6 +275,7 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
*/
@Override
public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
log("onAirplaneModeChanged: isAirplaneModeOn:" + isAirplaneModeOn);
updatePanelTitle();
}
@@ -254,6 +284,7 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
*/
@Override
public void onWifiEnabledChanged(boolean enabled) {
log("onWifiEnabledChanged: enabled:" + enabled);
updatePanelTitle();
}
@@ -305,13 +336,6 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
return;
}
if (mIsProgressBarVisible) {
// When the Wi-Fi scan result callback is received
// Sub-Title: Searching for networks...
mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
return;
}
if (mInternetUpdater.isAirplaneModeOn()) {
return;
}
@@ -319,11 +343,18 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
final List<ScanResult> wifiList = mWifiManager.getScanResults();
if (wifiList != null && wifiList.size() != 0) {
// When the Wi-Fi scan result is not empty
// Sub-Title: Select the network you want to use for data
// Sub-Title: Tap a network to connect
mSubtitle = SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT;
return;
}
if (!mIsScanningSubTitleShownOnce && mIsProgressBarVisible) {
// When the Wi-Fi scan result callback is received
// Sub-Title: Searching for networks...
mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
return;
}
// Sub-Title:
// show non_carrier_network_unavailable
// - while Wi-Fi on + no Wi-Fi item
@@ -353,7 +384,7 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
mSubtitle = SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE;
}
protected void showProgressBar() {
protected void updateProgressBar() {
if (mWifiManager == null || !mInternetUpdater.isWifiEnabled()) {
setProgressBarVisible(false);
return;
@@ -362,8 +393,9 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
setProgressBarVisible(true);
List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
if (wifiScanResults != null && wifiScanResults.size() > 0) {
mContext.getMainThreadHandler().postDelayed(mHideProgressBarRunnable,
2000 /* delay millis */);
mHandlerInjector.postDelay(mHideProgressBarRunnable);
} else if (!mIsScanningSubTitleShownOnce) {
mHandlerInjector.postDelay(mHideScanningSubTitleRunnable);
}
}

View File

@@ -82,15 +82,15 @@ public class SettingsMainSwitchPreference extends TwoStatePreference implements
holder.setDividerAllowedAbove(false);
holder.setDividerAllowedBelow(false);
mMainSwitchBar = (SettingsMainSwitchBar) holder.findViewById(R.id.main_switch_bar);
mMainSwitchBar.show();
if (mRestrictedHelper != null) {
mEnforcedAdmin = mRestrictedHelper.checkRestrictionEnforced();
}
updateStatus(isChecked());
registerListenerToSwitchBar();
if (!mIsVisible) {
mMainSwitchBar = (SettingsMainSwitchBar) holder.findViewById(R.id.main_switch_bar);
if (mIsVisible) {
mMainSwitchBar.show();
updateStatus(isChecked());
registerListenerToSwitchBar();
} else {
mMainSwitchBar.hide();
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2021 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.combination;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.UserManager;
import androidx.preference.Preference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
@RunWith(RobolectricTestRunner.class)
public class CombinedBiometricStatusPreferenceControllerTest {
@Mock
private LockPatternUtils mLockPatternUtils;
@Mock
private FingerprintManager mFingerprintManager;
@Mock
private FaceManager mFaceManager;
@Mock
private UserManager mUm;
@Mock
private PackageManager mPackageManager;
private FakeFeatureFactory mFeatureFactory;
private Context mContext;
private CombinedBiometricStatusPreferenceController mController;
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
ShadowApplication.getInstance().setSystemService(Context.FINGERPRINT_SERVICE,
mFingerprintManager);
ShadowApplication.getInstance().setSystemService(Context.FACE_SERVICE, mFaceManager);
ShadowApplication.getInstance().setSystemService(Context.USER_SERVICE, mUm);
mPreference = new Preference(mContext);
mFeatureFactory = FakeFeatureFactory.setupForTest();
when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
.thenReturn(mLockPatternUtils);
when(mUm.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {1234});
mController = new CombinedBiometricStatusPreferenceController(mContext);
}
@Test
public void updateState_parentalConsentRequired_preferenceDisabled() {
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
RestrictedPreference restrictedPreference = mock(RestrictedPreference.class);
RestrictedLockUtils.EnforcedAdmin admin = mock(RestrictedLockUtils.EnforcedAdmin.class);
mController.mPreference = restrictedPreference;
mController.updateStateInternal(admin);
verify(restrictedPreference).setDisabledByAdmin(eq(admin));
}
}

View File

@@ -22,8 +22,10 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -37,6 +39,8 @@ import androidx.preference.Preference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
import org.junit.Before;
import org.junit.Test;
@@ -129,4 +133,16 @@ public class FaceStatusPreferenceControllerTest {
.getString(R.string.security_settings_face_preference_summary));
assertThat(mPreference.isVisible()).isTrue();
}
@Test
public void updateState_parentalConsentRequired_preferenceDisabled() {
when(mFaceManager.isHardwareDetected()).thenReturn(true);
RestrictedPreference restrictedPreference = mock(RestrictedPreference.class);
RestrictedLockUtils.EnforcedAdmin admin = mock(RestrictedLockUtils.EnforcedAdmin.class);
mController.mPreference = restrictedPreference;
mController.updateStateInternal(admin);
verify(restrictedPreference).setDisabledByAdmin(eq(admin));
}
}

View File

@@ -22,8 +22,10 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -37,6 +39,8 @@ import androidx.preference.Preference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
import org.junit.Before;
import org.junit.Test;
@@ -130,4 +134,16 @@ public class FingerprintStatusPreferenceControllerTest {
R.plurals.security_settings_fingerprint_preference_summary, 1, 1));
assertThat(mPreference.isVisible()).isTrue();
}
@Test
public void updateState_parentalConsentRequired_preferenceDisabled() {
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
RestrictedPreference restrictedPreference = mock(RestrictedPreference.class);
RestrictedLockUtils.EnforcedAdmin admin = mock(RestrictedLockUtils.EnforcedAdmin.class);
mController.mPreference = restrictedPreference;
mController.updateStateInternal(admin);
verify(restrictedPreference).setDisabledByAdmin(eq(admin));
}
}

View File

@@ -37,7 +37,6 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ProviderInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.FeatureFlagUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
@@ -46,7 +45,6 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.slices.BlockingSlicePrefController;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -335,37 +333,6 @@ public class DashboardFragmentTest {
assertThat(pref).isInstanceOf(PrimarySwitchPreference.class);
}
@Test
public void isFeatureFlagAndIsParalleled_runParalleledUpdatePreferenceStates() {
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.CONTROLLER_ENHANCEMENT, true);
final TestFragment testFragment = spy(new TestFragment(RuntimeEnvironment.application));
testFragment.updatePreferenceStates();
verify(testFragment).updatePreferenceStatesInParallel();
}
@Test
public void notFeatureFlagAndIsParalleled_notRunParalleledUpdatePreferenceStates() {
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.CONTROLLER_ENHANCEMENT, false);
final TestFragment testFragment = spy(new TestFragment(RuntimeEnvironment.application));
testFragment.updatePreferenceStates();
verify(testFragment, never()).updatePreferenceStatesInParallel();
}
@Test
public void isFeatureFlagAndNotParalleled_notRunParalleledUpdatePreferenceStates() {
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.CONTROLLER_ENHANCEMENT, true);
final TestFragment testFragment = spy(new TestFragment(RuntimeEnvironment.application));
testFragment.setUsingControllerEnhancement(false);
testFragment.updatePreferenceStates();
verify(testFragment, never()).updatePreferenceStatesInParallel();
}
public static class TestPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin {

View File

@@ -145,9 +145,6 @@ public class EnterprisePrivacyFeatureProviderImplTest {
SpannableStringBuilder disclosure = new SpannableStringBuilder();
disclosure.append(mResources.getString(R.string.do_disclosure_generic));
disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
disclosure.append(mResources.getString(R.string.learn_more),
new EnterprisePrivacyFeatureProviderImpl.EnterprisePrivacySpan(mContext), 0);
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(mOwner);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null);
assertThat(mProvider.getDeviceOwnerDisclosure()).isEqualTo(disclosure);
@@ -155,9 +152,6 @@ public class EnterprisePrivacyFeatureProviderImplTest {
disclosure = new SpannableStringBuilder();
disclosure.append(mResources.getString(R.string.do_disclosure_with_name,
OWNER_ORGANIZATION));
disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
disclosure.append(mResources.getString(R.string.learn_more),
new EnterprisePrivacyFeatureProviderImpl.EnterprisePrivacySpan(mContext), 0);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(OWNER_ORGANIZATION);
assertThat(mProvider.getDeviceOwnerDisclosure()).isEqualTo(disclosure);
}

View File

@@ -24,6 +24,10 @@ import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,6 +43,7 @@ public class SettingsMainSwitchPreferenceTest {
@Mock
private EnforcedAdmin mEnforcedAdmin;
private SettingsMainSwitchPreference mPreference;
private PreferenceViewHolder mHolder;
@Before
public void setUp() {
@@ -48,6 +53,9 @@ public class SettingsMainSwitchPreferenceTest {
mPreference = new SettingsMainSwitchPreference(context);
ReflectionHelpers.setField(mPreference, "mEnforcedAdmin", mEnforcedAdmin);
ReflectionHelpers.setField(mPreference, "mMainSwitchBar", switchBar);
final View rootView = View.inflate(context, R.layout.preference_widget_main_switch,
null /* parent */);
mHolder = PreferenceViewHolder.createInstanceForTests(rootView);
}
@Test
@@ -60,4 +68,22 @@ public class SettingsMainSwitchPreferenceTest {
assertThat(restrictedIcon.getVisibility() == View.VISIBLE).isTrue();
}
@Test
public void show_preferenceShouldDisplay() {
mPreference.show();
mPreference.onBindViewHolder(mHolder);
assertThat(mPreference.isShowing()).isTrue();
}
@Test
public void hide_preferenceShouldNotDisplay() {
mPreference.hide();
mPreference.onBindViewHolder(mHolder);
assertThat(mPreference.isShowing()).isFalse();
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2021 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;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertNull;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
import android.hardware.biometrics.BiometricAuthenticator;
import android.os.UserHandle;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settingslib.RestrictedLockUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class ParentalControlsUtilsTest {
@Mock
private Context mContext;
@Mock
private DevicePolicyManager mDpm;
private ComponentName mSupervisionComponentName = new ComponentName("pkg", "cls");
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getContentResolver()).thenReturn(mock(ContentResolver.class));
}
/**
* Helper that sets the appropriate mocks and testing behavior before returning the actual
* EnforcedAdmin from ParentalControlsUtils.
*/
@Nullable
private RestrictedLockUtils.EnforcedAdmin getEnforcedAdminForCombination(
@Nullable ComponentName supervisionComponentName,
@BiometricAuthenticator.Modality int modality, int keyguardDisabledFlags) {
when(mDpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(any(UserHandle.class)))
.thenReturn(supervisionComponentName);
when(mDpm.getKeyguardDisabledFeatures(eq(supervisionComponentName)))
.thenReturn(keyguardDisabledFlags);
return ParentalControlsUtils.parentConsentRequiredInternal(mDpm, modality,
new UserHandle(UserHandle.myUserId()));
}
@Test
public void testEnforcedAdmin_whenDpmDisablesBiometricsAndSupervisionComponentExists() {
int[][] tests = {
{TYPE_FINGERPRINT, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT},
{TYPE_FACE, DevicePolicyManager.KEYGUARD_DISABLE_FACE},
{TYPE_IRIS, DevicePolicyManager.KEYGUARD_DISABLE_IRIS},
};
for (int i = 0; i < tests.length; i++) {
RestrictedLockUtils.EnforcedAdmin admin = getEnforcedAdminForCombination(
mSupervisionComponentName, tests[i][0] /* modality */,
tests[i][1] /* keyguardDisableFlags */);
assertNotNull(admin);
assertEquals(mSupervisionComponentName, admin.component);
}
}
@Test
public void testNoEnforcedAdmin_whenNoSupervisionComponent() {
// Even if DPM flag exists, returns null EnforcedAdmin when no supervision component exists
RestrictedLockUtils.EnforcedAdmin admin = getEnforcedAdminForCombination(
null /* supervisionComponentName */, TYPE_FINGERPRINT,
DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
assertNull(admin);
}
}

View File

@@ -18,8 +18,6 @@ package com.android.settings.panel;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -95,11 +93,31 @@ public class InternetConnectivityPanelTest {
private FragmentActivity mPanelActivity;
private Context mContext;
private FakeHandlerInjector mFakeHandlerInjector;
private InternetConnectivityPanel mPanel;
private class FakeHandlerInjector extends InternetConnectivityPanel.HandlerInjector {
private Runnable mRunnable;
FakeHandlerInjector(Context context) {
super(context);
}
@Override
public void postDelay(Runnable runnable) {
mRunnable = runnable;
}
public Runnable getRunnable() {
return mRunnable;
}
}
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
mFakeHandlerInjector = new FakeHandlerInjector(mContext);
when(mContext.getApplicationContext()).thenReturn(mContext);
when(mContext.getMainThreadHandler()).thenReturn(mMainThreadHandler);
when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
@@ -109,6 +127,7 @@ public class InternetConnectivityPanelTest {
mPanel.mIsProviderModelEnabled = true;
mPanel.mInternetUpdater = mInternetUpdater;
mPanel.mProviderModelSliceHelper = mProviderModelSliceHelper;
mPanel.mHandlerInjector = mFakeHandlerInjector;
}
@Test
@@ -295,36 +314,41 @@ public class InternetConnectivityPanelTest {
}
@Test
public void showProgressBar_wifiDisabled_hideProgress() {
public void updateProgressBar_wifiDisabled_hideProgress() {
mPanel.mIsProgressBarVisible = true;
doReturn(false).when(mInternetUpdater).isWifiEnabled();
clearInvocations(mPanelContentCallback);
mPanel.showProgressBar();
mPanel.updateProgressBar();
assertThat(mPanel.isProgressBarVisible()).isFalse();
verify(mPanelContentCallback).onProgressBarVisibleChanged();
}
@Test
public void showProgressBar_noWifiScanResults_showProgressForever() {
public void updateProgressBar_noWifiScanResults_showProgressForever() {
mPanel.mIsScanningSubTitleShownOnce = false;
mPanel.mIsProgressBarVisible = false;
doReturn(true).when(mInternetUpdater).isWifiEnabled();
List<ScanResult> noWifiScanResults = new ArrayList<>();
doReturn(noWifiScanResults).when(mWifiManager).getScanResults();
clearInvocations(mPanelContentCallback);
mPanel.showProgressBar();
mPanel.updateProgressBar();
assertThat(mPanel.isProgressBarVisible()).isTrue();
assertThat(mPanel.mIsProgressBarVisible).isTrue();
verify(mPanelContentCallback).onProgressBarVisibleChanged();
verify(mPanelContentCallback).onHeaderChanged();
verify(mMainThreadHandler, never())
.postDelayed(any() /* mHideProgressBarRunnable */, anyLong());
assertThat(mFakeHandlerInjector.getRunnable())
.isEqualTo(mPanel.mHideScanningSubTitleRunnable);
mFakeHandlerInjector.getRunnable().run();
assertThat(mPanel.mIsScanningSubTitleShownOnce).isTrue();
assertThat(mPanel.mIsProgressBarVisible).isTrue();
}
@Test
public void showProgressBar_hasWifiScanResults_showProgressDelayedHide() {
public void updateProgressBar_hasWifiScanResults_showProgressDelayedHide() {
mPanel.mIsProgressBarVisible = false;
doReturn(true).when(mInternetUpdater).isWifiEnabled();
List<ScanResult> hasWifiScanResults = mock(ArrayList.class);
@@ -332,11 +356,15 @@ public class InternetConnectivityPanelTest {
doReturn(hasWifiScanResults).when(mWifiManager).getScanResults();
clearInvocations(mPanelContentCallback);
mPanel.showProgressBar();
mPanel.updateProgressBar();
assertThat(mPanel.isProgressBarVisible()).isTrue();
verify(mPanelContentCallback).onProgressBarVisibleChanged();
verify(mMainThreadHandler).postDelayed(any() /* mHideProgressBarRunnable */, anyLong());
assertThat(mFakeHandlerInjector.getRunnable())
.isEqualTo(mPanel.mHideProgressBarRunnable);
mFakeHandlerInjector.getRunnable().run();
assertThat(mPanel.mIsProgressBarVisible).isFalse();
}
@Test