Merge "Fix background inconsistency of the font size page in SUW" into sc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c352694..9b11fe8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -494,6 +494,22 @@
android:value="com.android.settings.biometrics.fingerprint.FingerprintSettings$FingerprintSettingsFragment" />
</activity>
+ <activity android:name="Settings$CombinedBiometricSettingsActivity"
+ android:label="@string/security_settings_biometric_preference_title"
+ android:theme="@style/Theme.SubSettings"
+ android:exported="false">
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.biometrics.combination.CombinedBiometricSettings" />
+ </activity>
+
+ <activity android:name="Settings$CombinedBiometricProfileSettingsActivity"
+ android:label="@string/security_settings_biometric_preference_title"
+ android:theme="@style/Theme.SubSettings"
+ android:exported="false">
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.biometrics.combination.CombinedBiometricProfileSettings" />
+ </activity>
+
<activity android:name=".bluetooth.DevicePickerActivity"
android:label="@string/device_picker"
android:configChanges="orientation|keyboardHidden|screenSize"
diff --git a/res/drawable/baseline_near_me.xml b/res/drawable/baseline_near_me.xml
deleted file mode 100644
index 343f970..0000000
--- a/res/drawable/baseline_near_me.xml
+++ /dev/null
@@ -1,23 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24"
- android:tint="?attr/colorControlNormal">
- <path
- android:fillColor="@android:color/black"
- android:pathData="M21,3L3,10.53v0.98l6.84,2.65L12.48,21h0.98L21,3z"/>
-</vector>
diff --git a/res/layout/apps_filter_spinner.xml b/res/layout/apps_filter_spinner.xml
index 13d8078..1de5705 100644
--- a/res/layout/apps_filter_spinner.xml
+++ b/res/layout/apps_filter_spinner.xml
@@ -36,7 +36,7 @@
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="12dp"
- android:layout_toRightOf="@id/filter_spinner"
+ android:layout_toEndOf="@id/filter_spinner"
android:contentDescription="@string/configure"
android:scaleType="center"
android:src="@drawable/ic_apps_filter_settings_24dp"
diff --git a/res/layout/notification_history.xml b/res/layout/notification_history.xml
index fdcecb3..0b0e1d5 100644
--- a/res/layout/notification_history.xml
+++ b/res/layout/notification_history.xml
@@ -146,7 +146,6 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/notification_list"
- android:elevation="1dp"
android:background="@drawable/rounded_bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -170,7 +169,6 @@
android:paddingBottom="16dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/notification_list"
- android:elevation="1dp"
android:background="@drawable/rounded_bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -194,7 +192,6 @@
android:id="@+id/apps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:elevation="1dp"
android:orientation="vertical"
android:background="@drawable/rounded_bg">
<!-- app based recycler views added here -->
diff --git a/res/layout/notification_history_app_layout.xml b/res/layout/notification_history_app_layout.xml
index 78f2ef4..7c6e5a3 100644
--- a/res/layout/notification_history_app_layout.xml
+++ b/res/layout/notification_history_app_layout.xml
@@ -26,9 +26,9 @@
android:layout_width="match_parent"
android:clipChildren="true"
android:background="@drawable/button_ripple_radius"
- android:paddingTop="24dp"
+ android:paddingTop="20dp"
android:orientation="horizontal"
- android:paddingBottom="22dp"
+ android:paddingBottom="18dp"
android:paddingStart="16dp">
<ImageView
android:id="@+id/icon"
@@ -50,7 +50,7 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification"/>
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"/>
<TextView
android:id="@+id/count"
android:layout_height="wrap_content"
@@ -58,7 +58,7 @@
android:layout_gravity="start|center_vertical"
android:textDirection="locale"
android:paddingTop="4dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"/>
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification"/>
</LinearLayout>
<include layout="@*android:layout/notification_expand_button"
diff --git a/res/layout/settings_collapsing_base_layout.xml b/res/layout/settings_collapsing_base_layout.xml
deleted file mode 100644
index 97d249c..0000000
--- a/res/layout/settings_collapsing_base_layout.xml
+++ /dev/null
@@ -1,68 +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.
--->
-<androidx.coordinatorlayout.widget.CoordinatorLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/content_parent"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
-
- <com.google.android.material.appbar.AppBarLayout
- android:id="@+id/app_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:fitsSystemWindows="true"
- android:outlineAmbientShadowColor="@android:color/transparent"
- android:outlineSpotShadowColor="@android:color/transparent"
- android:background="@android:color/transparent"
- android:theme="@style/Theme.CollapsingToolbar.Settings">
-
- <com.google.android.material.appbar.CollapsingToolbarLayout
- android:id="@+id/collapsing_toolbar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/toolbar_one_line_height"
- android:clipToPadding="false"
- app:contentScrim="@color/color_surface_header"
- app:maxLines="3"
- app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
- app:scrimAnimationDuration="50"
- app:scrimVisibleHeightTrigger="@dimen/scrim_visible_height_trigger"
- app:statusBarScrim="@empty"
- app:titleCollapseMode="fade"
- app:collapsedTitleTextAppearance="@style/ToolbarText.Collapsed"
- app:expandedTitleTextAppearance="@style/ToolbarText.Expanded"
- app:expandedTitleMarginStart="@dimen/expanded_title_margin_start"
- app:expandedTitleMarginEnd="@dimen/expanded_title_margin_end"
- app:toolbarId="@id/action_bar">
-
- <Toolbar
- android:id="@+id/action_bar"
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:theme="?android:attr/actionBarTheme"
- app:layout_collapseMode="pin"/>
-
- </com.google.android.material.appbar.CollapsingToolbarLayout>
- </com.google.android.material.appbar.AppBarLayout>
-
- <FrameLayout
- android:id="@+id/content_frame"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index a41e41b..b2323c2 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -530,4 +530,24 @@
<!-- Whether to show Smart Storage toggle -->
<bool name="config_show_smart_storage_toggle">true</bool>
+
+ <!-- Display settings screen, Color mode options. Must be the same length and order as
+ config_color_mode_options_values below. Only the values that also appear in
+ frameworks/base/core/res/res/values/config.xml's config_availableColorModes are shown. -->
+ <string-array name="config_color_mode_options_strings" translatable="false">
+ <item>@string/color_mode_option_natural</item>
+ <item>@string/color_mode_option_boosted</item>
+ <item>@string/color_mode_option_saturated</item>
+ <item>@string/color_mode_option_automatic</item>
+ </string-array>
+
+ <!-- Display settings screen, Color mode options. Must be the same length and order as
+ config_color_mode_options_strings above. Only the values that also appear in
+ frameworks/base/core/res/res/values/config.xml's config_availableColorModes are shown. -->
+ <integer-array name="config_color_mode_options_values" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </integer-array>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6047092..0aaf930 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -443,15 +443,7 @@
<!-- Battery usage chart view component -->
<dimen name="chartview_divider_width">1dp</dimen>
<dimen name="chartview_divider_height">4dp</dimen>
- <dimen name="chartview_trapezoid_radius">2dp</dimen>
+ <dimen name="chartview_trapezoid_radius">3dp</dimen>
<dimen name="chartview_trapezoid_margin_start">1dp</dimen>
<dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
-
- <!-- Collapsing toolbar layout dimensions -->
- <dimen name="toolbar_one_line_height">226dp</dimen>
- <dimen name="toolbar_two_lines_height">270dp</dimen>
- <dimen name="toolbar_three_lines_height">314dp</dimen>
- <dimen name="scrim_visible_height_trigger">174dp</dimen>
- <dimen name="expanded_title_margin_start">24dp</dimen>
- <dimen name="expanded_title_margin_end">24dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1ca471f..ef5abb3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -739,6 +739,8 @@
<string name="security_dashboard_summary">Screen lock, fingerprint</string>
<!-- Summary for Security settings when fingerprint is not supported [CHAR LIMIT=NONE]-->
<string name="security_dashboard_summary_no_fingerprint">Screen lock</string>
+ <!-- Summary for Security settings when biometric unlock is supported [CHAR LIMIT=NONE] -->
+ <string name="security_dashboard_summary_biometric">Screen lock, biometric unlock, app security</string>
<!-- Face enrollment and settings --><skip />
<!-- Message shown in summary field when face unlock is set up. [CHAR LIMIT=40] -->
@@ -967,6 +969,22 @@
<!-- Message shown in fingerprint security settings home screen. [CHAR LIMIT=NONE]-->
<string name="security_settings_fingerprint_v2_home_screen">Use your fingerprint to unlock your phone or for authentication, like when you sign in to apps or approve a purchase\n\n<annotation id="url">Learn more</annotation></string>
+ <!-- Biometric settings --><skip />
+ <!-- Title shown for menu item that launches biometric settings. [CHAR LIMIT=66] -->
+ <string name="security_settings_biometric_preference_title">Face & fingerprint unlock</string>
+ <!-- Message shown in summary field of biometric settings. [CHAR LIMIT=66] -->
+ <string name="security_settings_biometric_preference_summary">Face and fingerprint</string>
+ <!-- Introduction shown in face and fingerprint page to introduce the biometric feature. [CHAR LIMIT=NONE]-->
+ <string name="biometric_settings_intro">When you set up face unlock and fingerprint, your phone will ask for your fingerprint when you wear a mask or are in a dark area.</string>
+ <!-- Biometric category title - biometric options for unlocking the device. [CHAR LIMIT=50] -->
+ <string name="biometric_settings_category_ways_to_unlock">Ways to unlock</string>
+ <!-- Biometric category title - configuration options for using biometric to unlock the device or authenticate in apps. [CHAR LIMIT=50] -->
+ <string name="biometric_settings_category_ways_to_use">Use face and fingerprint to</string>
+ <!-- Text shown on a toggle which allows or disallows the device to use biometric for unlocking the device. [CHAR LIMIT=20] -->
+ <string name="biometric_settings_use_biometric_unlock_phone">Unlocking your phone</string>
+ <!-- Text shown on a toggle which allows or disallows the device to use biometric for authentication. [CHAR LIMIT=30] -->
+ <string name="biometric_settings_use_biometric_for_apps">Authentication in apps</string>
+
<!-- Title of dialog shown when the user tries to skip setting up a screen lock, warning them of potential consequences of not doing so [CHAR LIMIT=30]-->
<string name="lock_screen_intro_skip_title">Skip screen lock?</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning them of potential consequences of not doing so, including loss of factory reset protection. (tablet) [CHAR LIMIT=NONE] -->
@@ -4121,7 +4139,7 @@
<!-- Description text for Bluetooth always scanning -->
<string name="location_scanning_bluetooth_always_scanning_description">Allow apps and services to scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services.</string>
<!-- [CHAR LIMIT=60] Location Services preference title -->
- <string name="location_services_preference_title">Manage location services</string>
+ <string name="location_services_preference_title">Location services</string>
<!-- [CHAR LIMIT=60] Location Services screen, screen title -->
<string name="location_services_screen_title">Location Services</string>
<!-- [CHAR LIMIT=50] Location settings screen, sub category for location services for managed profile -->
@@ -5691,15 +5709,54 @@
<!-- Title for the prompt shown as a placeholder if no accessibility services are installed. [CHAR LIMIT=50] -->
<string name="accessibility_no_services_installed">No services installed</string>
- <!-- Title for the acccessibility shortcut's summary if no service is selected for use with the shortcut. [CHAR LIMIT=50] -->
+ <!-- Title for the accessibility shortcut's summary if no service is selected for use with the shortcut. [CHAR LIMIT=50] -->
<string name="accessibility_no_service_selected">No service selected</string>
<!-- Default description for an accessibility service if the latter doesn't provide one. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_default_description">No description provided.</string>
- <!-- Accessibility settings: button for lauching settings for an accessibility service -->
+ <!-- Accessibility settings: button for launching settings for an accessibility service -->
<string name="settings_button">Settings</string>
+ <!-- List of synonyms used in the settings search bar to find the “Extra Dim” setting, which dims your screen. Title name is located at strings/reduce_bright_colors_preference_title. [CHAR LIMIT=NONE] -->
+ <string name="keywords_reduce_bright_colors">light sensitivity, photophobia, dark theme, migraine, headache, reading mode, night mode, reduce brightness, white point</string>
+ <!-- List of synonyms used in the settings search bar to find the “Accessibility”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_accessibility">Ease of use, ease of access, assistance, assistive</string>
+ <!-- List of synonyms used in the settings search bar to find the “Magnification”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_magnification">Window Magnifier, Zoom, Magnification, Low vision, Enlarge, make bigger</string>
+ <!-- List of synonyms used in the settings search bar to find the “TalkBack”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_talkback">Screen reader, Voice Over, VoiceOver, Voice Assistance, Blind, Low Vision, TTS, text to speech, spoken feedback</string>
+ <!-- List of synonyms used in the settings search bar to find the “Live Caption”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_live_caption">Captions, closed captions, CC, Live Transcribe, hard of hearing, hearing loss, CART, speech to text, subtitle</string>
+ <!-- List of synonyms used in the settings search bar to find the “Live Transcribe”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_live_transcribe">Captions, closed captions, CC, Live Caption, hard of hearing, hearing loss, CART, speech to text, subtitle</string>
+ <!-- List of synonyms used in the settings search bar to find the “Sound Notifications”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_sound_notifications">Notifications, hard of hearing, hearing loss, notify</string>
+ <!-- List of synonyms used in the settings search bar to find the “Sound Amplifier”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_sound_amplifier">PSAP, amplify, sound amplification, hard of hearing, hearing loss, amplification</string>
+ <!-- List of synonyms used in the settings search bar to find the “Display size”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_display_size">screen size, large screen</string>
+ <!-- List of synonyms used in the settings search bar to find the “Bold text”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_bold_text">High contrast, low vision, bold font, bold face</string>
+ <!-- List of synonyms used in the settings search bar to find the “Select to Speak”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_select_to_speak">Hear text, read aloud, speak screen, screen reader</string>
+ <!-- List of synonyms used in the settings search bar to find the “Color correction”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_color_correction">adjust color </string>
+ <!-- List of synonyms used in the settings search bar to find the “Color inversion”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_color_inversion">turn screen dark, turn screen light</string>
+ <!-- List of synonyms used in the settings search bar to find the “Accessibility Menu”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_accessibility_menu">motor, quick menu, assistive menu, touch, dexterity</string>
+ <!-- List of synonyms used in the settings search bar to find the “Switch Access”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_switch_access">motor, switch, hand, AT, assistive technology, paralysis, ALS, scanning, step scanning</string>
+ <!-- List of synonyms used in the settings search bar to find the “Autoclick(dwell timing)”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_auto_click">motor, mouse</string>
+ <!-- List of synonyms used in the settings search bar to find the “Hearing aids”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_hearing_aids">hard of hearing, hearing loss</string>
+ <!-- List of synonyms used in the settings search bar to find the “Real-time text (RTT)”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_rtt">hard of hearing, hearing loss, captions, Teletype, tty</string>
+ <!-- List of synonyms used in the settings search bar to find the “Voice Access”. [CHAR LIMIT=NONE] -->
+ <string name="keywords_voice_access">voice, voice control, motor, hand, mic, microphone, dictation, talk, control</string>
+
<!-- Printing settings -->
<skip />
@@ -6255,8 +6312,39 @@
<string name ="battery_detail_info_title">Since full charge</string>
<!-- Title for the battery management group [CHAR LIMIT=40] -->
<string name ="battery_detail_manage_title">Manage battery usage</string>
+
<!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background for past 24 hr. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_and_background_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background for past 24 hr</string>
+ <!-- Description for battery total and background usage time in a time period for an app, i.e. 1 hr 15 min total • 39 min background for 12 am-2 am. Note: ^1, ^2 and ^3 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_and_background_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^3</xliff:g></string>
+
+ <!-- Description for battery total usage time is less than a minute for an app [CHAR LIMIT=120] -->
+ <string name="battery_total_usage_less_minute">Total less than a minute for past 24 hr</string>
+ <!-- Description for battery total usage time is less than a minute in a time period for an app, i.e. Total less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
+ <string name="battery_total_usage_less_minute_with_period">Total less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
+
+ <!-- Description for battery background usage time is less than a minute for an app [CHAR LIMIT=120] -->
+ <string name="battery_background_usage_less_minute">Background less than a minute for past 24 hr</string>
+ <!-- Description for battery background usage time is less than a minute in a time period for an app, i.e. Background less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
+ <string name="battery_background_usage_less_minute_with_period">Background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
+
+ <!-- Description for battery total usage time for an app, i.e. 1 hr 15 min total for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for past 24 hr</string>
+ <!-- Description for battery total usage time in a time period for an app, i.e. 1 hr 15 min total for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+
+ <!-- Description for battery background usage time for an app, i.e. 1 hr 15 min background for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_background_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for past 24 hr</string>
+ <!-- Description for battery background usage time in a time period for an app, i.e. 1 hr 15 min background for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_background_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+
+ <!-- Description for battery total usage with background usage time less than a minute for an app, i.e. 1 hr 15 min total • background less than a minute for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_usage_and_background_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute for past 24 hr</string>
+ <!-- Description for battery total usage with background usage time less than a minute in a time period for an app, i.e. 1 hr 15 min total • background less than a minute for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_usage_and_background_less_minute_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+
+ <!-- Description for no any battery usage for past 24 hr [CHAR LIMIT=120] -->
+ <string name="battery_not_usage">No usage for past 24 hr</string>
<!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
<string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
@@ -7950,7 +8038,7 @@
<string name="keywords_wifi_calling">wifi, wi-fi, call, calling</string>
<string name="keywords_display">screen, touchscreen</string>
<string name="keywords_display_brightness_level">dim screen, touchscreen, battery, bright</string>
- <string name="keywords_display_night_display">dim screen, night, tint, night shift, brightness, screen color, colour, color</string>
+ <string name="keywords_display_night_display">dim screen, night, tint, night shift, brightness, screen color, colour, color, light sensitivity, photophobia, make darker, darken, dark mode, migraine</string>
<string name="keywords_display_wallpaper">background, personalize, customize display</string>
<string name="keywords_display_font_size">text size</string>
<!-- Search keyword for "Cast" settings [CHAR_LIMIT=NONE]-->
@@ -7990,6 +8078,7 @@
<string name="keywords_backup">backup, back up</string>
<string name="keywords_assist_gesture_launch">gesture</string>
<string name="keywords_face_unlock">face, unlock, auth, sign in</string>
+ <string name="keywords_biometric_unlock">face, unlock, auth, sign in, fingerprint, biometric</string>
<string name="keywords_imei_info">imei, meid, min, prl version, imei sv</string>
<string name="keywords_sim_status">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid, eid</string>
<string name="keywords_model_and_hardware">serial number, hardware version</string>
@@ -8015,6 +8104,9 @@
<!-- Search keyword for fingerprint settings. [CHAR_LIMIT=NONE]-->
<string name="keywords_fingerprint_settings">fingerprint, add fingerprint</string>
+ <!-- Search keyword for biometric settings. [CHAR_LIMIT=NONE]-->
+ <string name="keywords_biometric_settings">face, fingerprint, add fingerprint</string>
+
<!-- Search keywords for adaptive brightness setting [CHAR LIMIT=NONE]-->
<string name="keywords_display_auto_brightness">dim screen, touchscreen, battery, smart brightness, dynamic brightness, Auto brightness</string>
@@ -8076,10 +8168,7 @@
<string name="keywords_add_language">add language, add a language</string>
<!-- List of synonyms for the font size, used to match in settings search [CHAR LIMIT=NONE] -->
- <string name="keywords_font_size">text size</string>
-
- <!-- List of synonyms used in the settings search bar to find the “Extra Dim” setting, which dims your screen. Title name is located at strings/reduce_bright_colors_preference_title. [CHAR LIMIT=NONE] -->
- <string name="keywords_reduce_bright_colors">light sensitivity, photophobia, dark theme, migraine, headache, reading mode, night mode, reduce brightness, white point</string>
+ <string name="keywords_font_size">text size, large print, large font, large text, low vision, make text bigger, font enlarger, font enlargement</string>
<!-- Option title for the default sound, context based on screen -->
<string name="default_sound">Default sound</string>
@@ -9056,6 +9145,10 @@
<string name="notif_type_alerting_summary">Notifications that may ring or vibrate based on settings</string>
<string name="notif_type_silent">Silent</string>
<string name="notif_type_silent_summary">Notifications that never make sound or vibrations</string>
+ <!-- category header for apps allowed to read notifications. [CHAR LIMIT=45] -->
+ <string name="notification_listener_allowed">Allowed</string>
+ <!-- category header for apps not allowed to read notifications. [CHAR LIMIT=45] -->
+ <string name="notification_listener_not_allowed">Not allowed</string>
<!-- Per notification listener, a list of apps whose notifications this listener cannot see -->
<string name="notif_listener_excluded_app_title">See all apps</string>
@@ -13183,4 +13276,13 @@
<!-- Label for button to not allow grant the permission for remote devices. [CHAR_LIMIT=50] -->
<string name="request_manage_bluetooth_permission_dont_allow">Don\u2019t allow</string>
+
+ <!-- Title for UWB preference [CHAR_LIMIT=60] -->
+ <string name="uwb_settings_title">Ultra-WideBand (UWB)</string>
+
+ <!-- Summary for UWB preference. [CHAR_LIMIT=NONE]-->
+ <string name="uwb_settings_summary">Helps identify the relative position of nearby devices that have UWB</string>
+
+ <!-- Summary for UWB preference when airplane mode is disabled. [CHAR_LIMIT=NONE]-->
+ <string name="uwb_settings_summary_airplane_mode">Turn off Airplane mode to use UWB. </string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index e91ddcb..b27cc5d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -787,7 +787,7 @@
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
</style>
- <style name="HomepageTitleText" parent="ToolbarText.Expanded">
+ <style name="HomepageTitleText" parent="CollapsingToolbarTitle.Expanded">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">@dimen/homepage_title_margin_bottom</item>
@@ -879,8 +879,4 @@
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
-
- <style name="ToolbarText.Collapsed" parent="CollapsingToolbarTitle.Collapsed"/>
- <style name="ToolbarText.Expanded" parent="CollapsingToolbarTitle"/>
- <style name="ToolbarText.MoreThanTwoLines" parent="CollapsingToolbarTitle.MoreThanTwoLines"/>
</resources>
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index c162fc4..5ad553a 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -30,7 +30,6 @@
<style name="PreferenceTheme.SetupWizard" parent="@style/SettingsPreferenceTheme">
<item name="preferenceFragmentCompatStyle">@style/SetupWizardPreferenceFragmentStyle</item>
- <item name="preferenceStyle">@style/Preference.Material</item>
</style>
<style name="ApnPreference" parent="@style/Preference.Material">
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 5142d55..b5f71fa 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -258,5 +258,7 @@
<style name="Theme.NotificationHistory" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index ce3f4a2..6fa8b00 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -50,7 +50,8 @@
android:icon="@drawable/ic_reduce_bright_colors"
android:persistent="false"
android:title="@string/reduce_bright_colors_preference_title"
- settings:controller="com.android.settings.accessibility.ReduceBrightColorsPreferenceController"/>
+ settings:controller="com.android.settings.accessibility.ReduceBrightColorsPreferenceController"
+ settings:keywords="@string/keywords_reduce_bright_colors"/>
<SwitchPreference
android:key="dark_ui_mode_accessibility"
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index a801ae1..edf8cb9 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -26,7 +26,7 @@
<com.android.settings.widget.SettingsMainSwitchPreference
android:key="block" />
- <com.android.settings.notification.app.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="block_desc" />
@@ -96,11 +96,11 @@
</PreferenceCategory>
- <com.android.settings.notification.app.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="desc"
android:order="5000" />
- <com.android.settings.notification.app.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="deleted"
android:order="8000" />
diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml
index 95f7944..97dcc26 100644
--- a/res/xml/channel_notification_settings.xml
+++ b/res/xml/channel_notification_settings.xml
@@ -116,11 +116,11 @@
android:title="@string/app_settings_link"
settings:allowDividerAbove="true"/>
- <com.android.settings.notification.app.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="desc"
android:order="100"/>
- <com.android.settings.notification.app.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="block_desc"
android:order="110"
settings:allowDividerAbove="false"/>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 3ff7d99..85e4a76 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -65,6 +65,13 @@
android:icon="@drawable/ic_folder_vd_theme_24"
android:title="@string/bluetooth_show_files_received_via_bluetooth"/>
+ <SwitchPreference
+ android:key="uwb_settings"
+ android:title="@string/uwb_settings_title"
+ android:order="100"
+ android:summary="@string/summary_placeholder"
+ settings:controller="com.android.settings.uwb.UwbPreferenceController"/>
+
<PreferenceCategory
android:key="dashboard_tile_placeholder"
android:order="-8"/>
diff --git a/res/xml/conversation_notification_settings.xml b/res/xml/conversation_notification_settings.xml
index ea555c2..7e475be 100644
--- a/res/xml/conversation_notification_settings.xml
+++ b/res/xml/conversation_notification_settings.xml
@@ -58,7 +58,7 @@
android:summary="@string/demote_conversation_summary"
settings:allowDividerAbove="true"/>
- <com.android.settings.notification.app.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="block_desc"
settings:allowDividerAbove="false"/>
diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml
index 6fc0b25..47056df 100644
--- a/res/xml/date_time_prefs.xml
+++ b/res/xml/date_time_prefs.xml
@@ -53,11 +53,10 @@
settings:keywords="@string/keywords_time_zone"/>
<!-- This preference gets removed if location-based time zone detection is not supported -->
- <com.android.settingslib.RestrictedSwitchPreference
+ <SwitchPreference
android:key="location_time_zone_detection"
android:title="@string/location_time_zone_detection_toggle_title"
settings:controller="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceController"
- settings:userRestriction="no_config_date_time"
/>
<PreferenceCategory
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index cae128b..a950b3a 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -27,14 +27,6 @@
settings:controller=
"com.android.settings.location.RecentLocationAccessPreferenceController"/>
- <Preference
- android:key="recent_location_access_see_all_button"
- android:title="@string/location_recent_location_access_see_all"
- android:icon="@drawable/ic_chevron_right_24dp"
- android:fragment="com.android.settings.location.RecentLocationAccessSeeAllFragment"
- settings:controller="com.android.settings.location.RecentLocationAccessSeeAllButtonPreferenceController"
- settings:searchable="false"/>
-
<PreferenceCategory
android:key="location_advanced_settings"
android:layout="@layout/preference_category_no_label"
@@ -65,7 +57,7 @@
<Preference
android:fragment="com.android.settings.location.LocationServices"
android:key="location_services"
- android:icon="@drawable/baseline_near_me"
+ android:icon="@drawable/ic_chevron_right_24dp"
android:title="@string/location_services_preference_title"
settings:controller="com.android.settings.location.LocationServicesPreferenceController"/>
diff --git a/res/xml/location_settings_personal.xml b/res/xml/location_settings_personal.xml
index 726a96c..a798899 100644
--- a/res/xml/location_settings_personal.xml
+++ b/res/xml/location_settings_personal.xml
@@ -28,14 +28,6 @@
settings:controller=
"com.android.settings.location.RecentLocationAccessPreferenceController"/>
- <Preference
- android:key="recent_location_access_see_all_button"
- android:title="@string/location_recent_location_access_see_all"
- android:icon="@drawable/ic_chevron_right_24dp"
- android:fragment="com.android.settings.location.RecentLocationAccessSeeAllFragment"
- settings:controller="com.android.settings.location.RecentLocationAccessSeeAllButtonPreferenceController"
- settings:searchable="false"/>
-
<!-- This preference category gets removed if new_recent_location_ui is disabled -->
<Preference
android:key="app_level_permissions"
diff --git a/res/xml/location_settings_workprofile.xml b/res/xml/location_settings_workprofile.xml
index 99ccf14..62ec0cb 100644
--- a/res/xml/location_settings_workprofile.xml
+++ b/res/xml/location_settings_workprofile.xml
@@ -28,15 +28,6 @@
settings:controller=
"com.android.settings.location.RecentLocationAccessPreferenceController"/>
- <Preference
- android:key="recent_location_access_see_all_button"
- android:title="@string/location_recent_location_access_see_all"
- android:icon="@drawable/ic_chevron_right_24dp"
- android:fragment="com.android.settings.location.RecentLocationAccessSeeAllFragment"
- settings:controller="com.android.settings.location.RecentLocationAccessSeeAllButtonPreferenceController"
- settings:forWork="true"
- settings:searchable="false"/>
-
<com.android.settingslib.RestrictedSwitchPreference
android:key="managed_profile_location_switch"
android:title="@string/managed_profile_location_switch_title"
diff --git a/res/xml/notification_access_settings.xml b/res/xml/notification_access_settings.xml
index b523d7d..94c90b4 100644
--- a/res/xml/notification_access_settings.xml
+++ b/res/xml/notification_access_settings.xml
@@ -25,9 +25,9 @@
<PreferenceCategory
android:key="allowed"
- android:title="@string/app_permission_summary_allowed"/>
+ android:title="@string/notification_listener_allowed"/>
<PreferenceCategory
android:key="not_allowed"
- android:title="@string/app_permission_summary_not_allowed"/>
+ android:title="@string/notification_listener_not_allowed"/>
</PreferenceScreen>
diff --git a/res/xml/notification_group_settings.xml b/res/xml/notification_group_settings.xml
index cbe23c6..e714759 100644
--- a/res/xml/notification_group_settings.xml
+++ b/res/xml/notification_group_settings.xml
@@ -31,9 +31,9 @@
android:title="@string/app_settings_link"
settings:allowDividerAbove="true"/>
- <com.android.settings.notification.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="desc" />
- <com.android.settings.notification.NotificationFooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:key="block_desc" />
</PreferenceScreen>
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index fd9f318..be1f34c 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -55,6 +55,12 @@
android:title="@string/security_settings_face_preference_title"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_face_settings" />
+
+ <Preference
+ android:key="biometric_settings"
+ android:title="@string/security_settings_biometric_preference_title"
+ android:summary="@string/summary_placeholder"
+ settings:keywords="@string/keywords_biometric_settings" />
</PreferenceCategory>
<!-- work profile security section -->
@@ -91,6 +97,11 @@
android:title="@string/security_settings_face_preference_title"
android:summary="@string/summary_placeholder" />
+ <Preference
+ android:key="biometric_settings_profile"
+ android:title="@string/security_settings_biometric_preference_title"
+ android:summary="@string/summary_placeholder" />
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/res/xml/security_settings_combined_biometric.xml b/res/xml/security_settings_combined_biometric.xml
new file mode 100644
index 0000000..f7d0539
--- /dev/null
+++ b/res/xml/security_settings_combined_biometric.xml
@@ -0,0 +1,69 @@
+<?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.
+-->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/security_settings_biometric_preference_title">
+
+ <com.android.settingslib.widget.TopIntroPreference
+ android:title="@string/biometric_settings_intro" />
+
+ <PreferenceCategory
+ android:key="biometric_ways_to_unlock"
+ android:title="@string/biometric_settings_category_ways_to_unlock">
+
+ <Preference
+ android:key="biometric_fingerprint_settings"
+ android:title="@string/security_settings_fingerprint_preference_title"
+ android:summary="@string/summary_placeholder"
+ settings:keywords="@string/keywords_fingerprint_settings"
+ settings:controller="com.android.settings.biometrics.combination.BiometricFingerprintStatusPreferenceController" />
+
+ <Preference
+ android:key="biometric_face_settings"
+ android:title="@string/security_settings_face_preference_title"
+ android:summary="@string/summary_placeholder"
+ settings:keywords="@string/keywords_face_settings"
+ settings:controller="com.android.settings.biometrics.combination.BiometricFaceStatusPreferenceController" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="biometric_ways_to_use"
+ android:title="@string/biometric_settings_category_ways_to_use">
+
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="biometric_settings_biometric_keyguard"
+ android:title="@string/biometric_settings_use_biometric_unlock_phone"
+ settings:keywords="@string/keywords_biometric_unlock"
+ settings:controller="com.android.settings.biometrics.combination.BiometricSettingsKeyguardPreferenceController"/>
+
+ <SwitchPreference
+ android:key="biometric_settings_biometric_app"
+ android:title="@string/biometric_settings_use_biometric_for_apps"
+ settings:keywords="@string/keywords_biometric_unlock"
+ settings:controller="com.android.settings.biometrics.combination.BiometricSettingsAppPreferenceController"/>
+
+ </PreferenceCategory>
+
+ <SwitchPreference
+ android:key="biometric_setting_lockdown_enabled"
+ android:title="@string/lockdown_settings_title"
+ android:summary="@string/lockdown_settings_summary"
+ settings:controller="com.android.settings.security.LockdownButtonPreferenceController" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/security_settings_combined_biometric_profile.xml b/res/xml/security_settings_combined_biometric_profile.xml
new file mode 100644
index 0000000..5711152
--- /dev/null
+++ b/res/xml/security_settings_combined_biometric_profile.xml
@@ -0,0 +1,56 @@
+<?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.
+-->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/security_settings_biometric_preference_title">
+
+ <com.android.settingslib.widget.TopIntroPreference
+ android:title="@string/biometric_settings_intro" />
+
+ <PreferenceCategory
+ android:key="biometric_ways_to_unlock"
+ android:title="@string/biometric_settings_category_ways_to_unlock">
+
+ <Preference
+ android:key="biometric_fingerprint_settings_profile"
+ android:title="@string/security_settings_fingerprint_preference_title"
+ android:summary="@string/summary_placeholder"
+ settings:keywords="@string/keywords_fingerprint_settings"
+ settings:controller="com.android.settings.biometrics.combination.BiometricFingerprintProfileStatusPreferenceController" />
+
+ <Preference
+ android:key="biometric_face_settings_profile"
+ android:title="@string/security_settings_face_preference_title"
+ android:summary="@string/summary_placeholder"
+ settings:keywords="@string/keywords_face_settings"
+ settings:controller="com.android.settings.biometrics.combination.BiometricFaceProfileStatusPreferenceController" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="biometric_ways_to_use"
+ android:title="@string/biometric_settings_category_ways_to_use">
+
+ <SwitchPreference
+ android:key="biometric_settings_biometric_app_profile"
+ android:title="@string/biometric_settings_use_biometric_for_apps"
+ settings:keywords="@string/keywords_biometric_unlock"
+ settings:controller="com.android.settings.biometrics.combination.BiometricSettingsAppPreferenceController"/>
+
+ </PreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index 1fc1ca8..131f222 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -31,7 +31,8 @@
<PreferenceCategory
android:key="security_settings_face_unlock_category"
- android:title="@string/security_settings_face_settings_use_face_category">
+ android:title="@string/security_settings_face_settings_use_face_category"
+ settings:controller="com.android.settings.biometrics.face.FaceUnlockCategoryPreferenceController">
<com.android.settingslib.RestrictedSwitchPreference
android:key="security_settings_face_keyguard"
android:title="@string/security_settings_face_settings_use_face_unlock_phone"
@@ -66,6 +67,13 @@
android:summary="@string/security_settings_face_settings_require_confirmation_details"
settings:keywords="@string/keywords_face_unlock"
settings:controller="com.android.settings.biometrics.face.FaceSettingsConfirmPreferenceController"/>
+
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="biometric_settings_lockscreen_bypass"
+ android:title="@string/lockscreen_bypass_title"
+ android:summary="@string/lockscreen_bypass_summary"
+ settings:keywords="@string/keywords_lockscreen_bypass"
+ settings:controller="com.android.settings.biometrics.face.FaceSettingsLockscreenBypassPreferenceController" />
</PreferenceCategory>
<PreferenceCategory
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 48793e9..c89402c 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -38,6 +38,8 @@
public static class CreateShortcutActivity extends SettingsActivity { /* empty */ }
public static class FaceSettingsActivity extends SettingsActivity { /* empty */ }
public static class FingerprintSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class CombinedBiometricSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class CombinedBiometricProfileSettingsActivity extends SettingsActivity { /* empty */ }
public static class TetherSettingsActivity extends SettingsActivity {
// TODO(b/147675042): Clean the override up when we enable the new Fragment persistently.
@Override
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 391ee90..8418315 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -842,6 +842,13 @@
}
/**
+ * Return true if the device supports multiple biometrics authentications.
+ */
+ public static boolean isMultipleBiometricsSupported(Context context) {
+ return hasFingerprintHardware(context) && hasFaceHardware(context);
+ }
+
+ /**
* Launches an intent which may optionally have a user id defined.
* @param fragment Fragment to use to launch the activity.
* @param intent Intent to launch.
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
index 5402a9b..26c2313 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
@@ -26,6 +26,7 @@
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
@@ -320,8 +321,13 @@
}
private static CharSequence retrieveSummary(Context context, int lineHeight) {
- return AccessibilityUtil.isFloatingMenuEnabled(context)
- ? getSummaryStringWithLink(context) : getSummaryStringWithIcon(context, lineHeight);
+ final SpannableStringBuilder sb = new SpannableStringBuilder();
+ if (!AccessibilityUtil.isFloatingMenuEnabled(context)) {
+ sb.append(getSummaryStringWithIcon(context, lineHeight));
+ sb.append("\n\n");
+ }
+ sb.append(getCustomizeAccessibilityButtonLink(context));
+ return sb;
}
private static int retrieveSoftwareShortcutImageResId(Context context) {
@@ -330,7 +336,7 @@
: R.drawable.accessibility_shortcut_type_software;
}
- private static CharSequence getSummaryStringWithLink(Context context) {
+ private static CharSequence getCustomizeAccessibilityButtonLink(Context context) {
final View.OnClickListener linkListener = v -> new SubSettingLauncher(context)
.setDestination(AccessibilityButtonFragment.class.getName())
.setSourceMetricsCategory(
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index cede6a0..0a2e5fe 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -16,6 +16,9 @@
package com.android.settings.biometrics;
+import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL;
+import static android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED;
+
import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
@@ -24,6 +27,7 @@
import android.content.res.Resources;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricManager.Authenticators;
+import android.hardware.biometrics.BiometricManager.BiometricError;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintManager;
@@ -31,11 +35,11 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.util.Log;
import androidx.annotation.Nullable;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
@@ -68,12 +72,14 @@
public static final String EXTRA_SKIP_INTRO = "skip_intro";
private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials";
+ private static final String SAVED_STATE_ENROLL_ACTION_LOGGED = "enroll_action_logged";
private static final String SAVED_STATE_GK_PW_HANDLE = "gk_pw_handle";
public static final class InternalActivity extends BiometricEnrollActivity {}
private int mUserId = UserHandle.myUserId();
private boolean mConfirmingCredentials;
+ private boolean mIsEnrollActionLogged;
private boolean mIsFaceEnrollable;
private boolean mIsFingerprintEnrollable;
@Nullable private Long mGkPwHandle;
@@ -91,15 +97,44 @@
}
if (savedInstanceState != null) {
- mConfirmingCredentials = savedInstanceState
- .getBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, false);
+ mConfirmingCredentials = savedInstanceState.getBoolean(
+ SAVED_STATE_CONFIRMING_CREDENTIALS, false);
+ mIsEnrollActionLogged = savedInstanceState.getBoolean(
+ SAVED_STATE_ENROLL_ACTION_LOGGED, false);
if (savedInstanceState.containsKey(SAVED_STATE_GK_PW_HANDLE)) {
mGkPwHandle = savedInstanceState.getLong(SAVED_STATE_GK_PW_HANDLE);
}
}
- // Put the theme in the intent so it gets propagated to other activities in the flow
+ // Log a framework stats event if this activity was launched via intent action.
final Intent intent = getIntent();
+ if (!mIsEnrollActionLogged && ACTION_BIOMETRIC_ENROLL.equals(intent.getAction())) {
+ mIsEnrollActionLogged = true;
+
+ // Get the current status for each authenticator type.
+ @BiometricError final int strongBiometricStatus;
+ @BiometricError final int weakBiometricStatus;
+ @BiometricError final int deviceCredentialStatus;
+ final BiometricManager bm = getSystemService(BiometricManager.class);
+ if (bm != null) {
+ strongBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_STRONG);
+ weakBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_WEAK);
+ deviceCredentialStatus = bm.canAuthenticate(Authenticators.DEVICE_CREDENTIAL);
+ } else {
+ strongBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+ weakBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+ deviceCredentialStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+ }
+
+ FrameworkStatsLog.write(FrameworkStatsLog.AUTH_ENROLL_ACTION_INVOKED,
+ strongBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
+ weakBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
+ deviceCredentialStatus == BiometricManager.BIOMETRIC_SUCCESS,
+ intent.hasExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED),
+ intent.getIntExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, 0));
+ }
+
+ // Put the theme in the intent so it gets propagated to other activities in the flow
if (intent.getStringExtra(WizardManagerHelper.EXTRA_THEME) == null) {
intent.putExtra(
WizardManagerHelper.EXTRA_THEME,
@@ -108,7 +143,7 @@
// Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL.
final int authenticators = intent.getIntExtra(
- Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
+ EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
Log.d(TAG, "Authenticators: " + authenticators);
@@ -132,7 +167,7 @@
} else {
// If the caller is not setup wizard, and the user has something enrolled, finish.
final BiometricManager bm = getSystemService(BiometricManager.class);
- final @BiometricManager.BiometricError int result = bm.canAuthenticate(authenticators);
+ final @BiometricError int result = bm.canAuthenticate(authenticators);
if (result != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
Log.e(TAG, "Unexpected result: " + result);
finish();
@@ -159,6 +194,7 @@
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, mConfirmingCredentials);
+ outState.putBoolean(SAVED_STATE_ENROLL_ACTION_LOGGED, mIsEnrollActionLogged);
if (mGkPwHandle != null) {
outState.putLong(SAVED_STATE_GK_PW_HANDLE, mGkPwHandle);
}
diff --git a/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java b/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java
index 2a3bfb2..70f0baf 100644
--- a/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java
@@ -122,6 +122,9 @@
final String clazz = hasEnrolledBiometrics() ? getSettingsClassName()
: getEnrollClassName();
intent.setClassName(SETTINGS_PACKAGE_NAME, clazz);
+ if (!preference.getExtras().isEmpty()) {
+ intent.putExtras(preference.getExtras());
+ }
intent.putExtra(Intent.EXTRA_USER_ID, userId);
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, true);
context.startActivity(intent);
diff --git a/src/com/android/settings/biometrics/combination/BiometricFaceProfileStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricFaceProfileStatusPreferenceController.java
new file mode 100644
index 0000000..1dbfa64
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/BiometricFaceProfileStatusPreferenceController.java
@@ -0,0 +1,42 @@
+/*
+ * 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 android.content.Context;
+import android.os.UserHandle;
+
+/**
+ * Preference controller for face settings within the biometrics settings page of work profile,
+ * that controls the ability to unlock the phone with face authentication.
+ */
+public class BiometricFaceProfileStatusPreferenceController extends
+ BiometricFaceStatusPreferenceController {
+
+ public BiometricFaceProfileStatusPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected boolean isUserSupported() {
+ return mProfileChallengeUserId != UserHandle.USER_NULL
+ && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId);
+ }
+
+ @Override
+ protected int getUserId() {
+ return mProfileChallengeUserId;
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/BiometricFaceStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricFaceStatusPreferenceController.java
new file mode 100644
index 0000000..e4b210e
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/BiometricFaceStatusPreferenceController.java
@@ -0,0 +1,37 @@
+/*
+ * 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 android.content.Context;
+
+import com.android.settings.Utils;
+import com.android.settings.biometrics.face.FaceStatusPreferenceController;
+
+/**
+ * Preference controller for face settings within the biometrics settings page, that controls the
+ * ability to unlock the phone with face authentication.
+ */
+public class BiometricFaceStatusPreferenceController extends FaceStatusPreferenceController {
+
+ public BiometricFaceStatusPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected boolean isDeviceSupported() {
+ return Utils.hasFaceHardware(mContext);
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/BiometricFingerprintProfileStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricFingerprintProfileStatusPreferenceController.java
new file mode 100644
index 0000000..5477c9d
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/BiometricFingerprintProfileStatusPreferenceController.java
@@ -0,0 +1,42 @@
+/*
+ * 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 android.content.Context;
+import android.os.UserHandle;
+
+/**
+ * Preference controller for fingerprint settings within the biometrics settings page, that controls
+ * the ability to unlock the phone with fingerprint.
+ */
+public class BiometricFingerprintProfileStatusPreferenceController extends
+ BiometricFingerprintStatusPreferenceController {
+
+ public BiometricFingerprintProfileStatusPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected boolean isUserSupported() {
+ return mProfileChallengeUserId != UserHandle.USER_NULL
+ && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId);
+ }
+
+ @Override
+ protected int getUserId() {
+ return mProfileChallengeUserId;
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/BiometricFingerprintStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricFingerprintStatusPreferenceController.java
new file mode 100644
index 0000000..fd742ff
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/BiometricFingerprintStatusPreferenceController.java
@@ -0,0 +1,38 @@
+/*
+ * 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 android.content.Context;
+
+import com.android.settings.Utils;
+import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
+
+/**
+ * Preference controller for fingerprint settings within the biometrics settings page of work
+ * profile, that controls the ability to unlock the phone with fingerprint.
+ */
+public class BiometricFingerprintStatusPreferenceController extends
+ FingerprintStatusPreferenceController {
+
+ public BiometricFingerprintStatusPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected boolean isDeviceSupported() {
+ return Utils.hasFingerprintHardware(mContext);
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java
new file mode 100644
index 0000000..9107e1b
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java
@@ -0,0 +1,86 @@
+/*
+ * 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 android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.provider.Settings;
+
+import com.android.settings.Utils;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+/**
+ * Preference controller that controls whether the biometrics authentication to be used in apps.
+ */
+public class BiometricSettingsAppPreferenceController extends TogglePreferenceController {
+ private static final int ON = 1;
+ private static final int OFF = 0;
+ private static final int DEFAULT = ON;
+
+ private int mUserId;
+ private FaceManager mFaceManager;
+ private FingerprintManager mFingerprintManager;
+
+ public BiometricSettingsAppPreferenceController(Context context, String key) {
+ super(context, key);
+ mFaceManager = Utils.getFaceManagerOrNull(context);
+ mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
+ }
+
+ protected EnforcedAdmin getRestrictingAdmin() {
+ return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(mContext,
+ DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS, mUserId);
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(), BIOMETRIC_APP_ENABLED,
+ DEFAULT, mUserId) == ON;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.Secure.putIntForUser(mContext.getContentResolver(), BIOMETRIC_APP_ENABLED,
+ isChecked ? ON : OFF, mUserId);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mFaceManager == null || mFingerprintManager == null) {
+ return AVAILABLE_UNSEARCHABLE;
+ }
+ // This preference will be available only if the user has registered either face auth
+ // or fingerprint.
+ final boolean hasFaceEnrolledUser = mFaceManager.hasEnrolledTemplates(mUserId);
+ final boolean hasFingerprintEnrolledUser =
+ mFingerprintManager.hasEnrolledTemplates(mUserId);
+ if (hasFaceEnrolledUser || hasFingerprintEnrolledUser) {
+ return AVAILABLE;
+ } else {
+ return AVAILABLE_UNSEARCHABLE;
+ }
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java
new file mode 100644
index 0000000..263134a
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java
@@ -0,0 +1,67 @@
+/*
+ * 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 android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+/**
+ * Preference controller that controls whether the biometrics authentication to unlock the device.
+ */
+public class BiometricSettingsKeyguardPreferenceController extends TogglePreferenceController {
+ private static final int ON = 1;
+ private static final int OFF = 0;
+ private static final int DEFAULT = ON;
+
+ private int mUserId;
+
+ public BiometricSettingsKeyguardPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ protected RestrictedLockUtils.EnforcedAdmin getRestrictingAdmin() {
+ return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(mContext,
+ DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS, mUserId);
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ BIOMETRIC_KEYGUARD_ENABLED, DEFAULT, mUserId) == ON;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ BIOMETRIC_KEYGUARD_ENABLED, isChecked ? ON : OFF, mUserId);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java b/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
new file mode 100644
index 0000000..4260c7c
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
@@ -0,0 +1,197 @@
+/*
+ * 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 android.app.Activity.RESULT_OK;
+
+import static com.android.settings.password.ChooseLockPattern.RESULT_FINISHED;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+
+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.dashboard.DashboardFragment;
+import com.android.settings.password.ChooseLockGeneric;
+import com.android.settings.password.ChooseLockSettingsHelper;
+
+/**
+ * Base fragment with the confirming credential functionality for combined biometrics settings.
+ */
+public abstract class BiometricsSettingsBase extends DashboardFragment {
+
+ private static final int CONFIRM_REQUEST = 2001;
+ private static final int CHOOSE_LOCK_REQUEST = 2002;
+
+ private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential";
+
+ protected int mUserId;
+ protected long mFaceChallenge;
+ protected long mFingerprintChallenge;
+ protected int mFaceSensorId;
+ protected int mFingerprintSensorId;
+ protected long mGkPwHandle;
+ private boolean mConfirmCredential;
+ @Nullable private FaceManager mFaceManager;
+ @Nullable private FingerprintManager mFingerprintManager;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mUserId = getActivity().getIntent().getIntExtra(Intent.EXTRA_USER_ID,
+ UserHandle.myUserId());
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mFaceManager = Utils.getFaceManagerOrNull(getActivity());
+ mFingerprintManager = Utils.getFingerprintManagerOrNull(getActivity());
+
+ if (BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) {
+ mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(getIntent());
+ }
+
+ if (savedInstanceState != null) {
+ mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL);
+ if (savedInstanceState.containsKey(
+ ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE)) {
+ mGkPwHandle = savedInstanceState.getLong(
+ ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE);
+ }
+ }
+
+ if (mGkPwHandle == 0L && !mConfirmCredential) {
+ mConfirmCredential = true;
+ launchChooseOrConfirmLock();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (getActivity().isFinishing()) {
+ mFaceManager.revokeChallenge(mFaceSensorId, mUserId, mFaceChallenge);
+ mFingerprintManager.revokeChallenge(mUserId, mFingerprintChallenge);
+ BiometricUtils.removeGatekeeperPasswordHandle(getActivity(), mGkPwHandle);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(Preference preference) {
+ final String key = preference.getKey();
+ if (getFacePreferenceKey().equals(key)) {
+ final byte[] token = BiometricUtils.requestGatekeeperHat(getActivity(), mGkPwHandle,
+ mUserId, mFaceChallenge);
+ final Bundle extras = preference.getExtras();
+ extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+ extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, mFaceSensorId);
+ extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, mFaceChallenge);
+ } else if (getFingerprintPreferenceKey().equals(key)) {
+ final byte[] token = BiometricUtils.requestGatekeeperHat(getActivity(), mGkPwHandle,
+ mUserId, mFingerprintChallenge);
+ final Bundle extras = preference.getExtras();
+ extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+ extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, mFingerprintChallenge);
+ }
+ return super.onPreferenceTreeClick(preference);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(SAVE_STATE_CONFIRM_CREDETIAL, mConfirmCredential);
+ if (mGkPwHandle != 0L) {
+ outState.putLong(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, mGkPwHandle);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == CONFIRM_REQUEST || requestCode == CHOOSE_LOCK_REQUEST) {
+ mConfirmCredential = false;
+ if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
+ if (data != null && BiometricUtils.containsGatekeeperPasswordHandle(data)) {
+ mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data);
+ mFaceManager.generateChallenge((sensorId, challenge) -> {
+ mFaceSensorId = sensorId;
+ mFaceChallenge = challenge;
+ });
+ mFingerprintManager.generateChallenge(mUserId, (sensorId, challenge) -> {
+ mFingerprintSensorId = sensorId;
+ mFingerprintChallenge = challenge;
+ });
+ } else {
+ Log.d(getLogTag(), "Data null or GK PW missing.");
+ finish();
+ }
+ } else {
+ Log.d(getLogTag(), "Password not confirmed.");
+ finish();
+ }
+ }
+ }
+
+ /**
+ * Get the preference key of face for passing through credential data to face settings.
+ */
+ public abstract String getFacePreferenceKey();
+
+ /**
+ * Get the preference key of face for passing through credential data to face settings.
+ */
+ public abstract String getFingerprintPreferenceKey();
+
+ private void launchChooseOrConfirmLock() {
+ final ChooseLockSettingsHelper.Builder builder =
+ new ChooseLockSettingsHelper.Builder(getActivity(), this)
+ .setRequestCode(CONFIRM_REQUEST)
+ .setTitle(getString(R.string.security_settings_biometric_preference_title))
+ .setRequestGatekeeperPasswordHandle(true)
+ .setForegroundOnly(true)
+ .setReturnCredentials(true);
+ if (mUserId != UserHandle.USER_NULL) {
+ builder.setUserId(mUserId);
+ }
+ final boolean launched = builder.show();
+
+ if (!launched) {
+ Intent intent = BiometricUtils.getChooseLockIntent(getActivity(), getIntent());
+ intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
+
+ if (mUserId != UserHandle.USER_NULL) {
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ }
+ startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
+ }
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettings.java b/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettings.java
new file mode 100644
index 0000000..08c934d
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettings.java
@@ -0,0 +1,65 @@
+/*
+ * 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 android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+
+/**
+ * Settings screen for multiple biometrics used in work profile.
+ */
+public class CombinedBiometricProfileSettings extends BiometricsSettingsBase {
+ private static final String TAG = "BiometricProfileSetting";
+ private static final String KEY_FACE_SETTINGS = "biometric_face_settings_profile";
+ private static final String KEY_FINGERPRINT_SETTINGS = "biometric_fingerprint_settings_profile";
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ use(BiometricSettingsAppPreferenceController.class).setUserId(mUserId);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.security_settings_combined_biometric_profile;
+ }
+
+ @Override
+ public String getFacePreferenceKey() {
+ return KEY_FACE_SETTINGS;
+ }
+
+ @Override
+ public String getFingerprintPreferenceKey() {
+ return KEY_FINGERPRINT_SETTINGS;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.COMBINED_BIOMETRIC_PROFILE;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.security_settings_combined_biometric_profile);
+}
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricProfileStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/CombinedBiometricProfileStatusPreferenceController.java
new file mode 100644
index 0000000..e9cbcd8
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricProfileStatusPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * 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 android.content.Context;
+import android.os.UserHandle;
+
+import com.android.settings.Settings;
+
+/**
+ * Preference controller for biometrics settings page of work profile, controlling the ability to
+ * unlock the phone with face and fingerprint.
+ */
+public class CombinedBiometricProfileStatusPreferenceController extends
+ CombinedBiometricStatusPreferenceController {
+
+ private static final String KEY_BIOMETRIC_SETTINGS = "biometric_settings_profile";
+
+ public CombinedBiometricProfileStatusPreferenceController(Context context) {
+ super(context, KEY_BIOMETRIC_SETTINGS);
+ }
+
+ public CombinedBiometricProfileStatusPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected boolean isUserSupported() {
+ return mProfileChallengeUserId != UserHandle.USER_NULL
+ && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId);
+ }
+
+ @Override
+ protected int getUserId() {
+ return mProfileChallengeUserId;
+ }
+
+ @Override
+ protected String getSettingsClassName() {
+ return Settings.CombinedBiometricProfileSettingsActivity.class.getName();
+ }
+
+ @Override
+ protected String getEnrollClassName() {
+ return Settings.CombinedBiometricProfileSettingsActivity.class.getName();
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java b/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java
new file mode 100644
index 0000000..9ebb62f
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java
@@ -0,0 +1,68 @@
+/*
+ * 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 android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+/**
+ * Settings screen for multiple biometrics.
+ */
+@SearchIndexable
+public class CombinedBiometricSettings extends BiometricsSettingsBase {
+ private static final String TAG = "BiometricSettings";
+ private static final String KEY_FACE_SETTINGS = "biometric_face_settings";
+ private static final String KEY_FINGERPRINT_SETTINGS = "biometric_fingerprint_settings";
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ use(BiometricSettingsKeyguardPreferenceController.class).setUserId(mUserId);
+ use(BiometricSettingsAppPreferenceController.class).setUserId(mUserId);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.security_settings_combined_biometric;
+ }
+
+ @Override
+ public String getFacePreferenceKey() {
+ return KEY_FACE_SETTINGS;
+ }
+
+ @Override
+ public String getFingerprintPreferenceKey() {
+ return KEY_FINGERPRINT_SETTINGS;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.COMBINED_BIOMETRIC;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.security_settings_combined_biometric);
+}
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java
new file mode 100644
index 0000000..c3db174
--- /dev/null
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java
@@ -0,0 +1,71 @@
+/*
+ * 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 android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.Settings;
+import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricStatusPreferenceController;
+
+/**
+ * Preference controller for biometrics settings page controlling the ability to unlock the phone
+ * with face and fingerprint.
+ */
+public class CombinedBiometricStatusPreferenceController extends
+ BiometricStatusPreferenceController {
+ private static final String KEY_BIOMETRIC_SETTINGS = "biometric_settings";
+
+
+ public CombinedBiometricStatusPreferenceController(Context context) {
+ this(context, KEY_BIOMETRIC_SETTINGS);
+ }
+
+ public CombinedBiometricStatusPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected boolean isDeviceSupported() {
+ return Utils.hasFingerprintHardware(mContext) && Utils.hasFaceHardware(mContext);
+ }
+
+ @Override
+ protected boolean hasEnrolledBiometrics() {
+ return false;
+ }
+
+ @Override
+ protected String getSummaryTextEnrolled() {
+ return mContext.getString(R.string.security_settings_biometric_preference_summary);
+ }
+
+ @Override
+ protected String getSummaryTextNoneEnrolled() {
+ return mContext.getString(R.string.security_settings_biometric_preference_summary);
+ }
+
+ @Override
+ protected String getSettingsClassName() {
+ return Settings.CombinedBiometricSettingsActivity.class.getName();
+ }
+
+ @Override
+ protected String getEnrollClassName() {
+ return Settings.CombinedBiometricSettingsActivity.class.getName();
+ }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
index bde146b..c296e56 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
@@ -78,6 +78,11 @@
@Override
public int getAvailabilityStatus() {
+ // When the device supports multiple biometrics auth, this preference will be hidden.
+ if (Utils.isMultipleBiometricsSupported(mContext)) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+
if(mFaceManager == null){
return AVAILABLE_UNSEARCHABLE;
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
index 8ee7ffd..342d786 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
@@ -70,7 +70,8 @@
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
+ // When the device supports multiple biometrics auth, this preference will be unavailable.
+ return Utils.isMultipleBiometricsSupported(mContext) ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
index 0a2757b..2f0ef4f 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
@@ -26,6 +26,7 @@
import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.Utils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -82,6 +83,11 @@
@Override
public int getAvailabilityStatus() {
+ // When the device supports multiple biometrics auth, this preference will be shown
+ // in face unlock category.
+ if (Utils.isMultipleBiometricsSupported(mContext)) {
+ return AVAILABLE;
+ }
if (mUserManager.isManagedProfile(UserHandle.myUserId())) {
return UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
index 94651d7..c2143c0 100644
--- a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
@@ -41,7 +41,7 @@
@Override
protected boolean isDeviceSupported() {
- return FaceSettings.isFaceHardwareDetected(mContext);
+ return !Utils.isMultipleBiometricsSupported(mContext) && Utils.hasFaceHardware(mContext);
}
@Override
diff --git a/src/com/android/settings/biometrics/face/FaceUnlockCategoryPreferenceController.java b/src/com/android/settings/biometrics/face/FaceUnlockCategoryPreferenceController.java
new file mode 100644
index 0000000..d0debdf
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceUnlockCategoryPreferenceController.java
@@ -0,0 +1,36 @@
+/*
+ * 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.face;
+
+import android.content.Context;
+
+import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Preference controller that controls the face unlock features to be shown / be hidden.
+ */
+public class FaceUnlockCategoryPreferenceController extends BasePreferenceController {
+
+ public FaceUnlockCategoryPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return Utils.isMultipleBiometricsSupported(mContext) ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java
index 0e1ccd7..e53dbc4 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java
@@ -40,7 +40,8 @@
@Override
protected boolean isDeviceSupported() {
- return mFingerprintManager != null && mFingerprintManager.isHardwareDetected();
+ return !Utils.isMultipleBiometricsSupported(mContext)
+ && Utils.hasFingerprintHardware(mContext);
}
@Override
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
index 10acdb5..8794b08 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
@@ -32,6 +32,7 @@
import androidx.preference.Preference;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.settings.R;
@@ -51,8 +52,6 @@
private TextView messageView;
private Button mOkButton;
private BluetoothDevice mDevice;
- private String mReturnPackage = null;
- private String mReturnClass = null;
private int mRequestType = 0;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -89,8 +88,6 @@
}
mDevice = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- mReturnPackage = i.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME);
- mReturnClass = i.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME);
mRequestType = i.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
@@ -202,14 +199,14 @@
sendReplyIntentToReceiver(false, true);
}
- private void sendReplyIntentToReceiver(final boolean allowed, final boolean always) {
+ @VisibleForTesting
+ void sendReplyIntentToReceiver(final boolean allowed, final boolean always) {
Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
- if (mReturnPackage != null && mReturnClass != null) {
- intent.setClassName(mReturnPackage, mReturnClass);
+ if (DEBUG) {
+ Log.i(TAG, "sendReplyIntentToReceiver() Request type: " + mRequestType
+ + " mReturnPackage");
}
- if (DEBUG) Log.i(TAG, "sendReplyIntentToReceiver() Request type: " + mRequestType +
- " mReturnPackage" + mReturnPackage + " mReturnClass" + mReturnClass);
intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
allowed ? BluetoothDevice.CONNECTION_ACCESS_YES
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
index 7fac4991c..66665f0 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
@@ -56,8 +56,6 @@
Context mContext;
int mRequestType;
BluetoothDevice mDevice;
- String mReturnPackage = null;
- String mReturnClass = null;
@Override
public void onReceive(Context context, Intent intent) {
@@ -77,11 +75,10 @@
mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mRequestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION);
- mReturnPackage = intent.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME);
- mReturnClass = intent.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME);
- if (DEBUG) Log.d(TAG, "onReceive request type: " + mRequestType + " return "
- + mReturnPackage + "," + mReturnClass);
+ if (DEBUG) {
+ Log.d(TAG, "onReceive request type: " + mRequestType);
+ }
// Even if the user has already made the choice, Bluetooth still may not know that if
// the user preference data have not been migrated from Settings app's shared
@@ -110,8 +107,6 @@
connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
mRequestType);
connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
- connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_PACKAGE_NAME, mReturnPackage);
- connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_CLASS_NAME, mReturnClass);
String deviceAddress = mDevice != null ? mDevice.getAddress() : null;
String deviceName = mDevice != null ? mDevice.getName() : null;
@@ -231,7 +226,7 @@
LocalBluetoothManager bluetoothManager = Utils.getLocalBtManager(mContext);
CachedBluetoothDeviceManager cachedDeviceManager =
- bluetoothManager.getCachedDeviceManager();
+ bluetoothManager.getCachedDeviceManager();
CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
if (cachedDevice == null) {
cachedDevice = cachedDeviceManager.addDevice(mDevice);
@@ -289,13 +284,9 @@
private void sendReplyIntentToReceiver(final boolean allowed) {
Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
- if (mReturnPackage != null && mReturnClass != null) {
- intent.setClassName(mReturnPackage, mReturnClass);
- }
-
intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
- allowed ? BluetoothDevice.CONNECTION_ACCESS_YES
- : BluetoothDevice.CONNECTION_ACCESS_NO);
+ allowed ? BluetoothDevice.CONNECTION_ACCESS_YES
+ : BluetoothDevice.CONNECTION_ACCESS_NO);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType);
mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN);
diff --git a/src/com/android/settings/bluetooth/DevicePickerFragment.java b/src/com/android/settings/bluetooth/DevicePickerFragment.java
index ab8eea5..f60183b 100644
--- a/src/com/android/settings/bluetooth/DevicePickerFragment.java
+++ b/src/com/android/settings/bluetooth/DevicePickerFragment.java
@@ -48,10 +48,10 @@
@VisibleForTesting
BluetoothProgressCategory mAvailableDevicesCategory;
+ @VisibleForTesting
+ Context mContext;
private boolean mNeedAuth;
- private String mLaunchPackage;
- private String mLaunchClass;
private boolean mScanAllowed;
public DevicePickerFragment() {
@@ -64,8 +64,6 @@
mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
setFilter(intent.getIntExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
BluetoothDevicePicker.FILTER_TYPE_ALL));
- mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE);
- mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS);
mAvailableDevicesCategory = (BluetoothProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
}
@@ -85,6 +83,7 @@
getActivity().setTitle(getString(R.string.device_picker));
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
mScanAllowed = !um.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH);
+ mContext = getContext();
setHasOptionsMenu(true);
}
@@ -190,9 +189,7 @@
private void sendDevicePickedIntent(BluetoothDevice device) {
Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- if (mLaunchPackage != null && mLaunchClass != null) {
- intent.setClassName(mLaunchPackage, mLaunchClass);
- }
- getActivity().sendBroadcast(intent, Manifest.permission.BLUETOOTH_ADMIN);
+
+ mContext.sendBroadcast(intent, Manifest.permission.BLUETOOTH_ADMIN);
}
}
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index a9513ea..cf3cd50 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -50,8 +50,6 @@
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.util.ThemeHelper;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -62,7 +60,6 @@
protected static final boolean DEBUG_TIMING = false;
private static final String TAG = "SettingsBaseActivity";
private static final String DATA_SCHEME_PKG = "package";
- private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
// Serves as a temporary list of tiles to ignore until we heard back from the PM that they
// are disabled.
@@ -98,7 +95,7 @@
if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME)
&& isToolbarEnabled() && !isAnySetupWizard) {
- super.setContentView(R.layout.settings_collapsing_base_layout);
+ super.setContentView(R.layout.collapsing_toolbar_base_layout);
mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
} else {
super.setContentView(R.layout.settings_base_layout);
@@ -111,7 +108,6 @@
return;
}
setActionBar(toolbar);
- initCollapsingToolbar();
if (DEBUG_TIMING) {
Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms");
@@ -211,50 +207,6 @@
return true;
}
- private void initCollapsingToolbar() {
- if (mCollapsingToolbarLayout == null) {
- return;
- }
- mCollapsingToolbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- v.removeOnLayoutChangeListener(this);
- final int count = getLineCount();
- if (count > TOOLBAR_MAX_LINE_NUMBER) {
- ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
- lp.height = getResources()
- .getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
- mCollapsingToolbarLayout.setLayoutParams(lp);
- } else if (count == TOOLBAR_MAX_LINE_NUMBER) {
- ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
- lp.height =
- getResources().getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
- mCollapsingToolbarLayout.setLayoutParams(lp);
- }
- }
- });
- }
-
- private int getLineCount() {
- try {
- final Class<?> toolbarClazz = mCollapsingToolbarLayout.getClass();
- final Field textHelperField = toolbarClazz.getDeclaredField("collapsingTextHelper");
- textHelperField.setAccessible(true);
- final Object textHelperObj = textHelperField.get(mCollapsingToolbarLayout);
-
- final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
- layoutField.setAccessible(true);
- final Object layoutObj = layoutField.get(textHelperObj);
-
- final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
- return (int) method.invoke(layoutObj);
- } catch (Exception e) {
- return 0;
- }
- }
-
-
private void onCategoriesChanged(Set<String> categories) {
final int N = mCategoryListeners.size();
for (int i = 0; i < N; i++) {
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index a6305cb..01c613a 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -63,6 +63,8 @@
import com.android.settings.backup.PrivacySettings;
import com.android.settings.backup.ToggleBackupSettingFragment;
import com.android.settings.backup.UserBackupSettingsActivity;
+import com.android.settings.biometrics.combination.CombinedBiometricProfileSettings;
+import com.android.settings.biometrics.combination.CombinedBiometricSettings;
import com.android.settings.biometrics.face.FaceSettings;
import com.android.settings.biometrics.fingerprint.FingerprintSettings;
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
@@ -222,6 +224,8 @@
AssistGestureSettings.class.getName(),
FaceSettings.class.getName(),
FingerprintSettings.FingerprintSettingsFragment.class.getName(),
+ CombinedBiometricSettings.class.getName(),
+ CombinedBiometricProfileSettings.class.getName(),
SwipeToNotificationSettings.class.getName(),
DoubleTapPowerSettings.class.getName(),
DoubleTapScreenSettings.class.getName(),
diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java
index 16084c0..c55d0cb 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTiles.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java
@@ -371,7 +371,7 @@
mContext = getApplicationContext();
mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService(
Context.SENSOR_PRIVACY_SERVICE);
- mIsEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
+ mIsEnabled = mSensorPrivacyManager.isAllSensorPrivacyEnabled();
mMetricsFeatureProvider = FeatureFactory.getFactory(
mContext).getMetricsFeatureProvider();
mKeyguardManager = (KeyguardManager) mContext.getSystemService(
@@ -392,7 +392,7 @@
mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY,
isEnabled);
mIsEnabled = isEnabled;
- mSensorPrivacyManager.setSensorPrivacy(isEnabled);
+ mSensorPrivacyManager.setAllSensorPrivacy(isEnabled);
}
}
diff --git a/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java b/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
index 72a1c66..ba7a3ab 100644
--- a/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
@@ -43,7 +43,7 @@
mPreference.setPositiveButtonText(R.string.allow);
mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA,
- enabled -> updateVisibility());
+ (sensor, enabled) -> updateVisibility());
mPreference.setPositiveButtonOnClickListener(p -> {
mPrivacyManager.setSensorPrivacy(CAMERA, false);
});
diff --git a/src/com/android/settings/display/ColorModePreferenceController.java b/src/com/android/settings/display/ColorModePreferenceController.java
index 7a43e5c..6cd4867 100644
--- a/src/com/android/settings/display/ColorModePreferenceController.java
+++ b/src/com/android/settings/display/ColorModePreferenceController.java
@@ -18,13 +18,10 @@
import androidx.annotation.VisibleForTesting;
-import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class ColorModePreferenceController extends BasePreferenceController {
- private ColorDisplayManager mColorDisplayManager;
-
public ColorModePreferenceController(Context context, String key) {
super(context, key);
}
@@ -39,24 +36,11 @@
@Override
public CharSequence getSummary() {
- final int colorMode = getColorDisplayManager().getColorMode();
- if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
- return mContext.getText(R.string.color_mode_option_automatic);
- }
- if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) {
- return mContext.getText(R.string.color_mode_option_saturated);
- }
- if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) {
- return mContext.getText(R.string.color_mode_option_boosted);
- }
- return mContext.getText(R.string.color_mode_option_natural);
+ return ColorModeUtils.getColorModeMapping(mContext.getResources()).get(getColorMode());
}
@VisibleForTesting
- ColorDisplayManager getColorDisplayManager() {
- if (mColorDisplayManager == null) {
- mColorDisplayManager = mContext.getSystemService(ColorDisplayManager.class);
- }
- return mColorDisplayManager;
+ public int getColorMode() {
+ return mContext.getSystemService(ColorDisplayManager.class).getColorMode();
}
}
diff --git a/src/com/android/settings/display/ColorModePreferenceFragment.java b/src/com/android/settings/display/ColorModePreferenceFragment.java
index c48c1d4..b8fa0b9 100644
--- a/src/com/android/settings/display/ColorModePreferenceFragment.java
+++ b/src/com/android/settings/display/ColorModePreferenceFragment.java
@@ -13,9 +13,17 @@
*/
package com.android.settings.display;
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_AUTOMATIC;
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_BOOSTED;
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_NATURAL;
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED;
+import static android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX;
+import static android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN;
+
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.hardware.display.ColorDisplayManager;
@@ -36,28 +44,26 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
@SuppressWarnings("WeakerAccess")
@SearchIndexable
public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
- @VisibleForTesting
- static final String KEY_COLOR_MODE_NATURAL = "color_mode_natural";
- @VisibleForTesting
- static final String KEY_COLOR_MODE_BOOSTED = "color_mode_boosted";
- @VisibleForTesting
- static final String KEY_COLOR_MODE_SATURATED = "color_mode_saturated";
- @VisibleForTesting
- static final String KEY_COLOR_MODE_AUTOMATIC = "color_mode_automatic";
+ private static final String KEY_COLOR_MODE_PREFIX = "color_mode_";
+
+ private static final int COLOR_MODE_FALLBACK = COLOR_MODE_NATURAL;
private ContentObserver mContentObserver;
private ColorDisplayManager mColorDisplayManager;
+ private Resources mResources;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mColorDisplayManager = context.getSystemService(ColorDisplayManager.class);
+ mResources = context.getResources();
final ContentResolver cr = context.getContentResolver();
mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
@@ -81,11 +87,11 @@
@Override
public void onDetach() {
- super.onDetach();
if (mContentObserver != null) {
getContext().getContentResolver().unregisterContentObserver(mContentObserver);
mContentObserver = null;
}
+ super.onDetach();
}
@Override
@@ -108,73 +114,73 @@
@Override
protected List<? extends CandidateInfo> getCandidates() {
- final Context c = getContext();
- final int[] availableColorModes = c.getResources().getIntArray(
- com.android.internal.R.array.config_availableColorModes);
-
- List<ColorModeCandidateInfo> candidates = new ArrayList<>();
- if (availableColorModes != null) {
- for (int colorMode : availableColorModes) {
- if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) {
- candidates.add(new ColorModeCandidateInfo(
- c.getText(R.string.color_mode_option_natural),
- KEY_COLOR_MODE_NATURAL, true /* enabled */));
- } else if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) {
- candidates.add(new ColorModeCandidateInfo(
- c.getText(R.string.color_mode_option_boosted),
- KEY_COLOR_MODE_BOOSTED, true /* enabled */));
- } else if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) {
- candidates.add(new ColorModeCandidateInfo(
- c.getText(R.string.color_mode_option_saturated),
- KEY_COLOR_MODE_SATURATED, true /* enabled */));
- } else if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
- candidates.add(new ColorModeCandidateInfo(
- c.getText(R.string.color_mode_option_automatic),
- KEY_COLOR_MODE_AUTOMATIC, true /* enabled */));
- }
- }
+ final Map<Integer, String> colorModesToSummaries =
+ ColorModeUtils.getColorModeMapping(mResources);
+ final List<ColorModeCandidateInfo> candidates = new ArrayList<>();
+ for (int colorMode : mResources.getIntArray(
+ com.android.internal.R.array.config_availableColorModes)) {
+ candidates.add(new ColorModeCandidateInfo(
+ colorModesToSummaries.get(colorMode),
+ getKeyForColorMode(colorMode),
+ true /* enabled */));
}
return candidates;
}
@Override
protected String getDefaultKey() {
- final int colorMode = mColorDisplayManager.getColorMode();
- if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
- return KEY_COLOR_MODE_AUTOMATIC;
- } else if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) {
- return KEY_COLOR_MODE_SATURATED;
- } else if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) {
- return KEY_COLOR_MODE_BOOSTED;
+ final int colorMode = getColorMode();
+ if (isValidColorMode(colorMode)) {
+ return getKeyForColorMode(colorMode);
}
- return KEY_COLOR_MODE_NATURAL;
+ return getKeyForColorMode(COLOR_MODE_FALLBACK);
}
@Override
protected boolean setDefaultKey(String key) {
- switch (key) {
- case KEY_COLOR_MODE_NATURAL:
- mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
- break;
- case KEY_COLOR_MODE_BOOSTED:
- mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED);
- break;
- case KEY_COLOR_MODE_SATURATED:
- mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED);
- break;
- case KEY_COLOR_MODE_AUTOMATIC:
- mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
- break;
+ int colorMode = Integer.parseInt(key.substring(key.lastIndexOf("_") + 1));
+ if (isValidColorMode(colorMode)) {
+ setColorMode(colorMode);
}
return true;
}
+ /**
+ * Wraps ColorDisplayManager#getColorMode for substitution in testing.
+ */
+ @VisibleForTesting
+ public int getColorMode() {
+ return mColorDisplayManager.getColorMode();
+ }
+
+ /**
+ * Wraps ColorDisplayManager#setColorMode for substitution in testing.
+ */
+ @VisibleForTesting
+ public void setColorMode(int colorMode) {
+ mColorDisplayManager.setColorMode(colorMode);
+ }
+
@Override
public int getMetricsCategory() {
return SettingsEnums.COLOR_MODE_SETTINGS;
}
@VisibleForTesting
+ String getKeyForColorMode(int colorMode) {
+ return KEY_COLOR_MODE_PREFIX + colorMode;
+ }
+
+ private boolean isValidColorMode(int colorMode) {
+ return colorMode == COLOR_MODE_NATURAL
+ || colorMode == COLOR_MODE_BOOSTED
+ || colorMode == COLOR_MODE_SATURATED
+ || colorMode == COLOR_MODE_AUTOMATIC
+ || (colorMode >= VENDOR_COLOR_MODE_RANGE_MIN
+ && colorMode <= VENDOR_COLOR_MODE_RANGE_MAX);
+ }
+
+ @VisibleForTesting
static class ColorModeCandidateInfo extends CandidateInfo {
private final CharSequence mLabel;
private final String mKey;
diff --git a/src/com/android/settings/display/ColorModeUtils.java b/src/com/android/settings/display/ColorModeUtils.java
new file mode 100644
index 0000000..cdd978e
--- /dev/null
+++ b/src/com/android/settings/display/ColorModeUtils.java
@@ -0,0 +1,62 @@
+/*
+ * 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.display;
+
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_AUTOMATIC;
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_BOOSTED;
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_NATURAL;
+import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED;
+import static android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX;
+import static android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN;
+
+import android.content.res.Resources;
+import android.util.ArrayMap;
+
+import com.android.settings.R;
+
+import java.util.Map;
+
+final class ColorModeUtils {
+
+ private ColorModeUtils() {
+ // Do not instantiate.
+ }
+
+ static Map<Integer, String> getColorModeMapping(Resources resources) {
+ final String[] colorModeOptionsStrings = resources.getStringArray(
+ R.array.config_color_mode_options_strings);
+ final int[] colorModeOptionsValues = resources.getIntArray(
+ R.array.config_color_mode_options_values);
+ if (colorModeOptionsStrings.length != colorModeOptionsValues.length) {
+ throw new RuntimeException("Color mode options of unequal length");
+ }
+
+ final Map<Integer, String> colorModesToSummaries = new ArrayMap<>();
+ for (int i = 0; i < colorModeOptionsValues.length; i++) {
+ final int colorMode = colorModeOptionsValues[i];
+ if (colorMode == COLOR_MODE_NATURAL
+ || colorMode == COLOR_MODE_BOOSTED
+ || colorMode == COLOR_MODE_SATURATED
+ || colorMode == COLOR_MODE_AUTOMATIC
+ || (colorMode >= VENDOR_COLOR_MODE_RANGE_MIN
+ && colorMode <= VENDOR_COLOR_MODE_RANGE_MAX)) {
+ colorModesToSummaries.put(colorMode, colorModeOptionsStrings[i]);
+ }
+ }
+ return colorModesToSummaries;
+ }
+}
diff --git a/src/com/android/settings/display/ScreenTimeoutSettings.java b/src/com/android/settings/display/ScreenTimeoutSettings.java
index 444f8ef8..27e1e1b 100644
--- a/src/com/android/settings/display/ScreenTimeoutSettings.java
+++ b/src/com/android/settings/display/ScreenTimeoutSettings.java
@@ -111,9 +111,7 @@
mPrivacyPreference.setLayoutResource(R.layout.preference_footer);
mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA,
- enabled -> {
- mAdaptiveSleepController.updatePreference();
- });
+ (sensor, enabled) -> mAdaptiveSleepController.updatePreference());
}
@Override
diff --git a/src/com/android/settings/display/SmartAutoRotateCameraStateController.java b/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
index 1480785..9e2a784 100644
--- a/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
+++ b/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
@@ -43,7 +43,7 @@
public SmartAutoRotateCameraStateController(Context context, String key) {
super(context, key);
mPrivacyManager = SensorPrivacyManager.getInstance(context);
- mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> {
+ mPrivacyManager.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> {
mPreference.setVisible(enabled);
updateState(mPreference);
});
diff --git a/src/com/android/settings/display/SmartAutoRotateController.java b/src/com/android/settings/display/SmartAutoRotateController.java
index e3b2665..cf2a9a6 100644
--- a/src/com/android/settings/display/SmartAutoRotateController.java
+++ b/src/com/android/settings/display/SmartAutoRotateController.java
@@ -52,7 +52,8 @@
super(context, preferenceKey);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mPrivacyManager = SensorPrivacyManager.getInstance(context);
- mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> updateState(mPreference));
+ mPrivacyManager
+ .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> updateState(mPreference));
}
@Override
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 432224d..3ef7c45 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -27,6 +27,7 @@
import android.os.UserHandle;
import android.text.Html;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
@@ -282,20 +283,8 @@
final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
- final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
- //TODO(b/178197718) Refine the layout
- controller.setSummary(TextUtils.expandTemplate(
- getText(R.string.battery_total_and_background_usage),
- StringUtil.formatElapsedTime(
- getContext(),
- totalTimeMs,
- /* withSeconds */ false,
- /* collapseTimeUnit */ false),
- StringUtil.formatElapsedTime(
- getContext(),
- backgroundTimeMs,
- /* withSeconds */ false,
- /* collapseTimeUnit */ false)));
+ //TODO(b/178197718) Update layout to support multiple lines
+ controller.setSummary(getAppActiveTime(foregroundTimeMs, backgroundTimeMs));
controller.done(context, true /* rebindActions */);
}
@@ -388,4 +377,53 @@
private void updatePreferenceState(RadioButtonPreference preference, String selectedKey) {
preference.setChecked(selectedKey.equals(preference.getKey()));
}
+
+ //TODO(b/178197718) Update method to support time period
+ private CharSequence getAppActiveTime(long foregroundTimeMs, long backgroundTimeMs) {
+ final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
+ final CharSequence usageTimeSummary;
+
+ if (totalTimeMs == 0) {
+ usageTimeSummary = getText(R.string.battery_not_usage);
+ // Shows background summary only if we don't have foreground usage time.
+ } else if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
+ usageTimeSummary = backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS ?
+ getText(R.string.battery_background_usage_less_minute) :
+ TextUtils.expandTemplate(getText(R.string.battery_background_usage),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ backgroundTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ // Shows total usage summary only if total usage time is small.
+ } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+ usageTimeSummary = getText(R.string.battery_total_usage_less_minute);
+ // Shows different total usage summary when background usage time is small.
+ } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+ usageTimeSummary = TextUtils.expandTemplate(
+ getText(backgroundTimeMs == 0 ?
+ R.string.battery_total_usage :
+ R.string.battery_total_usage_and_background_less_minute_usage),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ totalTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ // Shows default summary.
+ } else {
+ usageTimeSummary = TextUtils.expandTemplate(
+ getText(R.string.battery_total_and_background_usage),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ totalTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ backgroundTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ }
+ return usageTimeSummary;
+ }
}
diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
index f12de01..7131f28 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- *
*/
package com.android.settings.fuelgauge;
@@ -51,7 +50,7 @@
/** Controls the update for chart graph and the list items. */
public class BatteryChartPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy,
- BatteryChartView.OnSelectListener {
+ BatteryChartView.OnSelectListener, ExpandDividerPreference.OnExpandListener {
private static final String TAG = "BatteryChartPreferenceController";
private static final int CHART_KEY_ARRAY_SIZE = 25;
private static final int CHART_LEVEL_ARRAY_SIZE = 13;
@@ -65,6 +64,7 @@
@VisibleForTesting BatteryUtils mBatteryUtils;
@VisibleForTesting PreferenceGroup mAppListPrefGroup;
@VisibleForTesting BatteryChartView mBatteryChartView;
+ @VisibleForTesting ExpandDividerPreference mExpandDividerPreference;
@VisibleForTesting int[] mBatteryHistoryLevels;
@VisibleForTesting long[] mBatteryHistoryKeys;
@@ -76,9 +76,13 @@
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final CharSequence[] mNotAllowShowSummaryPackages;
+ private boolean mIsExpanded = false;
+
// Preference cache to avoid create new instance each time.
@VisibleForTesting
final Map<String, Preference> mPreferenceCache = new HashMap<>();
+ @VisibleForTesting
+ final List<BatteryDiffEntry> mSystemEntries = new ArrayList<>();
public BatteryChartPreferenceController(
Context context, String preferenceKey,
@@ -163,6 +167,12 @@
refreshUi(trapezoidIndex, /*isForce=*/ false);
}
+ @Override
+ public void onExpand(boolean isExpanded) {
+ mIsExpanded = isExpanded;
+ refreshExpandUi();
+ }
+
void setBatteryHistoryMap(
final Map<Long, List<BatteryHistEntry>> batteryHistoryMap) {
mHandler.post(() -> setBatteryHistoryMapInner(batteryHistoryMap));
@@ -266,10 +276,10 @@
}
// Separates data into two groups and sort them individually.
final List<BatteryDiffEntry> appEntries = new ArrayList<>();
- final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
+ mSystemEntries.clear();
entries.forEach(entry -> {
if (entry.isSystemEntry()) {
- systemEntries.add(entry);
+ mSystemEntries.add(entry);
} else {
appEntries.add(entry);
}
@@ -279,11 +289,25 @@
}
});
Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR);
- Collections.sort(systemEntries, BatteryDiffEntry.COMPARATOR);
+ Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
Log.d(TAG, String.format("addAllPreferences() app=%d system=%d",
- appEntries.size(), systemEntries.size()));
- addPreferenceToScreen(appEntries);
- addPreferenceToScreen(systemEntries);
+ appEntries.size(), mSystemEntries.size()));
+
+ // Adds app entries to the list if it is not empty.
+ if (!appEntries.isEmpty()) {
+ addPreferenceToScreen(appEntries);
+ }
+ // Adds the expabable divider if we have two sections data.
+ if (!appEntries.isEmpty() && !mSystemEntries.isEmpty()) {
+ if (mExpandDividerPreference == null) {
+ mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
+ mExpandDividerPreference.setOnExpandListener(this);
+ }
+ mExpandDividerPreference.setOrder(
+ mAppListPrefGroup.getPreferenceCount());
+ mAppListPrefGroup.addPreference(mExpandDividerPreference);
+ }
+ refreshExpandUi();
}
@VisibleForTesting
@@ -293,6 +317,7 @@
}
int prefIndex = mAppListPrefGroup.getPreferenceCount();
for (BatteryDiffEntry entry : entries) {
+ boolean isAdded = false;
final String appLabel = entry.getAppLabel();
final Drawable appIcon = entry.getAppIcon();
if (TextUtils.isEmpty(appLabel) || appIcon == null) {
@@ -300,8 +325,13 @@
continue;
}
final String prefKey = entry.mBatteryHistEntry.getKey();
- PowerGaugePreference pref =
- (PowerGaugePreference) mPreferenceCache.get(prefKey);
+ PowerGaugePreference pref = mAppListPrefGroup.findPreference(prefKey);
+ if (pref != null) {
+ isAdded = true;
+ Log.w(TAG, "preference should be removed for\n" + entry);
+ } else {
+ pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
+ }
// Creates new innstance if cached preference is not found.
if (pref == null) {
pref = new PowerGaugePreference(mPrefContext);
@@ -316,7 +346,9 @@
// Sets the BatteryDiffEntry to preference for launching detailed page.
pref.setBatteryDiffEntry(entry);
setPreferenceSummary(pref, entry);
- mAppListPrefGroup.addPreference(pref);
+ if (!isAdded) {
+ mAppListPrefGroup.addPreference(pref);
+ }
prefIndex++;
}
}
@@ -337,6 +369,22 @@
mAppListPrefGroup.removeAll();
}
+ private void refreshExpandUi() {
+ if (mIsExpanded) {
+ addPreferenceToScreen(mSystemEntries);
+ } else {
+ // Removes and recycles all system entries to hide all of them.
+ for (BatteryDiffEntry entry : mSystemEntries) {
+ final String prefKey = entry.mBatteryHistEntry.getKey();
+ final Preference pref = mAppListPrefGroup.findPreference(prefKey);
+ if (pref != null) {
+ mAppListPrefGroup.removePreference(pref);
+ mPreferenceCache.put(pref.getKey(), pref);
+ }
+ }
+ }
+ }
+
@VisibleForTesting
void setPreferenceSummary(
PowerGaugePreference preference, BatteryDiffEntry entry) {
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index 26eb3e4..f970072 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -97,8 +97,18 @@
public void setLevels(int[] levels) {
// We should provide trapezoid count + 1 data to draw all trapezoids.
mLevels = levels.length == mTrapezoidCount + 1 ? levels : null;
- setClickable(mLevels != null);
+ setClickable(false);
invalidate();
+ if (mLevels == null) {
+ return;
+ }
+ // Sets the chart is clickable if there is at least one valid item in it.
+ for (int index = 0; index < mLevels.length; index++) {
+ if (mLevels[index] != 0) {
+ setClickable(true);
+ break;
+ }
+ }
}
/** Sets the selected group index to draw highlight effect. */
diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java
index 30982da..2e8726e 100644
--- a/src/com/android/settings/fuelgauge/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/ConvertUtils.java
@@ -71,6 +71,7 @@
private static String sZoneId;
private static SimpleDateFormat sSimpleDateFormat;
+ private static SimpleDateFormat sSimpleDateFormatForHour;
private ConvertUtils() {}
@@ -139,10 +140,27 @@
sZoneId = currentZoneId;
sSimpleDateFormat =
new SimpleDateFormat("MMM dd,yyyy HH:mm:ss", Locale.ENGLISH);
+ sSimpleDateFormatForHour = null;
}
return sSimpleDateFormat.format(new Date(timestamp));
}
+ /** Converts UTC timestamp to local time hour data. */
+ public static int utcToLocalTimeHour(long timestamp) {
+ final String currentZoneId = TimeZone.getDefault().getID();
+ if (!currentZoneId.equals(sZoneId) || sSimpleDateFormatForHour == null) {
+ sZoneId = currentZoneId;
+ sSimpleDateFormat = null;
+ sSimpleDateFormatForHour = new SimpleDateFormat("HH", Locale.ENGLISH);
+ }
+ try {
+ return Integer.parseInt(
+ sSimpleDateFormatForHour.format(new Date(timestamp)));
+ } catch (NumberFormatException e) {
+ return Integer.MIN_VALUE;
+ }
+ }
+
/** Gets indexed battery usage data for each corresponding time slot. */
public static Map<Integer, List<BatteryDiffEntry>> getIndexedUsageMap(
final Context context,
diff --git a/src/com/android/settings/location/LocationPersonalSettings.java b/src/com/android/settings/location/LocationPersonalSettings.java
index 0553d96..ab392d6 100644
--- a/src/com/android/settings/location/LocationPersonalSettings.java
+++ b/src/com/android/settings/location/LocationPersonalSettings.java
@@ -51,7 +51,6 @@
use(AppLocationPermissionPreferenceController.class).init(this);
use(LocationSettingsFooterPreferenceController.class).init(this);
- use(RecentLocationAccessSeeAllButtonPreferenceController.class).init(this);
final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
final RecentLocationAccessPreferenceController controller = use(
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index fe3cf30..093dc85 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -83,7 +83,6 @@
use(AppLocationPermissionPreferenceController.class).init(this);
use(RecentLocationAccessPreferenceController.class).init(this);
- use(RecentLocationAccessSeeAllButtonPreferenceController.class).init(this);
use(LocationForWorkPreferenceController.class).init(this);
use(LocationSettingsFooterPreferenceController.class).init(this);
}
diff --git a/src/com/android/settings/location/LocationWorkProfileSettings.java b/src/com/android/settings/location/LocationWorkProfileSettings.java
index 24c44f3..f50ba90 100644
--- a/src/com/android/settings/location/LocationWorkProfileSettings.java
+++ b/src/com/android/settings/location/LocationWorkProfileSettings.java
@@ -51,7 +51,6 @@
use(AppLocationPermissionPreferenceController.class).init(this);
use(LocationForWorkPreferenceController.class).init(this);
- use(RecentLocationAccessSeeAllButtonPreferenceController.class).init(this);
use(LocationSettingsFooterPreferenceController.class).init(this);
final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java
deleted file mode 100644
index 68cde63..0000000
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 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.location;
-
-import android.content.Context;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-/**
- * Preference controller that handles the "See All" button for recent location access.
- */
-public class RecentLocationAccessSeeAllButtonPreferenceController extends
- LocationBasePreferenceController {
-
- private Preference mPreference;
-
- /**
- * Constructor of {@link RecentLocationAccessSeeAllButtonPreferenceController}.
- */
- public RecentLocationAccessSeeAllButtonPreferenceController(Context context, String key) {
- super(context, key);
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = screen.findPreference(getPreferenceKey());
- }
-
- @Override
- public void onLocationModeChanged(int mode, boolean restricted) {
- boolean enabled = mLocationEnabler.isEnabled(mode);
- mPreference.setVisible(enabled);
- }
-}
diff --git a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
index cf08d10..d336cb4 100644
--- a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
+++ b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
@@ -72,7 +72,7 @@
public int getAvailabilityStatus(int subId) {
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
boolean visible =
- subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ SubscriptionManager.isUsableSubscriptionId(subId)
&& carrierConfig != null
&& !carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G)
&& mTelephonyManager.isRadioInterfaceCapabilitySupported(
@@ -89,6 +89,9 @@
@Override
public boolean setChecked(boolean isChecked) {
+ if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
+ return false;
+ }
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
diff --git a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
index 6237326..a46f164 100644
--- a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
@@ -77,11 +77,7 @@
protected void setNotificationAssistantGranted(ComponentName cn) {
if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, mUserId) == 0) {
- for (int profileId : mUserManager.getProfileIds(mUserId, false)) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.NAS_SETTINGS_UPDATED, 1, profileId);
- }
- mNotificationBackend.resetDefaultNotificationAssistant(cn != null);
+ mNotificationBackend.setNASMigrationDoneAndResetDefault(mUserId, cn != null);
}
mNotificationBackend.setNotificationAssistantGranted(cn);
}
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index b08d02c..e448dda 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -570,9 +570,9 @@
}
}
- public void resetDefaultNotificationAssistant(boolean loadFromConfig) {
+ public void setNASMigrationDoneAndResetDefault(int userId, boolean loadFromConfig) {
try {
- sINM.resetDefaultNotificationAssistant(loadFromConfig);
+ sINM.setNASMigrationDoneAndResetDefault(userId, loadFromConfig);
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
}
diff --git a/src/com/android/settings/notification/app/NotificationFooterPreference.java b/src/com/android/settings/notification/app/NotificationFooterPreference.java
deleted file mode 100644
index 6f34cdd..0000000
--- a/src/com/android/settings/notification/app/NotificationFooterPreference.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 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.app;
-
-import android.content.Context;
-import android.text.method.LinkMovementMethod;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.core.content.res.TypedArrayUtils;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settingslib.R;
-
-/**
- * FooterPreference that can have any key or ordering.
- */
-public class NotificationFooterPreference extends Preference {
-
- public NotificationFooterPreference(Context context, AttributeSet attrs) {
- super(context, attrs, TypedArrayUtils.getAttr(
- context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
- init();
- }
-
- public NotificationFooterPreference(Context context) {
- this(context, null);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
- super.onBindViewHolder(holder);
- TextView title = holder.itemView.findViewById(android.R.id.title);
- title.setMovementMethod(new LinkMovementMethod());
- title.setClickable(false);
- title.setLongClickable(false);
- }
-
- private void init() {
- setIcon(R.drawable.ic_info_outline_24dp);
- setSelectable(false);
- }
-}
diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
index 577144f..01cdba7 100644
--- a/src/com/android/settings/security/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -22,6 +22,8 @@
import android.content.Intent;
import com.android.settings.R;
+import com.android.settings.biometrics.combination.CombinedBiometricProfileStatusPreferenceController;
+import com.android.settings.biometrics.combination.CombinedBiometricStatusPreferenceController;
import com.android.settings.biometrics.face.FaceProfileStatusPreferenceController;
import com.android.settings.biometrics.face.FaceStatusPreferenceController;
import com.android.settings.biometrics.fingerprint.FingerprintProfileStatusPreferenceController;
@@ -115,6 +117,7 @@
final List<AbstractPreferenceController> securityPreferenceControllers = new ArrayList<>();
securityPreferenceControllers.add(new FaceStatusPreferenceController(context));
securityPreferenceControllers.add(new FingerprintStatusPreferenceController(context));
+ securityPreferenceControllers.add(new CombinedBiometricStatusPreferenceController(context));
securityPreferenceControllers.add(new ChangeScreenLockPreferenceController(context, host));
controllers.add(new PreferenceCategoryController(context, SECURITY_CATEGORY)
.setChildren(securityPreferenceControllers));
@@ -128,6 +131,8 @@
context, lifecycle));
profileSecurityControllers.add(new FaceProfileStatusPreferenceController(context));
profileSecurityControllers.add(new FingerprintProfileStatusPreferenceController(context));
+ profileSecurityControllers
+ .add(new CombinedBiometricProfileStatusPreferenceController(context));
controllers.add(new PreferenceCategoryController(context, WORK_PROFILE_SECURITY_CATEGORY)
.setChildren(profileSecurityControllers));
controllers.addAll(profileSecurityControllers);
diff --git a/src/com/android/settings/uwb/UwbPreferenceController.java b/src/com/android/settings/uwb/UwbPreferenceController.java
new file mode 100644
index 0000000..daadb63
--- /dev/null
+++ b/src/com/android/settings/uwb/UwbPreferenceController.java
@@ -0,0 +1,168 @@
+/*
+ * 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.uwb;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.uwb.UwbManager;
+import android.uwb.UwbManager.AdapterStateCallback;
+
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/** Controller for "UWB" toggle. */
+public class UwbPreferenceController extends TogglePreferenceController implements
+ AdapterStateCallback, LifecycleObserver {
+ @VisibleForTesting
+ static final String KEY_UWB_SETTINGS = "uwb_settings";
+ @VisibleForTesting
+ UwbManager mUwbManager;
+ @VisibleForTesting
+ boolean mAirplaneModeOn;
+ @VisibleForTesting
+ private final BroadcastReceiver mAirplaneModeChangedReceiver;
+ private final Executor mExecutor;
+ private boolean mIsChecked = true;
+ boolean mRegisteredAdapterStateCallback = false;
+ private Preference mPreference;
+
+ public UwbPreferenceController(Context context, String key) {
+ super(context, key);
+ mExecutor = Executors.newSingleThreadExecutor();
+ mUwbManager = context.getSystemService(UwbManager.class);
+ mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+ mAirplaneModeChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateState(mPreference);
+ }
+ };
+ }
+
+ @VisibleForTesting
+ boolean isUwbSupportedOnDevice() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!isUwbSupportedOnDevice()) {
+ return UNSUPPORTED_ON_DEVICE;
+ } else if (mAirplaneModeOn) {
+ return DISABLED_DEPENDENT_SETTING;
+ } else {
+ return AVAILABLE;
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public boolean isChecked() {
+ //TODO(b/186075119): Update toggle state by assigning to the real value by default.
+ return mIsChecked;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ mIsChecked = isChecked;
+ mUwbManager.setUwbEnabled(isChecked);
+ return true;
+ }
+
+ @Override
+ public void onStateChanged(int state, int reason) {
+ // Only update toggle state from service the first time. Otherwise toggle state is
+ // changed from controller. For example, UWB is disabled if airplane mode is on but we do
+ // not want to change the preference for the user in this case.
+ if (!mRegisteredAdapterStateCallback) {
+ mIsChecked = state == STATE_ENABLED_ACTIVE || state == STATE_ENABLED_INACTIVE;
+ mRegisteredAdapterStateCallback = true;
+ }
+ }
+
+ /** Called when activity starts being displayed to user. */
+ @OnLifecycleEvent(ON_START)
+ public void onStart() {
+ if (isUwbSupportedOnDevice()) {
+ mUwbManager.registerAdapterStateCallback(mExecutor, this);
+ }
+ if (mAirplaneModeChangedReceiver != null) {
+ mContext.registerReceiver(mAirplaneModeChangedReceiver,
+ new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+ }
+ refreshSummary(mPreference);
+ }
+
+ /** Called when activity stops being displayed to user. */
+ @OnLifecycleEvent(ON_STOP)
+ public void onStop() {
+ if (isUwbSupportedOnDevice()) {
+ mUwbManager.unregisterAdapterStateCallback(this);
+ }
+ if (mAirplaneModeChangedReceiver != null) {
+ mContext.unregisterReceiver(mAirplaneModeChangedReceiver);
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+ preference.setEnabled(!mAirplaneModeOn);
+ if (isUwbSupportedOnDevice()) {
+ if (mAirplaneModeOn) {
+ mUwbManager.setUwbEnabled(false);
+ } else {
+ mUwbManager.setUwbEnabled(mIsChecked);
+ }
+ }
+ refreshSummary(preference);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ if (mAirplaneModeOn) {
+ return mContext.getResources().getString(R.string.uwb_settings_summary_airplane_mode);
+ } else {
+ return mContext.getResources().getString(R.string.uwb_settings_summary);
+ }
+ }
+}
+
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPermissionActivityTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPermissionActivityTest.java
new file mode 100644
index 0000000..35b8f1f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPermissionActivityTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.bluetooth;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothPermissionActivityTest {
+
+ private BluetoothPermissionActivity mActivity;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mActivity = new BluetoothPermissionActivity();
+ }
+
+ @Test
+ public void sendBroadcastWithPermission() {
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ ReflectionHelpers.setField(mActivity, "mBase", mContext);
+
+ mActivity.sendReplyIntentToReceiver(true, true);
+
+ verify(mContext).sendBroadcast(intentCaptor.capture(),
+ eq("android.permission.BLUETOOTH_ADMIN"));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java
index feaf683..d9e054d 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java
@@ -16,28 +16,43 @@
package com.android.settings.bluetooth;
+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.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class DevicePickerFragmentTest {
@Mock
private BluetoothProgressCategory mAvailableDevicesCategory;
+
private DevicePickerFragment mFragment;
+ private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFragment = new DevicePickerFragment();
-
+ mContext = spy(RuntimeEnvironment.application);
+ mFragment.mContext = mContext;
mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory;
}
@@ -49,4 +64,18 @@
verify(mAvailableDevicesCategory).setProgress(true);
}
+
+ @Test
+ public void sendBroadcastWithPermission() {
+ final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
+ final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ when(cachedDevice.getDevice()).thenReturn(bluetoothDevice);
+ mFragment.mSelectedDevice = bluetoothDevice;
+
+ mFragment.onDeviceBondStateChanged(cachedDevice, BluetoothDevice.BOND_BONDED);
+
+ verify(mContext).sendBroadcast(intentCaptor.capture(),
+ eq("android.permission.BLUETOOTH_ADMIN"));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java
deleted file mode 100644
index cf7e34f..0000000
--- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.display;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.hardware.display.ColorDisplayManager;
-
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class ColorModePreferenceControllerTest {
-
- @Mock
- private ColorDisplayManager mColorDisplayManager;
-
- private Context mContext;
- private Preference mPreference;
- private ColorModePreferenceController mController;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- mController = spy(new ColorModePreferenceController(mContext, "test"));
- mPreference = new Preference(mContext);
- doReturn(mColorDisplayManager).when(mController).getColorDisplayManager();
- }
-
- @Test
- public void updateState_colorModeAutomatic_shouldSetSummaryToAutomatic() {
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.getSummary())
- .isEqualTo(mContext.getText(R.string.color_mode_option_automatic));
- }
-
- @Test
- public void updateState_colorModeSaturated_shouldSetSummaryToSaturated() {
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.getSummary())
- .isEqualTo(mContext.getText(R.string.color_mode_option_saturated));
- }
-
- @Test
- public void updateState_colorModeBoosted_shouldSetSummaryToBoosted() {
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_BOOSTED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.getSummary())
- .isEqualTo(mContext.getText(R.string.color_mode_option_boosted));
- }
-
- @Test
- public void updateState_colorModeNatural_shouldSetSummaryToNatural() {
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.getSummary())
- .isEqualTo(mContext.getText(R.string.color_mode_option_natural));
- }
-}
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
deleted file mode 100644
index 54e8e4d..0000000
--- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.display;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doNothing;
-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.when;
-
-import android.hardware.display.ColorDisplayManager;
-import android.os.Bundle;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.R;
-import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settingslib.widget.CandidateInfo;
-import com.android.settingslib.widget.LayoutPreference;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = SettingsShadowResources.class)
-public class ColorModePreferenceFragmentTest {
-
- private ColorModePreferenceFragment mFragment;
-
- @Mock
- private ColorDisplayManager mManager;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
-
- mFragment = spy(new ColorModePreferenceFragment());
- ReflectionHelpers.setField(mFragment, "mColorDisplayManager", mManager);
- }
-
- @After
- public void tearDown() {
- SettingsShadowResources.reset();
- }
-
- @Test
- public void verifyMetricsConstant() {
- assertThat(mFragment.getMetricsCategory())
- .isEqualTo(MetricsProto.MetricsEvent.COLOR_MODE_SETTINGS);
- }
-
- @Test
- public void getCandidates_all() {
- when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
- SettingsShadowResources.overrideResource(
- com.android.internal.R.array.config_availableColorModes, new int[]{
- ColorDisplayManager.COLOR_MODE_NATURAL,
- ColorDisplayManager.COLOR_MODE_BOOSTED,
- ColorDisplayManager.COLOR_MODE_SATURATED,
- ColorDisplayManager.COLOR_MODE_AUTOMATIC
- });
- List<? extends CandidateInfo> candidates = mFragment.getCandidates();
-
- assertThat(candidates.size()).isEqualTo(4);
- assertThat(candidates.get(0).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
- assertThat(candidates.get(1).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
- assertThat(candidates.get(2).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
- assertThat(candidates.get(3).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_AUTOMATIC);
- }
-
- @Test
- public void getCandidates_none() {
- when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
- SettingsShadowResources.overrideResource(
- com.android.internal.R.array.config_availableColorModes, null);
- List<? extends CandidateInfo> candidates = mFragment.getCandidates();
-
- assertThat(candidates.size()).isEqualTo(0);
- }
-
- @Test
- public void getCandidates_withAutomatic() {
- when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
- SettingsShadowResources.overrideResource(
- com.android.internal.R.array.config_availableColorModes, new int[]{
- ColorDisplayManager.COLOR_MODE_NATURAL,
- ColorDisplayManager.COLOR_MODE_AUTOMATIC
- });
- List<? extends CandidateInfo> candidates = mFragment.getCandidates();
-
- assertThat(candidates.size()).isEqualTo(2);
- assertThat(candidates.get(0).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
- assertThat(candidates.get(1).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_AUTOMATIC);
- }
-
- @Test
- public void getCandidates_withoutAutomatic() {
- when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
- SettingsShadowResources.overrideResource(
- com.android.internal.R.array.config_availableColorModes, new int[]{
- ColorDisplayManager.COLOR_MODE_NATURAL,
- ColorDisplayManager.COLOR_MODE_BOOSTED,
- ColorDisplayManager.COLOR_MODE_SATURATED,
- });
- List<? extends CandidateInfo> candidates = mFragment.getCandidates();
-
- assertThat(candidates.size()).isEqualTo(3);
- assertThat(candidates.get(0).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
- assertThat(candidates.get(1).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
- assertThat(candidates.get(2).getKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
- }
-
- @Test
- public void getKey_natural() {
- when(mManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
-
- assertThat(mFragment.getDefaultKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
- }
-
- @Test
- public void getKey_boosted() {
- when(mManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_BOOSTED);
-
- assertThat(mFragment.getDefaultKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
- }
-
- @Test
- public void getKey_saturated() {
- when(mManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
-
- assertThat(mFragment.getDefaultKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
- }
-
- @Test
- public void getKey_automatic() {
- when(mManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
-
- assertThat(mFragment.getDefaultKey())
- .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_AUTOMATIC);
- }
-
- @Test
- public void setKey_natural() {
- mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
- verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
- }
-
- @Test
- public void setKey_boosted() {
- mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
- verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED);
- }
-
- @Test
- public void setKey_saturated() {
- mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
- verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED);
- }
-
- @Test
- public void setKey_automatic() {
- mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_AUTOMATIC);
- verify(mManager).setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
- }
-
- @Test
- public void onCreatePreferences_useNewTitle_shouldAddColorModePreferences() {
- when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
- doNothing().when(mFragment).addPreferencesFromResource(anyInt());
- doNothing().when(mFragment).updateCandidates();
-
- mFragment.onCreatePreferences(Bundle.EMPTY, null /* rootKey */);
-
- verify(mFragment).addPreferencesFromResource(R.xml.color_mode_settings);
- }
-
- @Test
- public void addStaticPreferences_shouldAddPreviewImage() {
- PreferenceScreen mockPreferenceScreen = mock(PreferenceScreen.class);
- LayoutPreference mockPreview = mock(LayoutPreference.class);
-
- ArgumentCaptor<Preference> preferenceCaptor = ArgumentCaptor.forClass(Preference.class);
-
- mFragment.configureAndInstallPreview(mockPreview, mockPreferenceScreen);
- verify(mockPreview, times(1)).setSelectable(false);
- verify(mockPreferenceScreen, times(1)).addPreference(preferenceCaptor.capture());
-
- assertThat(preferenceCaptor.getValue()).isEqualTo(mockPreview);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index a288c3a..dd10a9e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -249,14 +249,122 @@
}
@Test
- public void testInitHeader_hasCorrectSummary() {
- mFragment.mAppEntry = null;
+ public void testInitHeader_noUsageTime_hasCorrectSummary() {
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
- .isEqualTo("0 min total • 0 min background for past 24 hr");
+ .isEqualTo("No usage for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_backgroundTwoMinutesForegroundZero_hasCorrectSummary() {
+ final long backgroundTimeTwoMinutes = 120000;
+ final long foregroundTimeZero = 0;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("2 min background for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_backgroundLessThanAMinutesForegroundZero_hasCorrectSummary() {
+ final long backgroundTimeLessThanAMinute = 59999;
+ final long foregroundTimeZero = 0;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("Background less than a minute for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_totalUsageLessThanAMinutes_hasCorrectSummary() {
+ final long backgroundTimeLessThanHalfMinute = 20000;
+ final long foregroundTimeLessThanHalfMinute = 20000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("Total less than a minute for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_TotalAMinutesBackgroundLessThanAMinutes_hasCorrectSummary() {
+ final long backgroundTimeZero = 59999;
+ final long foregroundTimeTwoMinutes = 1;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("1 min total • background less than a minute for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_TotalAMinutesBackgroundZero_hasCorrectSummary() {
+ final long backgroundTimeZero = 0;
+ final long foregroundTimeAMinutes = 60000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("1 min total for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_foregroundTwoMinutesBackgroundFourMinutes_hasCorrectSummary() {
+ final long backgroundTimeFourMinute = 240000;
+ final long foregroundTimeTwoMinutes = 120000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("6 min total • 4 min background for past 24 hr");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
index c8bbba3..9f0ffb0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
@@ -43,6 +43,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -56,6 +57,8 @@
@RunWith(RobolectricTestRunner.class)
public final class BatteryChartPreferenceControllerTest {
+ private static final String PREF_KEY = "pref_key";
+ private static final String PREF_SUMMARY = "fake preference summary";
@Mock private InstrumentedPreferenceFragment mFragment;
@Mock private SettingsActivity mSettingsActivity;
@@ -119,10 +122,9 @@
@Test
public void testOnDestroy_clearPreferenceCache() {
- final String prefKey = "preference fake key";
// Ensures the testing environment is correct.
mBatteryChartPreferenceController.mPreferenceCache.put(
- prefKey, mPowerGaugePreference);
+ PREF_KEY, mPowerGaugePreference);
assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
mBatteryChartPreferenceController.onDestroy();
@@ -230,17 +232,16 @@
@Test
public void testRemoveAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
final int trapezoidIndex = 1;
- final String prefKey = "preference fake key";
doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
- doReturn(prefKey).when(mPowerGaugePreference).getKey();
+ doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
// Ensures the testing data is correct.
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
mBatteryChartPreferenceController.refreshUi(
trapezoidIndex, /*isForce=*/ true);
- assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(prefKey))
+ assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
.isEqualTo(mPowerGaugePreference);
verify(mAppListGroup).removeAll();
}
@@ -254,12 +255,12 @@
@Test
public void testAddPreferenceToScreen_addPreferenceIntoScreen() {
- final String prefKey = "preference fake key";
final String appLabel = "fake app label";
doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
- doReturn(prefKey).when(mBatteryHistEntry).getKey();
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(null).when(mAppListGroup).findPreference(PREF_KEY);
mBatteryChartPreferenceController.addPreferenceToScreen(
Arrays.asList(mBatteryDiffEntry));
@@ -267,11 +268,11 @@
// Verifies the preference cache.
final PowerGaugePreference pref =
(PowerGaugePreference) mBatteryChartPreferenceController.mPreferenceCache
- .get(prefKey);
+ .get(PREF_KEY);
assertThat(pref).isNotNull();
// Verifies the added preference configuration.
verify(mAppListGroup).addPreference(pref);
- assertThat(pref.getKey()).isEqualTo(prefKey);
+ assertThat(pref.getKey()).isEqualTo(PREF_KEY);
assertThat(pref.getTitle()).isEqualTo(appLabel);
assertThat(pref.getIcon()).isEqualTo(mDrawable);
assertThat(pref.getOrder()).isEqualTo(1);
@@ -280,6 +281,21 @@
}
@Test
+ public void testAddPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
+ final String appLabel = "fake app label";
+ doReturn(1).when(mAppListGroup).getPreferenceCount();
+ doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
+ doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
+
+ mBatteryChartPreferenceController.addPreferenceToScreen(
+ Arrays.asList(mBatteryDiffEntry));
+
+ verify(mAppListGroup, never()).addPreference(any());
+ }
+
+ @Test
public void testHandlePreferenceTreeClick_notPowerGaugePreference_returnFalse() {
assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup))
.isFalse();
@@ -309,7 +325,7 @@
@Test
public void testSetPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary("fake preference summary");
+ pref.setSummary(PREF_SUMMARY);
mBatteryChartPreferenceController.setPreferenceSummary(
pref, createBatteryDiffEntry(
@@ -321,7 +337,7 @@
@Test
public void testSetPreferenceSummary_setBackgroundUsageTimeOnly() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary("fake preference summary");
+ pref.setSummary(PREF_SUMMARY);
mBatteryChartPreferenceController.setPreferenceSummary(
pref, createBatteryDiffEntry(
@@ -333,7 +349,7 @@
@Test
public void testSetPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary("fake preference summary");
+ pref.setSummary(PREF_SUMMARY);
mBatteryChartPreferenceController.setPreferenceSummary(
pref, createBatteryDiffEntry(
@@ -345,7 +361,7 @@
@Test
public void testSetPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary("fake preference summary");
+ pref.setSummary(PREF_SUMMARY);
mBatteryChartPreferenceController.setPreferenceSummary(
pref, createBatteryDiffEntry(
@@ -357,7 +373,7 @@
@Test
public void testSetPreferenceSummary_setTotalAndBackgroundUsageTime() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary("fake preference summary");
+ pref.setSummary(PREF_SUMMARY);
mBatteryChartPreferenceController.setPreferenceSummary(
pref, createBatteryDiffEntry(
@@ -369,7 +385,7 @@
@Test
public void testSetPreferenceSummary_notAllowShownPackage_setSummayAsNull() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary("fake preference summary");
+ pref.setSummary(PREF_SUMMARY);
final BatteryDiffEntry batteryDiffEntry =
spy(createBatteryDiffEntry(
/*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
@@ -416,23 +432,54 @@
@Test
public void testValidateSlotTimestamp_returnExpectedResult() {
- final List<Long> slotTimestampList =
+ final ArrayList<Long> slotTimestampList = new ArrayList<Long>(
Arrays.asList(
Long.valueOf(0),
Long.valueOf(DateUtils.HOUR_IN_MILLIS),
Long.valueOf(DateUtils.HOUR_IN_MILLIS * 2 + DateUtils.MINUTE_IN_MILLIS),
- Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2));
+ Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2)));
// Verifies the testing data is correct before we added invalid data into it.
assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
.isTrue();
// Insert invalid timestamp into the list.
slotTimestampList.add(
- Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 3));
+ Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 6));
assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
.isFalse();
}
+ @Test
+ public void testOnExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
+ doReturn(1).when(mAppListGroup).getPreferenceCount();
+ mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ doReturn("label").when(mBatteryDiffEntry).getAppLabel();
+ doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+
+ mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ true);
+
+ final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
+ verify(mAppListGroup).addPreference(captor.capture());
+ // Verifies the added preference.
+ assertThat(captor.getValue().getKey()).isEqualTo(PREF_KEY);
+ }
+
+ @Test
+ public void testOnExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
+ mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ // Verifies the cache is empty first.
+ assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
+
+ mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ false);
+
+ verify(mAppListGroup).findPreference(PREF_KEY);
+ verify(mAppListGroup).removePreference(mPowerGaugePreference);
+ assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
+ }
+
private static Map<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) {
final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < size; index++) {
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
index f6b72d9..9b45a98 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
@@ -122,13 +122,13 @@
assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
//Test user enable again, migration should not happen
mPreferenceController.setNotificationAssistantGranted(mNASComponent);
//Number of invocations should not increase
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
}
@Test
@@ -146,13 +146,13 @@
assertEquals(0, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 20));
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
//Test user enable again, migration should not happen
mPreferenceController.setNotificationAssistantGranted(mNASComponent);
//Number of invocations should not increase
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
}
@Test
@@ -170,13 +170,13 @@
assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(false));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
//Test user disable again, migration should not happen
mPreferenceController.setChecked(false);
//Number of invocations should not increase
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(false));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
}
}
diff --git a/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
new file mode 100644
index 0000000..00dc4df
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.uwb;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.uwb.UwbManager;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+/** Unit tests for UWB preference toggle. */
+@RunWith(RobolectricTestRunner.class)
+public class UwbPreferenceControllerTest {
+ @Rule
+ public MockitoRule rule = MockitoJUnit.rule();
+
+ private Context mContext;
+ private PackageManager mPackageManager;
+ private UwbPreferenceController mController;
+
+ @Mock
+ private UwbManager mUwbManager;
+
+ @Before
+ public void setUp() {
+ mContext = spy(RuntimeEnvironment.application);
+ mPackageManager = spy(mContext.getPackageManager());
+ mController = new UwbPreferenceController(mContext, "uwb_settings");
+ mController.mUwbManager = mUwbManager;
+ }
+
+ @Test
+ public void getAvailabilityStatus_uwbDisabled_shouldReturnDisabled() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mAirplaneModeOn = true;
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void getAvailabilityStatus_uwbShown_shouldReturnAvailable() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mAirplaneModeOn = false;
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_uwbNotShown_shouldReturnUnsupported() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(false).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void onStateChanged_stateNotRegistered_shouldUpdate() {
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void onStateChanged_stateRegistered_shouldNotUpdate() {
+ mController.mRegisteredAdapterStateCallback = true;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_uwbEnabledInactive_shouldReturnTrue() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_uwbEnabledActive_shouldReturnTrue() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_uwbDisabled_shouldReturnFalse() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void setChecked_uwbDisabled_shouldEnableUwb() {
+ clearInvocations(mUwbManager);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+ mController.setChecked(true);
+
+ verify(mUwbManager).setUwbEnabled(true);
+ verify(mUwbManager, never()).setUwbEnabled(false);
+ }
+
+ @Test
+ public void setChecked_uwbEnabled_shouldDisableUwb() {
+ clearInvocations(mUwbManager);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+ mController.setChecked(false);
+
+ verify(mUwbManager).setUwbEnabled(false);
+ verify(mUwbManager, never()).setUwbEnabled(true);
+ }
+}
+
diff --git a/tests/unit/src/com/android/settings/display/ColorModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/display/ColorModePreferenceControllerTest.java
new file mode 100644
index 0000000..e2f77fd
--- /dev/null
+++ b/tests/unit/src/com/android/settings/display/ColorModePreferenceControllerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.display;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.display.ColorDisplayManager;
+
+import androidx.preference.Preference;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class ColorModePreferenceControllerTest {
+
+ private Preference mPreference;
+ private ColorModePreferenceController mController;
+
+ @Before
+ public void setup() {
+ final Context context = spy(ApplicationProvider.getApplicationContext());
+ mController = spy(new ColorModePreferenceController(context, "test"));
+ mPreference = new Preference(context);
+ final Resources res = spy(context.getResources());
+ when(res.getIntArray(com.android.internal.R.array.config_availableColorModes)).thenReturn(
+ new int[]{
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ ColorDisplayManager.COLOR_MODE_BOOSTED,
+ ColorDisplayManager.COLOR_MODE_SATURATED,
+ ColorDisplayManager.COLOR_MODE_AUTOMATIC
+ });
+ doReturn(res).when(context).getResources();
+ }
+
+ @Test
+ @UiThreadTest
+ public void updateState_colorModeAutomatic_shouldSetSummaryToAutomatic() {
+ doReturn(ColorDisplayManager.COLOR_MODE_AUTOMATIC).when(mController).getColorMode();
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo("Adaptive");
+ }
+
+ @Test
+ @UiThreadTest
+ public void updateState_colorModeSaturated_shouldSetSummaryToSaturated() {
+ doReturn(ColorDisplayManager.COLOR_MODE_SATURATED).when(mController).getColorMode();
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo("Saturated");
+ }
+
+ @Test
+ public void updateState_colorModeBoosted_shouldSetSummaryToBoosted() {
+ doReturn(ColorDisplayManager.COLOR_MODE_BOOSTED).when(mController).getColorMode();
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo("Boosted");
+ }
+
+ @Test
+ public void updateState_colorModeNatural_shouldSetSummaryToNatural() {
+ doReturn(ColorDisplayManager.COLOR_MODE_NATURAL).when(mController).getColorMode();
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo("Natural");
+ }
+}
diff --git a/tests/unit/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/unit/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
new file mode 100644
index 0000000..cfdedc7
--- /dev/null
+++ b/tests/unit/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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.display;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+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.res.Resources;
+import android.hardware.display.ColorDisplayManager;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.widget.CandidateInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class ColorModePreferenceFragmentTest {
+
+ private ColorModePreferenceFragment mFragment;
+
+ private Context mContext;
+
+ @Before
+ @UiThreadTest
+ public void setup() {
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mFragment = spy(new ColorModePreferenceFragment());
+ doNothing().when(mFragment).setColorMode(anyInt());
+ }
+
+ @Test
+ public void verifyMetricsConstant() {
+ assertThat(mFragment.getMetricsCategory())
+ .isEqualTo(MetricsProto.MetricsEvent.COLOR_MODE_SETTINGS);
+ }
+
+ @Test
+ @UiThreadTest
+ public void getCandidates_all() {
+ final Resources res = spy(mContext.getResources());
+ when(res.getIntArray(com.android.internal.R.array.config_availableColorModes)).thenReturn(
+ new int[]{
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ ColorDisplayManager.COLOR_MODE_BOOSTED,
+ ColorDisplayManager.COLOR_MODE_SATURATED,
+ ColorDisplayManager.COLOR_MODE_AUTOMATIC
+ });
+ doReturn(res).when(mContext).getResources();
+ mFragment.onAttach(mContext);
+
+ final List<? extends CandidateInfo> candidates = mFragment.getCandidates();
+
+ assertThat(candidates.size()).isEqualTo(4);
+ assertThat(candidates.get(0).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_NATURAL));
+ assertThat(candidates.get(1).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED));
+ assertThat(candidates.get(2).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_SATURATED));
+ assertThat(candidates.get(3).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC));
+ }
+
+ @Test
+ @UiThreadTest
+ public void getCandidates_none() {
+ final Resources res = spy(mContext.getResources());
+ when(res.getIntArray(com.android.internal.R.array.config_availableColorModes)).thenReturn(
+ new int[]{
+ });
+ doReturn(res).when(mContext).getResources();
+ mFragment.onAttach(mContext);
+
+ List<? extends CandidateInfo> candidates = mFragment.getCandidates();
+
+ assertThat(candidates.size()).isEqualTo(0);
+ }
+
+ @Test
+ @UiThreadTest
+ public void getCandidates_withAutomatic() {
+ final Resources res = spy(mContext.getResources());
+ when(res.getIntArray(com.android.internal.R.array.config_availableColorModes)).thenReturn(
+ new int[]{
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ ColorDisplayManager.COLOR_MODE_AUTOMATIC
+ });
+ doReturn(res).when(mContext).getResources();
+ mFragment.onAttach(mContext);
+
+ List<? extends CandidateInfo> candidates = mFragment.getCandidates();
+
+ assertThat(candidates.size()).isEqualTo(2);
+ assertThat(candidates.get(0).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_NATURAL));
+ assertThat(candidates.get(1).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC));
+ }
+
+ @Test
+ @UiThreadTest
+ public void getCandidates_withoutAutomatic() {
+ final Resources res = spy(mContext.getResources());
+ when(res.getIntArray(com.android.internal.R.array.config_availableColorModes)).thenReturn(
+ new int[]{
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ ColorDisplayManager.COLOR_MODE_BOOSTED,
+ ColorDisplayManager.COLOR_MODE_SATURATED
+ });
+ doReturn(res).when(mContext).getResources();
+ mFragment.onAttach(mContext);
+
+ List<? extends CandidateInfo> candidates = mFragment.getCandidates();
+
+ assertThat(candidates.size()).isEqualTo(3);
+ assertThat(candidates.get(0).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_NATURAL));
+ assertThat(candidates.get(1).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED));
+ assertThat(candidates.get(2).getKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_SATURATED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void getKey_natural() {
+ doReturn(ColorDisplayManager.COLOR_MODE_NATURAL).when(mFragment).getColorMode();
+ mFragment.onAttach(mContext);
+
+ assertThat(mFragment.getDefaultKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_NATURAL));
+ }
+
+ @Test
+ @UiThreadTest
+ public void getKey_boosted() {
+ doReturn(ColorDisplayManager.COLOR_MODE_BOOSTED).when(mFragment).getColorMode();
+ mFragment.onAttach(mContext);
+
+ assertThat(mFragment.getDefaultKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void getKey_saturated() {
+ doReturn(ColorDisplayManager.COLOR_MODE_SATURATED).when(mFragment).getColorMode();
+ mFragment.onAttach(mContext);
+
+ assertThat(mFragment.getDefaultKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_SATURATED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void getKey_automatic() {
+ doReturn(ColorDisplayManager.COLOR_MODE_AUTOMATIC).when(mFragment).getColorMode();
+ mFragment.onAttach(mContext);
+
+ assertThat(mFragment.getDefaultKey())
+ .isEqualTo(mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC));
+ }
+
+ @Test
+ @UiThreadTest
+ public void setKey_natural() {
+ mFragment.onAttach(mContext);
+
+ mFragment.setDefaultKey(
+ mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_NATURAL));
+
+ verify(mFragment).setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
+ }
+
+ @Test
+ @UiThreadTest
+ public void setKey_boosted() {
+ mFragment.onAttach(mContext);
+
+ mFragment.setDefaultKey(
+ mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED));
+
+ verify(mFragment).setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED);
+ }
+
+ @Test
+ @UiThreadTest
+ public void setKey_saturated() {
+ mFragment.onAttach(mContext);
+
+ mFragment.setDefaultKey(
+ mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_SATURATED));
+
+ verify(mFragment).setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED);
+ }
+
+ @Test
+ @UiThreadTest
+ public void setKey_automatic() {
+ mFragment.onAttach(mContext);
+
+ mFragment.setDefaultKey(
+ mFragment.getKeyForColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC));
+
+ verify(mFragment).setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
index 293a19d..5ade979 100644
--- a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
@@ -48,6 +48,8 @@
@Mock
private TelephonyManager mTelephonyManager;
@Mock
+ private TelephonyManager mInvalidTelephonyManager;
+ @Mock
private CarrierConfigManager mCarrierConfigManager;
private PersistableBundle mPersistableBundle;
@@ -65,6 +67,8 @@
.thenReturn(mCarrierConfigManager);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+ doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mPersistableBundle = new PersistableBundle();
doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
@@ -121,6 +125,18 @@
}
@Test
+ public void setChecked_invalidSubIdAndIsCheckedTrue_returnFalse() {
+ mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ assertThat(mController.setChecked(true)).isFalse();
+ }
+
+ @Test
+ public void setChecked_invalidSubIdAndIsCheckedFalse_returnFalse() {
+ mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ assertThat(mController.setChecked(false)).isFalse();
+ }
+
+ @Test
public void onPreferenceChange_update() {
// Set "Enable 2G" flag to "on"
when(mTelephonyManager.getAllowedNetworkTypesForReason(