Merge "Rearrange Settings dependencies" into main
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 29d9d39..06e0143 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4986,6 +4986,10 @@
</intent-filter>
</provider>
+ <activity android:name=".privatespace.PrivateSpaceAuthenticationActivity"
+ android:theme="@*android:style/Theme.DeviceDefault.Settings.Dialog.NoActionBar"
+ android:exported="false"/>
+
<activity-alias android:name="UsageStatsActivity"
android:exported="true"
android:label="@string/testing_usage_stats"
diff --git a/aconfig/OWNERS b/aconfig/OWNERS
new file mode 100644
index 0000000..1131545
--- /dev/null
+++ b/aconfig/OWNERS
@@ -0,0 +1 @@
+per-file settings_accessibility_flag_declarations.aconfig = file:/src/com/android/settings/accessibility/OWNERS
diff --git a/aconfig/settings_accessibility_flag_declarations.aconfig b/aconfig/settings_accessibility_flag_declarations.aconfig
index 9a24399..4363bfc 100644
--- a/aconfig/settings_accessibility_flag_declarations.aconfig
+++ b/aconfig/settings_accessibility_flag_declarations.aconfig
@@ -1,8 +1,21 @@
package: "com.android.settings.flags"
+# NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors.
+
+# NOTE: All Settings flags share the same Flags class, so prefix our
+# flags with 'accessibility' to prevent naming collision.
+
+flag {
+ name: "accessibility_show_app_info_button"
+ namespace: "accessibility"
+ description: "Shows an 'app info' button on non-framework a11y Service and Activity pages."
+ bug: "277378550"
+}
+
flag {
name: "separate_accessibility_vibration_settings_fragments"
namespace: "accessibility"
description: "Splits VibrationSettings into two fragments, one per XML resource"
bug: "289967175"
}
+
diff --git a/res/drawable/ic_bt_audio_sharing.xml b/res/drawable/ic_bt_audio_sharing.xml
new file mode 100644
index 0000000..6186773
--- /dev/null
+++ b/res/drawable/ic_bt_audio_sharing.xml
@@ -0,0 +1,87 @@
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#000000"
+ android:pathData="M16.984,24H7.279L12.131,15.508L16.984,24ZM10.481,22.144H13.781L12.131,19.257L10.481,22.144Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M12.131,14.295C13.471,14.295 14.558,13.209 14.558,11.869C14.558,10.529 13.471,9.442 12.131,9.442C10.791,9.442 9.705,10.529 9.705,11.869C9.705,13.209 10.791,14.295 12.131,14.295Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M4.573,21.368C4.052,20.943 3.967,20.179 4.379,19.657C4.804,19.136 5.568,19.051 6.09,19.463C6.611,19.876 6.696,20.64 6.284,21.174C6.041,21.465 5.689,21.623 5.338,21.623C5.071,21.623 4.804,21.538 4.573,21.368Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M17.991,21.162C17.579,20.628 17.663,19.876 18.185,19.451C18.707,19.039 19.471,19.124 19.896,19.646C20.308,20.167 20.223,20.931 19.702,21.344C19.471,21.526 19.204,21.611 18.949,21.611C18.586,21.611 18.234,21.453 17.991,21.162Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M1.213,17.145C0.91,16.551 1.165,15.823 1.771,15.532C2.378,15.241 3.093,15.495 3.397,16.09C3.688,16.697 3.433,17.424 2.827,17.715C2.657,17.8 2.475,17.837 2.305,17.837C1.844,17.837 1.419,17.582 1.213,17.145Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M21.449,17.691C20.842,17.4 20.588,16.684 20.879,16.077C21.17,15.471 21.898,15.216 22.504,15.507C23.099,15.798 23.354,16.526 23.062,17.133C22.856,17.557 22.419,17.812 21.971,17.812C21.789,17.812 21.619,17.776 21.449,17.691Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M0,11.892C0,11.225 0.546,10.679 1.213,10.679C1.88,10.679 2.426,11.212 2.426,11.892C2.426,12.559 1.88,13.105 1.213,13.105C0.546,13.105 0,12.559 0,11.892Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M21.837,11.869C21.837,11.857 21.837,11.845 21.837,11.833C21.824,11.153 22.37,10.62 23.05,10.607C23.717,10.607 24.251,11.153 24.263,11.821C24.263,11.833 24.263,11.845 24.263,11.845C24.263,11.857 24.263,11.869 24.263,11.869C24.263,12.536 23.717,13.082 23.05,13.082C22.382,13.082 21.837,12.536 21.837,11.869Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M1.759,8.242C1.152,7.963 0.898,7.235 1.189,6.628C1.48,6.022 2.196,5.767 2.802,6.058C3.409,6.349 3.664,7.077 3.372,7.684C3.166,8.108 2.729,8.363 2.281,8.363C2.099,8.363 1.929,8.327 1.759,8.242Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M20.866,7.622C20.563,7.028 20.818,6.3 21.424,6.009C22.019,5.706 22.747,5.96 23.038,6.567C23.038,6.567 23.038,6.567 23.05,6.567C23.341,7.161 23.087,7.889 22.48,8.181C22.31,8.265 22.128,8.302 21.958,8.302C21.509,8.302 21.073,8.059 20.866,7.622Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M4.355,4.104C3.931,3.582 4.016,2.818 4.537,2.406C5.071,1.981 5.823,2.066 6.248,2.588C6.672,3.109 6.588,3.874 6.066,4.298C5.835,4.48 5.569,4.565 5.302,4.565C4.95,4.565 4.598,4.407 4.355,4.104Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M18.161,4.262C17.627,3.838 17.542,3.073 17.955,2.552C18.379,2.03 19.132,1.945 19.666,2.358C20.187,2.77 20.272,3.534 19.86,4.068C19.617,4.359 19.265,4.517 18.913,4.517C18.646,4.517 18.379,4.432 18.161,4.262Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M8.492,1.497C8.334,0.854 8.747,0.199 9.402,0.041C10.057,-0.105 10.7,0.308 10.858,0.963C11.003,1.606 10.591,2.261 9.948,2.407C9.851,2.431 9.754,2.443 9.669,2.443C9.123,2.443 8.613,2.067 8.492,1.497Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M14.267,2.395C13.599,2.249 13.199,1.606 13.345,0.951C13.49,0.296 14.133,-0.116 14.788,0.029C15.443,0.175 15.856,0.83 15.71,1.485C15.589,2.043 15.08,2.431 14.534,2.431C14.437,2.431 14.352,2.419 14.267,2.395Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M7,17.037C6.527,16.564 6.527,15.8 7,15.326C7.473,14.841 8.237,14.841 8.71,15.314C9.196,15.787 9.196,16.552 8.723,17.025C8.48,17.267 8.177,17.389 7.861,17.389C7.546,17.389 7.242,17.267 7,17.037Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M15.565,17.012C15.092,16.539 15.092,15.762 15.565,15.289C16.038,14.816 16.814,14.816 17.288,15.289C17.761,15.762 17.761,16.539 17.288,17.012C17.045,17.243 16.742,17.364 16.426,17.364C16.111,17.364 15.807,17.243 15.565,17.012Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M4.853,11.917C4.853,11.237 5.386,10.691 6.054,10.691C6.721,10.691 7.279,11.225 7.279,11.892C7.279,12.56 6.745,13.106 6.078,13.118C5.398,13.118 4.853,12.584 4.853,11.917Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M16.984,11.868C16.984,11.856 16.984,11.844 16.984,11.832C16.984,11.832 16.984,11.82 16.984,11.807C16.972,11.14 17.506,10.582 18.185,10.582C18.852,10.57 19.398,11.116 19.41,11.783C19.41,11.795 19.41,11.82 19.41,11.832C19.41,11.844 19.41,11.856 19.41,11.868C19.41,12.535 18.865,13.081 18.197,13.081C17.53,13.081 16.984,12.535 16.984,11.868Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M6.952,8.471C6.478,7.997 6.478,7.233 6.952,6.76C6.952,6.76 6.952,6.76 6.939,6.76C7.413,6.275 8.189,6.275 8.662,6.748C9.135,7.221 9.147,7.985 8.674,8.458C8.432,8.701 8.116,8.822 7.813,8.822C7.497,8.822 7.194,8.701 6.952,8.471Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M15.529,8.399C15.043,7.938 15.043,7.161 15.504,6.688C15.977,6.203 16.742,6.203 17.227,6.664C17.7,7.137 17.712,7.901 17.239,8.387C17.009,8.629 16.693,8.751 16.378,8.751C16.075,8.751 15.759,8.629 15.529,8.399Z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M10.87,5.815C10.858,5.148 11.392,4.59 12.071,4.59C12.738,4.578 13.284,5.124 13.284,5.791C13.296,6.458 12.762,7.016 12.083,7.016C11.416,7.016 10.87,6.483 10.87,5.815Z"/>
+</vector>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a2bb40e..c908152 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -288,6 +288,11 @@
<!-- Name shown in the title of individual stylus preference in the connected devices page [CHAR LIMIT=60] -->
<string name="stylus_connected_devices_title">Stylus</string>
+ <!-- Title for audio sharing page [CHAR LIMIT=none]-->
+ <string name="audio_sharing_title">Audio sharing</string>
+ <!-- Title for audio sharing primary switch [CHAR LIMIT=none]-->
+ <string name="audio_sharing_switch_title">Share audio</string>
+
<!-- Date & time settings screen title -->
<string name="date_and_time">Date & time</string>
@@ -782,7 +787,7 @@
<string name="security_settings_face_settings_remove_face_model">Delete face model</string>
<!-- Button text in face settings which lets the user enroll their face [CHAR LIMIT=40] -->
<string name="security_settings_face_settings_enroll">Set up Face Unlock</string>
- <!-- Dialog title shown when the user removes an enrollment [CHAR LIMIT=35] -->
+ <!-- Dialog title shown when the user removes an enrollment [CHAR LIMIT=35] -->
<string name="security_settings_face_settings_remove_dialog_title">Delete face model?</string>
<!-- Dialog contents shown when the user removes an enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_remove_dialog_details">Your face model will be permanently and securely deleted.\n\nAfter deletion, you will need your PIN, pattern, or password to unlock your phone or for authentication in apps.</string>
@@ -866,7 +871,7 @@
<string name="biometric_settings_intro_with_activeunlock">When you set up Face Unlock and Fingerprint Unlock, your phone will ask for your fingerprint when you wear a mask or are in a dark area.\n\nYou can unlock with your watch when your face or fingerprint isn\u2019t recognized.</string>
<!-- Introduction shown in fingerprint page to explain that watch unlock can be used if fingerprint isn't recognized. [CHAR LIMIT=NONE]-->
<string name="biometric_settings_intro_with_fingerprint">You can unlock with your watch when your fingerprint isn\u2019t recognized.</string>
- <!-- Introduction shown in face page to explain that watch unlock can be used if face isn't recognized. [CHAR LIMIT=NONE]-->
+ <!-- Introduction shown in face page to explain that watch unlock can be used if face isn't recognized. [CHAR LIMIT=NONE]-->
<string name="biometric_settings_intro_with_face">You can unlock with your watch when your face isn\u2019t recognized.</string>
<string name="biometric_settings_use_fingerprint_or_watch_for"> Use fingerprint or watch to</string>
<string name="biometric_settings_use_face_or_watch_for"> Use face or watch to</string>
@@ -1210,6 +1215,14 @@
<string name="private_space_deleted">Private Space successfully deleted</string>
<!-- Toast to show when the private space could not be deleted. [CHAR LIMIT=NONE] -->
<string name="private_space_delete_failed">Private Space could not be deleted</string>
+ <!-- Title of the Alert Dialog when no screen lock is set [CHAR LIMIT=30] -->
+ <string name="no_device_lock_title">Set a screen lock</string>
+ <!-- Summary of the alert when no screen lock is set [CHAR LIMIT=60] -->
+ <string name="no_device_lock_summary">To use Private Space, set a screen lock on this device.</string>
+ <!-- Action label for dialog when no screen lock is set [CHAR LIMIT=30] -->
+ <string name="no_device_lock_action_label">Set screen lock</string>
+ <!-- Action label to cancel Alert dialog when no screen lock is set [CHAR LIMIT=30] -->
+ <string name="no_device_lock_cancel">Cancel</string>
<!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
@@ -2001,7 +2014,7 @@
<string name="wifi_dpp_connect_network_using_qr_code">Use a QR code to add a device to this network</string>
<!-- Hint for QR code process failure [CHAR LIMIT=NONE] -->
<string name="wifi_dpp_qr_code_is_not_valid_format">QR code isn\u0027t a valid format</string>
- <!-- Label for the try again button [CHAR LIMIT=20]-->
+ <!-- Label for the try again button [CHAR LIMIT=20]-->
<string name="retry">Retry</string>
<!-- Label for the check box to share a network with other users on the same device -->
<string name="wifi_shared">Share with other device users</string>
@@ -2569,7 +2582,7 @@
<string name="night_display_temperature_title">Intensity</string>
<!-- Display settings screen, summary of night display when off and will *never* turn on automatically. [CHAR LIMIT=NONE] -->
<string name="night_display_summary_off_auto_mode_never">Will never turn on automatically</string>
- <!-- Display settings screen, summary format of night display when off and will turn on automatically at a user defined time. [CHAR LIMIT=NONE] -->
+ <!-- Display settings screen, summary format of night display when off and will turn on automatically at a user defined time. [CHAR LIMIT=NONE] -->
<string name="night_display_summary_off_auto_mode_custom">Will turn on automatically at <xliff:g name="time" example="6 AM">%1$s</xliff:g></string>
<!-- Display settings screen, summary of night display when off and will turn on automatically at sunset. [CHAR LIMIT=NONE] -->
<string name="night_display_summary_off_auto_mode_twilight">Will turn on automatically at sunset</string>
@@ -2615,7 +2628,7 @@
<string name="dark_ui_summary_off_auto_mode_never">Will never turn on automatically</string>
<!-- Display settings screen, summary of Dark UI when off and will turn on automatically at sunset. [CHAR LIMIT=NONE] -->
<string name="dark_ui_summary_off_auto_mode_auto">Will turn on automatically at sunset</string>
- <!-- Display settings screen, summary format of night display when off and will turn on automatically at a user defined time. [CHAR LIMIT=NONE] -->
+ <!-- Display settings screen, summary format of night display when off and will turn on automatically at a user defined time. [CHAR LIMIT=NONE] -->
<string name="dark_ui_summary_off_auto_mode_custom">Will turn on automatically at <xliff:g name="time" example="6 AM">%1$s</xliff:g></string>
<!-- Display settings screen, summary of Dark UI when off and will turn on automatically at bedtime. [CHAR LIMIT=NONE] -->
<string name="dark_ui_summary_off_auto_mode_custom_bedtime">Will turn on automatically at bedtime</string>
@@ -2977,8 +2990,8 @@
<!-- Body of dialog informing user about the storage used by the Android System [CHAR LIMIT=NONE]-->
<string name="storage_detail_dialog_system">System includes files used to run Android version <xliff:g id="version" example="8.0">%s</xliff:g></string>
- <!-- Message to notify guest users as to why they can't set up the storage device [CHAR LIMIT=50]-->
- <string name="storage_wizard_guest">Guest mode users cannot format SD cards</string>
+ <!-- Message to notify guest users as to why they can't set up the storage device [CHAR LIMIT=50]-->
+ <string name="storage_wizard_guest">Guest mode users cannot format SD cards</string>
<!-- In-progress title. This string lets the user know the SD card is being formatted. The user won't be able to proceed with setup until this step is finished. The placeholder is for the name of the device (e.g. brand name of the SD card). [CHAR LIMIT=32] -->
<string name="storage_wizard_format_progress_title">Formatting <xliff:g id="name" example="SD card">^1</xliff:g>\u2026</string>
@@ -3023,7 +3036,7 @@
<!-- Body of a dialog. This text is confirming that the user wants to use their SD card as extra phone storage, but the formatting process will erase existing content on the card. The first placeholder is for the name of the device (e.g. a brand name of the SD card or USB drive). The second and third placeholders are for the general references (e.g. SD card, USB drive). [CHAR LIMIT=NONE] -->
<string name="storage_wizard_format_confirm_v2_body">This <xliff:g id="name" example="SanDisk SD card">^1</xliff:g> needs to be formatted to store apps, files, and media.
\n\nFormatting will erase existing content on the <xliff:g id="name" example="SD card">^2</xliff:g>. To avoid losing content, back it up to another <xliff:g id="name" example="SD card">^3</xliff:g> or device.</string>
- <!-- Body of a dialog. This text is confirming that the user wants to use their SD card as portable storage, but the formatting process will erase existing content on the card. The first placeholder is for the name of the device (e.g. a brand name of the SD card or USB drive). The second and third placeholders are for the general references (e.g. SD card, USB drive). [CHAR LIMIT=NONE] -->
+ <!-- Body of a dialog. This text is confirming that the user wants to use their SD card as portable storage, but the formatting process will erase existing content on the card. The first placeholder is for the name of the device (e.g. a brand name of the SD card or USB drive). The second and third placeholders are for the general references (e.g. SD card, USB drive). [CHAR LIMIT=NONE] -->
<string name="storage_wizard_format_confirm_v2_body_external">This <xliff:g id="name" example="SanDisk SD card">^1</xliff:g> needs to be formatted to store photos, videos, music, and more.
\n\nFormatting will erase existing content on the <xliff:g id="name" example="SD card">^2</xliff:g>. To avoid losing content, back it up to another <xliff:g id="name" example="SD card">^3</xliff:g> or device.</string>
<!-- Button text. If a user taps this button, their SD card or USB device will be formatted and used as extra phone storage. The placeholder is for the specific device (e.g. SD card, USB drive, etc.). [CHAR LIMIT=16] -->
@@ -6908,6 +6921,8 @@
<string name="help_url_insecure_vpn" translatable="false"></string>
<!-- url for learning more about IT admin policy disabling -->
<string name="help_url_action_disabled_by_it_admin" translatable="false"></string>
+ <!-- url for learning more about bluetooth audio sharing -->
+ <string name="help_url_audio_sharing" translatable="false"></string>
<!-- User account title [CHAR LIMIT=30] -->
<string name="user_account_title">Account for content</string>
@@ -7839,7 +7854,7 @@
<string name="notification_history_off_title_extended">Notification history turned off</string>
<!-- Notification history screen; summary when history is off [CHAR LIMIT=NONE] -->
- <string name="notification_history_off_summary">Turn on notification history to see recent notifications and snoozed notifications</string>
+ <string name="notification_history_off_summary">Turn on notification history to see recent notifications and snoozed notifications</string>
<!-- Notification history screen; title when history is newly turned on [CHAR LIMIT=200] -->
<string name="history_toggled_on_title">No recent notifications</string>
diff --git a/res/xml/bluetooth_audio_sharing.xml b/res/xml/bluetooth_audio_sharing.xml
new file mode 100644
index 0000000..a90da72
--- /dev/null
+++ b/res/xml/bluetooth_audio_sharing.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/audio_sharing_title">
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 11e3288..a1eae91 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -27,6 +27,13 @@
android:order="-9"/>
<Preference
+ android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment"
+ android:key="audio_sharing_settings"
+ android:title="@string/audio_sharing_title"
+ android:icon="@drawable/ic_bt_audio_sharing"
+ settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingPreferenceController"/>
+
+ <Preference
android:fragment="com.android.settings.connecteddevice.NfcAndPaymentFragment"
android:key="nfc_and_payment_settings"
android:title="@string/nfc_quick_toggle_title"
diff --git a/res/xml/private_space_settings.xml b/res/xml/private_space_settings.xml
index 08053e0..0277254 100644
--- a/res/xml/private_space_settings.xml
+++ b/res/xml/private_space_settings.xml
@@ -19,7 +19,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="private_space_title"
- android:title="@string/private_space_title">
+ android:title="@string/private_space_title"
+ settings:searchable="false">
<PreferenceCategory
android:title="@string/security_header">
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 7f62544..3dc0b47 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -47,6 +47,7 @@
import android.widget.ImageView;
import android.widget.Switch;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
@@ -58,6 +59,7 @@
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
import com.android.settings.utils.LocaleUtils;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settings.widget.SettingsMainSwitchPreference;
@@ -188,6 +190,7 @@
initGeneralCategory();
initShortcutPreference();
initSettingsPreference();
+ initAppInfoPreference();
initHtmlTextPreference();
initFooterPreference();
@@ -208,7 +211,7 @@
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case DialogEnums.EDIT_SHORTCUT:
- final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent())
+ final int dialogType = isAnySetupWizard()
? DialogType.EDIT_SHORTCUT_GENERIC_SUW : DialogType.EDIT_SHORTCUT_GENERIC;
mDialog = AccessibilityDialogUtils.showEditShortcutDialog(
getPrefContext(), dialogType, getShortcutTitle(),
@@ -216,7 +219,7 @@
setupEditShortcutDialog(mDialog);
return mDialog;
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
- if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ if (isAnySetupWizard()) {
mDialog = AccessibilityGestureNavigationTutorial
.createAccessibilityTutorialDialogForSetupWizard(
getPrefContext(), getUserShortcutTypes(),
@@ -541,6 +544,44 @@
generalCategory.addPreference(mSettingsPreference);
}
+ @VisibleForTesting
+ @Nullable
+ Preference createAppInfoPreference() {
+ if (!Flags.accessibilityShowAppInfoButton()) {
+ return null;
+ }
+ // App Info is not available in Setup Wizard.
+ if (isAnySetupWizard()) {
+ return null;
+ }
+ // Only show the button for pages with valid component package names.
+ if (mComponentName == null) {
+ return null;
+ }
+ final String packageName = mComponentName.getPackageName();
+ final PackageManager packageManager = getPrefContext().getPackageManager();
+ if (!packageManager.isPackageAvailable(packageName)) {
+ return null;
+ }
+
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.parse("package:" + packageName));
+
+ final Preference appInfoPreference = new Preference(getPrefContext());
+ appInfoPreference.setTitle(getString(R.string.application_info_label));
+ appInfoPreference.setIconSpaceReserved(false);
+ appInfoPreference.setIntent(intent);
+ return appInfoPreference;
+ }
+
+ private void initAppInfoPreference() {
+ final Preference appInfoPreference = createAppInfoPreference();
+ if (appInfoPreference != null) {
+ final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY);
+ generalCategory.addPreference(appInfoPreference);
+ }
+ }
+
private void initHtmlTextPreference() {
if (TextUtils.isEmpty(mHtmlDescription)) {
return;
@@ -902,4 +943,9 @@
}
return null;
}
+
+ @VisibleForTesting
+ boolean isAnySetupWizard() {
+ return WizardManagerHelper.isAnySetupWizard(getIntent());
+ }
}
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index b096467..16cf85d 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -44,7 +44,8 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.DialogCreatable;
@@ -75,7 +76,7 @@
private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
- protected SwitchPreference mFollowingTypingSwitchPreference;
+ protected TwoStatePreference mFollowingTypingSwitchPreference;
// TODO(b/147021230): Move duplicated functions with android/internal/accessibility into util.
private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener;
@@ -201,8 +202,7 @@
getSettingsLifecycle().addObserver(magnificationModePreferenceController);
magnificationModePreferenceController.displayPreference(getPreferenceScreen());
- mFollowingTypingSwitchPreference =
- new SwitchPreference(getPrefContext());
+ mFollowingTypingSwitchPreference = new SwitchPreferenceCompat(getPrefContext());
mFollowingTypingSwitchPreference.setTitle(
R.string.accessibility_screen_magnification_follow_typing_title);
mFollowingTypingSwitchPreference.setSummary(
@@ -260,7 +260,7 @@
return;
}
- var alwaysOnPreference = new SwitchPreference(getPrefContext());
+ var alwaysOnPreference = new SwitchPreferenceCompat(getPrefContext());
alwaysOnPreference.setTitle(
R.string.accessibility_screen_magnification_always_on_title);
alwaysOnPreference.setSummary(
@@ -285,7 +285,7 @@
return;
}
- SwitchPreference joystickPreference = new SwitchPreference(getPrefContext());
+ TwoStatePreference joystickPreference = new SwitchPreferenceCompat(getPrefContext());
joystickPreference.setTitle(
R.string.accessibility_screen_magnification_joystick_title);
joystickPreference.setSummary(
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncController.java b/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncController.java
index 81c5689..1f63993 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncController.java
@@ -25,7 +25,8 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
@@ -81,7 +82,7 @@
@Override
public boolean onPreferenceClick(Preference preference) {
- SwitchPreference switchPreference = (SwitchPreference) preference;
+ TwoStatePreference switchPreference = (TwoStatePreference) preference;
String key = switchPreference.getKey();
if (key.equals(KEY_PERM_SYNC)) {
if (switchPreference.isChecked()) {
@@ -106,7 +107,7 @@
@Override
protected void refresh() {
- SwitchPreference permSyncPref = mPreferenceCategory.findPreference(KEY_PERM_SYNC);
+ TwoStatePreference permSyncPref = mPreferenceCategory.findPreference(KEY_PERM_SYNC);
if (permSyncPref == null) {
permSyncPref = createPermSyncPreference(mPreferenceCategory.getContext());
mPreferenceCategory.addPreference(permSyncPref);
@@ -132,8 +133,8 @@
}
@VisibleForTesting
- SwitchPreference createPermSyncPreference(Context context) {
- SwitchPreference pref = new SwitchPreference(context);
+ TwoStatePreference createPermSyncPreference(Context context) {
+ TwoStatePreference pref = new SwitchPreferenceCompat(context);
pref.setKey(KEY_PERM_SYNC);
pref.setTitle(context.getString(R.string.bluetooth_details_permissions_sync_title));
pref.setSummary(context.getString(R.string.bluetooth_details_permissions_sync_summary));
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index 61e0a75..73857f2 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -32,7 +32,8 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.core.SettingsUIDeviceConfig;
@@ -112,14 +113,14 @@
/**
* Creates a switch preference for the particular profile.
*
- * @param context The context to use when creating the SwitchPreference
+ * @param context The context to use when creating the TwoStatePreference
* @param profile The profile for which the preference controls.
* @return A preference that allows the user to choose whether this profile
* will be connected to.
*/
- private SwitchPreference createProfilePreference(Context context,
+ private TwoStatePreference createProfilePreference(Context context,
LocalBluetoothProfile profile) {
- SwitchPreference pref = new SwitchPreference(context);
+ TwoStatePreference pref = new SwitchPreferenceCompat(context);
pref.setKey(profile.toString());
pref.setTitle(profile.getNameResource(mCachedDevice.getDevice()));
pref.setOnPreferenceClickListener(this);
@@ -148,9 +149,9 @@
}
/**
- * Refreshes the state for an existing SwitchPreference for a profile.
+ * Refreshes the state for an existing TwoStatePreference for a profile.
*/
- private void refreshProfilePreference(SwitchPreference profilePref,
+ private void refreshProfilePreference(TwoStatePreference profilePref,
LocalBluetoothProfile profile) {
BluetoothDevice device = mCachedDevice.getDevice();
boolean isLeAudioEnabled = isLeAudioEnabled();
@@ -189,8 +190,8 @@
if (profile instanceof A2dpProfile) {
A2dpProfile a2dp = (A2dpProfile) profile;
- SwitchPreference highQualityPref = (SwitchPreference) mProfilesContainer.findPreference(
- HIGH_QUALITY_AUDIO_PREF_TAG);
+ TwoStatePreference highQualityPref =
+ mProfilesContainer.findPreference(HIGH_QUALITY_AUDIO_PREF_TAG);
if (highQualityPref != null) {
if (a2dp.isEnabled(device) && a2dp.supportsHighQualityAudio(device)) {
highQualityPref.setVisible(true);
@@ -275,7 +276,7 @@
return false;
}
}
- SwitchPreference profilePref = (SwitchPreference) preference;
+ TwoStatePreference profilePref = (TwoStatePreference) preference;
if (profilePref.isChecked()) {
enableProfile(profile);
} else {
@@ -454,12 +455,12 @@
BluetoothDevice device = mCachedDevice.getDevice();
A2dpProfile a2dp = (A2dpProfile) profile;
if (a2dp.isProfileReady() && a2dp.supportsHighQualityAudio(device)) {
- SwitchPreference highQualityAudioPref = new SwitchPreference(
+ TwoStatePreference highQualityAudioPref = new SwitchPreferenceCompat(
mProfilesContainer.getContext());
highQualityAudioPref.setKey(HIGH_QUALITY_AUDIO_PREF_TAG);
highQualityAudioPref.setVisible(false);
highQualityAudioPref.setOnPreferenceClickListener(clickedPref -> {
- boolean enable = ((SwitchPreference) clickedPref).isChecked();
+ boolean enable = ((TwoStatePreference) clickedPref).isChecked();
a2dp.setHighQualityAudioEnabled(mCachedDevice.getDevice(), enable);
return true;
});
@@ -531,8 +532,7 @@
if (profile == null || !profile.isProfileReady()) {
continue;
}
- SwitchPreference pref = mProfilesContainer.findPreference(
- profile.toString());
+ TwoStatePreference pref = mProfilesContainer.findPreference(profile.toString());
if (pref == null) {
pref = createProfilePreference(mProfilesContainer.getContext(), profile);
mProfilesContainer.addPreference(pref);
@@ -541,8 +541,8 @@
refreshProfilePreference(pref, profile);
}
for (LocalBluetoothProfile removedProfile : mCachedDevice.getRemovedProfiles()) {
- final SwitchPreference pref = mProfilesContainer.findPreference(
- removedProfile.toString());
+ final TwoStatePreference pref =
+ mProfilesContainer.findPreference(removedProfile.toString());
if (pref != null) {
mProfilesContainer.removePreference(pref);
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
index c431cee..0ce1b97 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
@@ -31,7 +31,8 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -72,7 +73,7 @@
@Override
public boolean onPreferenceClick(Preference preference) {
- SwitchPreference switchPreference = (SwitchPreference) preference;
+ TwoStatePreference switchPreference = (TwoStatePreference) preference;
String key = switchPreference.getKey();
if (TextUtils.equals(key, KEY_SPATIAL_AUDIO)) {
updateSpatializerEnabled(switchPreference.isChecked());
@@ -124,7 +125,7 @@
getAvailableDevice();
}
- SwitchPreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO);
+ TwoStatePreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO);
if (spatialAudioPref == null && mAudioDevice != null) {
spatialAudioPref = createSpatialAudioPreference(mProfilesContainer.getContext());
mProfilesContainer.addPreference(spatialAudioPref);
@@ -132,7 +133,7 @@
if (spatialAudioPref != null) {
mProfilesContainer.removePreference(spatialAudioPref);
}
- final SwitchPreference headTrackingPref =
+ final TwoStatePreference headTrackingPref =
mProfilesContainer.findPreference(KEY_HEAD_TRACKING);
if (headTrackingPref != null) {
mProfilesContainer.removePreference(headTrackingPref);
@@ -144,12 +145,12 @@
refreshSpatialAudioEnabled(spatialAudioPref);
}
- private void refreshSpatialAudioEnabled(SwitchPreference spatialAudioPref) {
+ private void refreshSpatialAudioEnabled(TwoStatePreference spatialAudioPref) {
boolean isSpatialAudioOn = mSpatializer.getCompatibleAudioDevices().contains(mAudioDevice);
Log.d(TAG, "refresh() isSpatialAudioOn : " + isSpatialAudioOn);
spatialAudioPref.setChecked(isSpatialAudioOn);
- SwitchPreference headTrackingPref = mProfilesContainer.findPreference(KEY_HEAD_TRACKING);
+ TwoStatePreference headTrackingPref = mProfilesContainer.findPreference(KEY_HEAD_TRACKING);
if (headTrackingPref == null) {
headTrackingPref = createHeadTrackingPreference(mProfilesContainer.getContext());
mProfilesContainer.addPreference(headTrackingPref);
@@ -157,8 +158,8 @@
refreshHeadTracking(spatialAudioPref, headTrackingPref);
}
- private void refreshHeadTracking(SwitchPreference spatialAudioPref,
- SwitchPreference headTrackingPref) {
+ private void refreshHeadTracking(TwoStatePreference spatialAudioPref,
+ TwoStatePreference headTrackingPref) {
boolean isHeadTrackingAvailable =
spatialAudioPref.isChecked() && mSpatializer.hasHeadTracker(mAudioDevice);
Log.d(TAG, "refresh() has head tracker : " + mSpatializer.hasHeadTracker(mAudioDevice));
@@ -169,8 +170,8 @@
}
@VisibleForTesting
- SwitchPreference createSpatialAudioPreference(Context context) {
- SwitchPreference pref = new SwitchPreference(context);
+ TwoStatePreference createSpatialAudioPreference(Context context) {
+ TwoStatePreference pref = new SwitchPreferenceCompat(context);
pref.setKey(KEY_SPATIAL_AUDIO);
pref.setTitle(context.getString(R.string.bluetooth_details_spatial_audio_title));
pref.setSummary(context.getString(R.string.bluetooth_details_spatial_audio_summary));
@@ -179,8 +180,8 @@
}
@VisibleForTesting
- SwitchPreference createHeadTrackingPreference(Context context) {
- SwitchPreference pref = new SwitchPreference(context);
+ TwoStatePreference createHeadTrackingPreference(Context context) {
+ TwoStatePreference pref = new SwitchPreferenceCompat(context);
pref.setKey(KEY_HEAD_TRACKING);
pref.setTitle(context.getString(R.string.bluetooth_details_head_tracking_title));
pref.setSummary(context.getString(R.string.bluetooth_details_head_tracking_summary));
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
new file mode 100644
index 0000000..370b69a
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.widget.SettingsMainSwitchBar;
+
+public class AudioSharingDashboardFragment extends DashboardFragment {
+ private static final String TAG = "AudioSharingDashboardFrag";
+
+ SettingsMainSwitchBar mMainSwitchBar;
+ private AudioSharingSwitchBarController mSwitchBarController;
+
+ public AudioSharingDashboardFragment() {
+ super();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ // TODO: update category id.
+ return 0;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public int getHelpResource() {
+ return R.string.help_url_audio_sharing;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.bluetooth_audio_sharing;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ // Assume we are in a SettingsActivity. This is only safe because we currently use
+ // SettingsActivity as base for all preference fragments.
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+ mMainSwitchBar = activity.getSwitchBar();
+ mMainSwitchBar.setTitle(getText(R.string.audio_sharing_switch_title));
+ mSwitchBarController = new AudioSharingSwitchBarController(activity, mMainSwitchBar);
+ mMainSwitchBar.show();
+ }
+}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
new file mode 100644
index 0000000..b6b4568
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flags.Flags;
+
+public class AudioSharingPreferenceController extends BasePreferenceController {
+ private static final String TAG = "AudioSharingPreferenceController";
+
+ private Context mContext;
+
+ public AudioSharingPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ mContext = context;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return Flags.enableLeAudioSharing() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
new file mode 100644
index 0000000..f2a332b
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.content.Context;
+import android.widget.Switch;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.settings.widget.SettingsMainSwitchBar;
+import com.android.settingslib.widget.OnMainSwitchChangeListener;
+
+public class AudioSharingSwitchBarController
+ implements DefaultLifecycleObserver, OnMainSwitchChangeListener {
+
+ private static final String TAG = "AudioSharingSwitchBarCtl";
+
+ private final Context mContext;
+ private final SettingsMainSwitchBar mSwitchBar;
+ private final Switch mSwitch;
+
+ AudioSharingSwitchBarController(Context context, SettingsMainSwitchBar switchBar) {
+ mContext = context;
+ mSwitchBar = switchBar;
+ mSwitch = mSwitchBar.getSwitch();
+ mSwitch.setChecked(false);
+ }
+
+ @Override
+ public void onStart(@NonNull LifecycleOwner owner) {
+ mSwitchBar.addOnSwitchChangeListener(this);
+ }
+
+ @Override
+ public void onStop(@NonNull LifecycleOwner owner) {
+ mSwitchBar.removeOnSwitchChangeListener(this);
+ }
+
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ // Filter out unnecessary callbacks when switch is disabled.
+ if (!switchView.isEnabled()) return;
+
+ if (isChecked) {
+ // TODO: start sharing
+ } else {
+ // TODO: stop sharing
+ }
+ }
+}
diff --git a/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java b/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
index 985c8b7..64ec63f 100644
--- a/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
+++ b/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
@@ -40,7 +40,8 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
@@ -157,8 +158,8 @@
return pref;
}
- private SwitchPreference createButtonPressPreference() {
- SwitchPreference pref = new SwitchPreference(mContext);
+ private TwoStatePreference createButtonPressPreference() {
+ TwoStatePreference pref = new SwitchPreferenceCompat(mContext);
pref.setKey(KEY_IGNORE_BUTTON);
pref.setTitle(mContext.getString(R.string.stylus_ignore_button));
pref.setIcon(R.drawable.ic_block);
@@ -198,7 +199,7 @@
case KEY_IGNORE_BUTTON:
Settings.Secure.putInt(mContext.getContentResolver(),
Secure.STYLUS_BUTTONS_ENABLED,
- ((SwitchPreference) preference).isChecked() ? 0 : 1);
+ ((TwoStatePreference) preference).isChecked() ? 0 : 1);
break;
}
return true;
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
index 07bd175..f00435a 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
@@ -26,7 +26,8 @@
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -39,7 +40,7 @@
private static final String KEY_USB_USE_POWER_ONLY = "usb_use_power_only";
private PreferenceCategory mPreferenceCategory;
- private SwitchPreference mSwitchPreference;
+ private TwoStatePreference mSwitchPreference;
private int mNextPowerRole;
@@ -60,7 +61,7 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceCategory = screen.findPreference(getPreferenceKey());
- mSwitchPreference = new SwitchPreference(mPreferenceCategory.getContext());
+ mSwitchPreference = new SwitchPreferenceCompat(mPreferenceCategory.getContext());
mSwitchPreference.setTitle(R.string.usb_use_power_only);
mSwitchPreference.setKey(KEY_USB_USE_POWER_ONLY);
mSwitchPreference.setOnPreferenceClickListener(this);
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsTranscodeMtpController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsTranscodeMtpController.java
index 280e1d2..192ae74 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsTranscodeMtpController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsTranscodeMtpController.java
@@ -25,7 +25,8 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -41,7 +42,7 @@
private static final String KEY_USB_TRANSCODE_FILES = "usb_transcode_files";
private PreferenceCategory mPreferenceCategory;
- private SwitchPreference mSwitchPreference;
+ private TwoStatePreference mSwitchPreference;
public UsbDetailsTranscodeMtpController(Context context, UsbDetailsFragment fragment,
UsbBackend backend) {
@@ -53,7 +54,7 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceCategory = screen.findPreference(getPreferenceKey());
- mSwitchPreference = new SwitchPreference(mPreferenceCategory.getContext());
+ mSwitchPreference = new SwitchPreferenceCompat(mPreferenceCategory.getContext());
mSwitchPreference.setTitle(R.string.usb_transcode_files);
mSwitchPreference.setKey(KEY_USB_TRANSCODE_FILES);
mSwitchPreference.setOnPreferenceClickListener(this);
diff --git a/src/com/android/settings/core/InstrumentedPreferenceFragment.java b/src/com/android/settings/core/InstrumentedPreferenceFragment.java
index ba92eae..4d871d4 100644
--- a/src/com/android/settings/core/InstrumentedPreferenceFragment.java
+++ b/src/com/android/settings/core/InstrumentedPreferenceFragment.java
@@ -27,7 +27,7 @@
import androidx.annotation.XmlRes;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.TwoStatePreference;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.jank.InteractionJankMonitor;
@@ -71,9 +71,9 @@
super.onStart();
// Override the OnPreferenceTreeClickListener in super.onStart() to inject jank detection.
getPreferenceManager().setOnPreferenceTreeClickListener((preference) -> {
- if (preference instanceof SwitchPreference) {
+ if (preference instanceof TwoStatePreference twoStatePreference) {
SettingsJankMonitor.detectSwitchPreferenceClickJank(
- getListView(), (SwitchPreference) preference);
+ getListView(), twoStatePreference);
}
return onPreferenceTreeClick(preference);
});
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 9d673b1..0973076 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -38,7 +38,7 @@
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -600,7 +600,7 @@
.setWidgetLayoutResource(R.layout.preference_external_action_icon);
return externalActionPreference;
case SWITCH:
- return new SwitchPreference(getPrefContext());
+ return new SwitchPreferenceCompat(getPrefContext());
case SWITCH_WITH_ACTION:
return new PrimarySwitchPreference(getPrefContext());
case GROUP:
diff --git a/src/com/android/settings/development/compat/PlatformCompatDashboard.java b/src/com/android/settings/development/compat/PlatformCompatDashboard.java
index 3f0ffc7..05159c7 100644
--- a/src/com/android/settings/development/compat/PlatformCompatDashboard.java
+++ b/src/com/android/settings/development/compat/PlatformCompatDashboard.java
@@ -33,7 +33,8 @@
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceCategory;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
@@ -171,7 +172,7 @@
Preference createPreferenceForChange(Context context, CompatibilityChangeInfo change,
CompatibilityChangeConfig configMappings) {
final boolean currentValue = configMappings.isChangeEnabled(change.getId());
- final SwitchPreference item = new SwitchPreference(context);
+ final TwoStatePreference item = new SwitchPreferenceCompat(context);
final String changeName =
change.getName() != null ? change.getName() : "Change_" + change.getId();
item.setSummary(changeName);
diff --git a/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java b/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java
index d713ff3..7fc9d9e 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java
@@ -31,7 +31,8 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.internal.statusbar.IStatusBarService;
import com.android.settings.core.BasePreferenceController;
@@ -82,7 +83,7 @@
|| ((enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
&& sInfo.enabled);
- SwitchPreference preference = new SwitchPreference(context);
+ TwoStatePreference preference = new SwitchPreferenceCompat(context);
preference.setTitle(sInfo.loadLabel(mPackageManager));
preference.setIcon(sInfo.icon);
preference.setKey(sInfo.name);
diff --git a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java
index 69b34b0..e38f5d4 100644
--- a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java
+++ b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java
@@ -27,7 +27,8 @@
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
@@ -42,7 +43,7 @@
public class DeviceStateAutoRotateSettingController extends TogglePreferenceController implements
LifecycleObserver {
- private SwitchPreference mPreference;
+ private TwoStatePreference mPreference;
private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager;
private final int mOrder;
@@ -86,7 +87,7 @@
@Override
public void displayPreference(PreferenceScreen screen) {
- mPreference = new SwitchPreference(mContext);
+ mPreference = new SwitchPreferenceCompat(mContext);
mPreference.setTitle(mDeviceStateDescription);
mPreference.setKey(getPreferenceKey());
mPreference.setOrder(mOrder);
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
index 10cd4a2..1f29a2b 100644
--- a/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
@@ -25,7 +25,8 @@
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -40,7 +41,7 @@
InputManager.InputDeviceListener, LifecycleObserver, OnStart, OnStop {
private final InputManager mIm;
- private final Map<SwitchPreference, KeyboardLayout> mPreferenceMap;
+ private final Map<TwoStatePreference, KeyboardLayout> mPreferenceMap;
private Fragment mParent;
private int mInputDeviceId;
@@ -95,11 +96,10 @@
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
- if (!(preference instanceof SwitchPreference)) {
+ if (!(preference instanceof TwoStatePreference switchPref)) {
return false;
}
- final SwitchPreference switchPref = (SwitchPreference) preference;
final KeyboardLayout layout = mPreferenceMap.get(switchPref);
if (layout != null) {
final boolean checked = switchPref.isChecked();
@@ -138,7 +138,7 @@
mInputDeviceIdentifier);
Arrays.sort(enabledKeyboardLayouts);
- for (Map.Entry<SwitchPreference, KeyboardLayout> entry : mPreferenceMap.entrySet()) {
+ for (Map.Entry<TwoStatePreference, KeyboardLayout> entry : mPreferenceMap.entrySet()) {
entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
entry.getValue().getDescriptor()) >= 0);
}
@@ -149,7 +149,7 @@
return;
}
for (KeyboardLayout layout : mKeyboardLayouts) {
- final SwitchPreference pref = new SwitchPreference(mScreen.getContext());
+ final TwoStatePreference pref = new SwitchPreferenceCompat(mScreen.getContext());
pref.setTitle(layout.getLabel());
pref.setSummary(layout.getCollection());
// TODO: Waiting for new API to use a prefix with special number to setKey
diff --git a/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java b/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
new file mode 100644
index 0000000..50a44e17
--- /dev/null
+++ b/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.privatespace;
+
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+
+import android.app.AlertDialog;
+import android.app.KeyguardManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Flags;
+import android.util.Log;
+
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.transition.SettingsTransitionHelper;
+
+import com.google.android.setupdesign.util.ThemeHelper;
+
+/**
+ * Prompts user to set a device lock if not set with an alert dialog.
+ * If a lock is already set then first authenticates user before displaying private space settings
+ * page.
+ */
+public class PrivateSpaceAuthenticationActivity extends FragmentActivity {
+ private static final String TAG = "PrivateSpaceAuthCheck";
+ private PrivateSpaceMaintainer mPrivateSpaceMaintainer;
+ private KeyguardManager mKeyguardManager;
+
+ private final ActivityResultLauncher<Intent> mSetDeviceLock =
+ registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
+ this::onSetDeviceLockResult);
+ private final ActivityResultLauncher<Intent> mVerifyDeviceLock =
+ registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
+ this::onVerifyDeviceLock);
+
+ static class Injector {
+ PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
+ return PrivateSpaceMaintainer.getInstance(context);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (Flags.allowPrivateProfile()) {
+ ThemeHelper.trySetDynamicColor(this);
+ mPrivateSpaceMaintainer = new Injector().injectPrivateSpaceMaintainer(
+ getApplicationContext());
+ if (getKeyguardManager().isDeviceSecure()) {
+ if (savedInstanceState == null) {
+ Intent credentialIntent =
+ mPrivateSpaceMaintainer.getPrivateProfileLockCredentialIntent();
+ if (credentialIntent != null) {
+ mVerifyDeviceLock.launch(credentialIntent);
+ } else {
+ Log.e(TAG, "verifyCredentialIntent is null even though device lock is set");
+ finish();
+ }
+ }
+ } else {
+ promptToSetDeviceLock();
+ }
+ } else {
+ Log.w(TAG, "allowPrivateProfile flag is Off!");
+ finish();
+ }
+ }
+
+ /** Show private space settings page on device lock authentications */
+ @VisibleForTesting
+ public void onLockAuthentication(Context context) {
+ new SubSettingLauncher(context)
+ .setDestination(PrivateSpaceDashboardFragment.class.getName())
+ .setTransitionType(
+ SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE)
+ .setSourceMetricsCategory(SettingsEnums.PRIVATE_SPACE_SETTINGS)
+ .launch();
+ }
+
+ @VisibleForTesting
+ public void setPrivateSpaceMaintainer(Injector injector) {
+ mPrivateSpaceMaintainer = injector.injectPrivateSpaceMaintainer(getApplicationContext());
+ }
+
+ private void promptToSetDeviceLock() {
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.no_device_lock_title)
+ .setMessage(R.string.no_device_lock_summary)
+ .setPositiveButton(
+ R.string.no_device_lock_action_label,
+ (DialogInterface dialog, int which) -> {
+ mSetDeviceLock.launch(new Intent(ACTION_SET_NEW_PASSWORD));
+ })
+ .setNegativeButton(
+ R.string.no_device_lock_cancel,
+ (DialogInterface dialog, int which) -> finish())
+ .setOnCancelListener(
+ (DialogInterface dialog) -> {
+ finish();
+ })
+ .show();
+ }
+
+ private KeyguardManager getKeyguardManager() {
+ if (mKeyguardManager == null) {
+ mKeyguardManager = getSystemService(KeyguardManager.class);
+ }
+ return mKeyguardManager;
+ }
+
+ private void onSetDeviceLockResult(@Nullable ActivityResult result) {
+ if (result != null) {
+ if (getKeyguardManager().isDeviceSecure()) {
+ onLockAuthentication(this);
+ }
+ finish();
+ }
+ }
+
+ private void onVerifyDeviceLock(@Nullable ActivityResult result) {
+ if (result != null && result.getResultCode() == RESULT_OK) {
+ onLockAuthentication(this);
+ }
+ finish();
+ }
+}
diff --git a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
index 0abf8f7..af2da5b 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
@@ -20,7 +20,9 @@
import android.app.ActivityManager;
import android.app.IActivityManager;
+import android.app.KeyguardManager;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -28,6 +30,8 @@
import android.util.ArraySet;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.GuardedBy;
import java.util.List;
@@ -43,6 +47,7 @@
private final UserManager mUserManager;
@GuardedBy("this")
private UserHandle mUserHandle;
+ private final KeyguardManager mKeyguardManager;
public enum ErrorDeletingPrivateSpace {
DELETE_PS_ERROR_NONE,
@@ -140,6 +145,23 @@
return mUserManager.isQuietModeEnabled(mUserHandle);
}
+ /**
+ * Returns an intent to prompt the user to confirm private profile credentials if it is set
+ * otherwise returns intent to confirm device credentials.
+ */
+ @Nullable
+ public synchronized Intent getPrivateProfileLockCredentialIntent() {
+ //TODO(b/307281644): To replace with check for doesPrivateSpaceExist() method once Auth
+ // changes are merged.
+ if (isPrivateProfileLockSet()) {
+ return mKeyguardManager.createConfirmDeviceCredentialIntent(
+ /* title= */ null, /* description= */null, mUserHandle.getIdentifier());
+ }
+ // TODO(b/304796434) Need to try changing this intent to use BiometricPrompt
+ return mKeyguardManager.createConfirmDeviceCredentialIntent(
+ /* title= */ null, /* description= */ null);
+ }
+
/** Returns the instance of {@link PrivateSpaceMaintainer} */
public static synchronized PrivateSpaceMaintainer getInstance(Context context) {
if (sPrivateSpaceMaintainer == null) {
@@ -151,5 +173,19 @@
private PrivateSpaceMaintainer(Context context) {
mContext = context.getApplicationContext();
mUserManager = mContext.getSystemService(UserManager.class);
+ mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
+ }
+
+
+ // TODO(b/307281644): Remove this method once new auth change is merged
+ /**
+ * Returns true if private space exists and a separate private profile lock is set
+ * otherwise false when the private space does not exit or exists but does not have a
+ * separate profile lock.
+ */
+ @GuardedBy("this")
+ private boolean isPrivateProfileLockSet() {
+ return doesPrivateSpaceExist()
+ && mKeyguardManager.isDeviceSecure(mUserHandle.getIdentifier());
}
}
diff --git a/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java b/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java
index 4910a7b..6729830 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceSafetySource.java
@@ -17,7 +17,6 @@
package com.android.settings.privatespace;
import android.app.PendingIntent;
-import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.Flags;
@@ -28,9 +27,7 @@
import android.util.Log;
import com.android.settings.R;
-import com.android.settings.core.SubSettingLauncher;
import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
-import com.android.settingslib.transition.SettingsTransitionHelper;
/** Private Space safety source for the Safety Center */
public final class PrivateSpaceSafetySource {
@@ -86,18 +83,15 @@
}
private static PendingIntent getPendingIntentForPsDashboard(Context context) {
- Intent privateSpaceDashboardIntent = new SubSettingLauncher(context)
- .setDestination(PrivateSpaceDashboardFragment.class.getName())
- .setTransitionType(SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE)
- .setSourceMetricsCategory(SettingsEnums.PRIVATE_SPACE_SETTINGS)
- .toIntent()
- .setIdentifier(SAFETY_SOURCE_ID);
+ Intent privateSpaceAuthenticationIntent =
+ new Intent(context, PrivateSpaceAuthenticationActivity.class)
+ .setIdentifier(SAFETY_SOURCE_ID);
return PendingIntent
.getActivity(
context,
/* requestCode */ 0,
- privateSpaceDashboardIntent,
+ privateSpaceAuthenticationIntent,
PendingIntent.FLAG_IMMUTABLE);
}
}
diff --git a/src/com/android/settings/spa/app/AllAppList.kt b/src/com/android/settings/spa/app/AllAppList.kt
index f3ad2e6..383a0e8 100644
--- a/src/com/android/settings/spa/app/AllAppList.kt
+++ b/src/com/android/settings/spa/app/AllAppList.kt
@@ -136,7 +136,7 @@
derivedStateOf {
storageSummary.value +
when {
- !record.app.installed -> {
+ !record.app.installed && !record.app.isArchived -> {
System.lineSeparator() + context.getString(R.string.not_installed)
}
isDisabled(record) -> {
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index db7612f..465da39 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -54,7 +54,8 @@
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -132,7 +133,7 @@
}
};
- static class AppRestrictionsPreference extends SwitchPreference {
+ static class AppRestrictionsPreference extends SwitchPreferenceCompat {
private boolean hasSettings;
private OnClickListener listener;
private ArrayList<RestrictionEntry> restrictions;
@@ -687,10 +688,10 @@
Preference p = null;
switch (entry.getType()) {
case RestrictionEntry.TYPE_BOOLEAN:
- p = new SwitchPreference(getPrefContext());
+ p = new SwitchPreferenceCompat(getPrefContext());
p.setTitle(entry.getTitle());
p.setSummary(entry.getDescription());
- ((SwitchPreference)p).setChecked(entry.getSelectedState());
+ ((TwoStatePreference) p).setChecked(entry.getSelectedState());
break;
case RestrictionEntry.TYPE_CHOICE:
case RestrictionEntry.TYPE_CHOICE_LEVEL:
diff --git a/src/com/android/settings/wfd/WifiDisplaySettings.java b/src/com/android/settings/wfd/WifiDisplaySettings.java
old mode 100755
new mode 100644
index 8562e5f..96f067c
--- a/src/com/android/settings/wfd/WifiDisplaySettings.java
+++ b/src/com/android/settings/wfd/WifiDisplaySettings.java
@@ -59,7 +59,8 @@
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import androidx.preference.TwoStatePreference;
import com.android.internal.app.MediaRouteDialogPresenter;
import com.android.settings.R;
@@ -370,7 +371,7 @@
}
// switch for Listen Mode
- SwitchPreference pref = new SwitchPreference(getPrefContext()) {
+ TwoStatePreference pref = new SwitchPreferenceCompat(getPrefContext()) {
@Override
protected void onClick() {
mListen = !mListen;
@@ -383,7 +384,7 @@
mCertCategory.addPreference(pref);
// switch for Autonomous GO
- pref = new SwitchPreference(getPrefContext()) {
+ pref = new SwitchPreferenceCompat(getPrefContext()) {
@Override
protected void onClick() {
mAutoGO = !mAutoGO;
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index de305a6..66211a2 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -32,7 +32,12 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,6 +47,7 @@
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
@@ -50,10 +56,12 @@
import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
+import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settingslib.widget.TopIntroPreference;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -74,6 +82,9 @@
})
public class ToggleFeaturePreferenceFragmentTest {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example";
private static final String PLACEHOLDER_CLASS_NAME = PLACEHOLDER_PACKAGE_NAME + ".placeholder";
private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName(
@@ -105,6 +116,8 @@
private FragmentActivity mActivity;
@Mock
private ContentResolver mContentResolver;
+ @Mock
+ private PackageManager mPackageManager;
@Before
public void setUpTestFragment() {
@@ -116,6 +129,7 @@
when(mFragment.getContext()).thenReturn(mContext);
when(mFragment.getActivity()).thenReturn(mActivity);
when(mActivity.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
final PreferenceScreen screen = spy(new PreferenceScreen(mContext, null));
when(screen.getPreferenceManager()).thenReturn(mPreferenceManager);
doReturn(screen).when(mFragment).getPreferenceScreen();
@@ -318,6 +332,53 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ACCESSIBILITY_SHOW_APP_INFO_BUTTON)
+ public void createAppInfoPreference_withValidComponentName() {
+ when(mPackageManager.isPackageAvailable(PLACEHOLDER_PACKAGE_NAME)).thenReturn(true);
+ mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
+
+ final Preference preference = mFragment.createAppInfoPreference();
+
+ assertThat(preference).isNotNull();
+ final Intent appInfoIntent = preference.getIntent();
+ assertThat(appInfoIntent.getAction())
+ .isEqualTo(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ assertThat(appInfoIntent.getDataString()).isEqualTo("package:" + PLACEHOLDER_PACKAGE_NAME);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ACCESSIBILITY_SHOW_APP_INFO_BUTTON)
+ public void createAppInfoPreference_noComponentName_shouldBeNull() {
+ mFragment.mComponentName = null;
+
+ final Preference preference = mFragment.createAppInfoPreference();
+
+ assertThat(preference).isNull();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ACCESSIBILITY_SHOW_APP_INFO_BUTTON)
+ public void createAppInfoPreference_withUnavailablePackage_shouldBeNull() {
+ when(mPackageManager.isPackageAvailable(PLACEHOLDER_PACKAGE_NAME)).thenReturn(false);
+ mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
+
+ final Preference preference = mFragment.createAppInfoPreference();
+
+ assertThat(preference).isNull();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ACCESSIBILITY_SHOW_APP_INFO_BUTTON)
+ public void createAppInfoPreference_inSetupWizard_shouldBeNull() {
+ when(mFragment.isAnySetupWizard()).thenReturn(true);
+ mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
+
+ final Preference preference = mFragment.createAppInfoPreference();
+
+ assertThat(preference).isNull();
+ }
+
+ @Test
public void createFooterPreference_shouldSetAsExpectedValue() {
mFragment.createFooterPreference(mFragment.getPreferenceScreen(),
DEFAULT_SUMMARY, DEFAULT_DESCRIPTION);
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
index fe316ea..f26e838 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
@@ -32,7 +32,7 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
@@ -124,7 +124,7 @@
mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context));
mTopIntroPreference = new TopIntroPreference(context);
mSettingsPreference = new Preference(context);
- mFollowingTypingSwitchPreference = new SwitchPreference(context);
+ mFollowingTypingSwitchPreference = new SwitchPreferenceCompat(context);
}
@Override
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
index f0b2fbe..539c503 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
@@ -43,7 +43,7 @@
import android.provider.Settings;
import androidx.appcompat.app.AlertDialog;
-import androidx.preference.SwitchPreference;
+import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.DialogCreatable;
@@ -133,7 +133,7 @@
mFragController.create(R.id.main_content, /* bundle= */ null).start().resume();
- final SwitchPreference switchPreference =
+ final TwoStatePreference switchPreference =
mFragController.get().findPreference(
MagnificationFollowTypingPreferenceController.PREF_KEY);
assertThat(switchPreference).isNotNull();
@@ -146,7 +146,7 @@
mFragController.create(R.id.main_content, /* bundle= */ null).start().resume();
- final SwitchPreference switchPreference =
+ final TwoStatePreference switchPreference =
mFragController.get().findPreference(
MagnificationFollowTypingPreferenceController.PREF_KEY);
assertThat(switchPreference).isNotNull();
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncControllerTest.java
index 5d6fe31..8fa3e8a 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsDataSyncControllerTest.java
@@ -25,7 +25,7 @@
import android.companion.datatransfer.PermissionSyncRequest;
import androidx.preference.PreferenceCategory;
-import androidx.preference.SwitchPreference;
+import androidx.preference.TwoStatePreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -56,7 +56,7 @@
private CompanionDeviceManager mCompanionDeviceManager;
private PermissionSyncRequest mPermissionSyncRequest;
- private SwitchPreference mPermSyncPreference;
+ private TwoStatePreference mPermSyncPreference;
@Before
public void setUp() {
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
index ce5631f..de70330 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
@@ -32,7 +32,7 @@
import android.media.Spatializer;
import androidx.preference.PreferenceCategory;
-import androidx.preference.SwitchPreference;
+import androidx.preference.TwoStatePreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -68,8 +68,8 @@
private AudioDeviceAttributes mAvailableDevice;
private BluetoothDetailsSpatialAudioController mController;
- private SwitchPreference mSpatialAudioPref;
- private SwitchPreference mHeadTrackingPref;
+ private TwoStatePreference mSpatialAudioPref;
+ private TwoStatePreference mHeadTrackingPref;
@Before
public void setUp() {
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
index fe7c6a2..53ed4f0 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
@@ -216,6 +216,23 @@
composeTestRule.onNodeWithText(LABEL).assertIsDisplayed()
}
+ @Test
+ fun allAppListModel_getSummaryWhenArchived() {
+ val listModel = AllAppListModel(context) { stateOf(SUMMARY) }
+ val archivedApp = ApplicationInfo().apply {
+ packageName = PACKAGE_NAME
+ isArchived = true
+ }
+
+ lateinit var summaryState: State<String>
+ composeTestRule.setContent {
+ summaryState =
+ listModel.getSummary(option = 0, record = AppRecordWithSize(app = archivedApp))
+ }
+
+ assertThat(summaryState.value).isEqualTo(SUMMARY)
+ }
+
private fun getAppListInput(): AppListInput<AppRecordWithSize> {
lateinit var input: AppListInput<AppRecordWithSize>
composeTestRule.setContent {
diff --git a/tests/uitests/Android.bp b/tests/uitests/Android.bp
index f149519..4a47c90 100644
--- a/tests/uitests/Android.bp
+++ b/tests/uitests/Android.bp
@@ -47,7 +47,8 @@
"settings-helper",
"sysui-helper",
"timeresult-helper-lib",
- "truth",
+ "truth-prebuilt",
+ "flag-junit",
],
//sdk_version: "current",
diff --git a/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt b/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt
index 5339e95..b5a4fe9 100644
--- a/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt
+++ b/tests/uitests/src/com/android/settings/ui/SecuritySettingsTest.kt
@@ -16,6 +16,9 @@
package com.android.settings.ui
+import android.os.Flags
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
@@ -23,13 +26,18 @@
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+
@RunWith(AndroidJUnit4::class)
class SecuritySettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ @get:Rule
+ public val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_SECURITY_SETTINGS)
@@ -40,6 +48,12 @@
device.assertHasTexts(ON_SCREEN_TEXTS)
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+ fun privateSpace_ifFlagON() {
+ device.assertHasTexts(listOf("Private Space"))
+ }
+
private companion object {
// Items we really want to always show
val ON_SCREEN_TEXTS = listOf(
diff --git a/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt b/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
new file mode 100644
index 0000000..8751471
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.ui.privatespace
+
+
+import android.os.Flags
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import android.provider.Settings
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
+import com.android.settings.ui.testutils.SettingsTestUtils.clickObject
+import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
+import com.android.settings.ui.testutils.SettingsTestUtils.waitObject
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+
+@RunWith(AndroidJUnit4::class)
+@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+class PrivateSpaceAuthenticationActivityTest {
+ private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+
+ @get:Rule
+ public val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
+ @Before
+ fun setUp() {
+ device.startMainActivityFromHomeScreen(Settings.ACTION_SECURITY_SETTINGS)
+ device.assertHasTexts(listOf(PRIVATE_SPACE_SETTING))
+ }
+
+ @Test
+ fun showAuthenticationScreen() {
+ Thread.sleep(1000)
+ device.clickObject(By.text(PRIVATE_SPACE_SETTING))
+ device.waitObject(By.text(DIALOG_TITLE))
+ Thread.sleep(1000)
+ device.assertHasTexts(listOf("Set a screen lock","Cancel"))
+ }
+
+ @Test
+ fun onCancelLockExitSetup() {
+ Thread.sleep(1000)
+ device.clickObject(By.text(PRIVATE_SPACE_SETTING))
+ device.waitObject(By.text(DIALOG_TITLE))
+ Thread.sleep(1000)
+ device.assertHasTexts(listOf(SET_LOCK_BUTTON, CANCEL_TEXT))
+ device.clickObject(By.text(CANCEL_TEXT))
+ device.assertHasTexts(listOf(PRIVATE_SPACE_SETTING))
+ }
+
+ @Test
+ fun onSetupSetLock() {
+ Thread.sleep(1000)
+ device.clickObject(By.text(PRIVATE_SPACE_SETTING))
+ device.waitObject(By.text(DIALOG_TITLE))
+ Thread.sleep(1000)
+ device.assertHasTexts(listOf(SET_LOCK_BUTTON,CANCEL_TEXT))
+ device.clickObject(By.text(SET_LOCK_BUTTON))
+ device.assertHasTexts(listOf(LOCK_SCREEN_TITLE))
+ }
+
+ private companion object {
+ // Items we really want to always show
+ val PRIVATE_SPACE_SETTING = "Private Space"
+ const val SET_LOCK_BUTTON = "Set screen lock"
+ val CANCEL_TEXT = "Cancel"
+ val DIALOG_TITLE = "Set a screen lock"
+ val LOCK_SCREEN_TITLE = "Choose screen lock"
+ }
+}
diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivityTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivityTest.java
new file mode 100644
index 0000000..d2e1270
--- /dev/null
+++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivityTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.privatespace;
+
+import static com.android.settings.privatespace.PrivateSpaceSafetySource.SAFETY_SOURCE_ID;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Flags;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class PrivateSpaceAuthenticationActivityTest {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
+ @Mock private PrivateSpaceMaintainer mPrivateSpaceMaintainer;
+ @Mock private Context mContext;
+ private PrivateSpaceAuthenticationActivity mPrivateSpaceAuthenticationActivity;
+ private Intent mDefaultIntent;
+
+ /** Required setup before a test. */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = ApplicationProvider.getApplicationContext();
+ mDefaultIntent = new Intent();
+ mDefaultIntent.setClass(InstrumentationRegistry.getInstrumentation().getTargetContext(),
+ PrivateSpaceAuthenticationActivity.class);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ try {
+ mPrivateSpaceAuthenticationActivity =
+ spy((PrivateSpaceAuthenticationActivity) InstrumentationRegistry
+ .getInstrumentation().newActivity(
+ getClass().getClassLoader(),
+ PrivateSpaceAuthenticationActivity.class.getName(),
+ mDefaultIntent));
+ } catch (Exception e) {
+ throw new RuntimeException(e); // nothing to do
+ }
+ });
+ doNothing().when(mPrivateSpaceAuthenticationActivity).startActivity(any(Intent.class));
+ PrivateSpaceAuthenticationActivity.Injector injector =
+ new PrivateSpaceAuthenticationActivity.Injector() {
+ @Override
+ PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
+ return mPrivateSpaceMaintainer;
+ }
+ };
+ mPrivateSpaceAuthenticationActivity.setPrivateSpaceMaintainer(injector);
+ }
+
+ /** Tests that on lock authentication Private space settings is launched. */
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+ public void deviceSecurePrivateSpaceExists() {
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ mPrivateSpaceAuthenticationActivity.onLockAuthentication(mContext);
+ verify(mPrivateSpaceAuthenticationActivity).startActivity(intentCaptor.capture());
+ assertThat(intentCaptor.getValue().getIdentifier()).isEqualTo(SAFETY_SOURCE_ID);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java
index ddf5287..bb3f891 100644
--- a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceSafetySourceTest.java
@@ -18,8 +18,11 @@
import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED;
+
import static com.android.settings.privatespace.PrivateSpaceSafetySource.SAFETY_SOURCE_ID;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -122,9 +125,9 @@
assertThat(safetySourceStatus.isEnabled()).isTrue();
}
- /** Tests that setSafetySourceData sets the PS settings page intent. */
+ /** Tests that setSafetySourceData sets the PS settings page authenticator intent. */
@Test
- public void setSafetySourceData_setsPsIntent() {
+ public void setSafetySourceData_setsPsAuthenticatorIntent() {
when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(true);
mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
@@ -135,7 +138,7 @@
any(), eq(SAFETY_SOURCE_ID), captor.capture(), eq(EVENT_TYPE_DEVICE_REBOOTED));
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
- assertThat(safetySourceStatus.getPendingIntent().getIntent().getIdentifier())
- .isEqualTo(SAFETY_SOURCE_ID);
+ assertThat(safetySourceStatus.getPendingIntent().getIntent()
+ .equals(PrivateSpaceAuthenticationActivity.class));
}
}