Snap for 7991057 from 4f5f174a5e to tm-release
Change-Id: Ief02fb5fad2bb474f76e4885b46fa3c8307a0080
This commit is contained in:
@@ -110,6 +110,7 @@
|
|||||||
<uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION" />
|
<uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION" />
|
||||||
<uses-permission android:name="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK" />
|
<uses-permission android:name="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK" />
|
||||||
<uses-permission android:name="android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS" />
|
<uses-permission android:name="android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".SettingsApplication"
|
android:name=".SettingsApplication"
|
||||||
@@ -150,6 +151,7 @@
|
|||||||
android:taskAffinity=""
|
android:taskAffinity=""
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:enabled="false"
|
||||||
android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout"
|
android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout"
|
||||||
android:permission="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK">
|
android:permission="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -311,6 +313,7 @@
|
|||||||
|
|
||||||
<receiver android:name=".search.SearchStateReceiver"
|
<receiver android:name=".search.SearchStateReceiver"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:enabled="false"
|
||||||
android:permission="android.permission.READ_SEARCH_INDEXABLES">
|
android:permission="android.permission.READ_SEARCH_INDEXABLES">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.android.settings.SEARCH_START"/>
|
<action android:name="com.android.settings.SEARCH_START"/>
|
||||||
@@ -673,12 +676,12 @@
|
|||||||
<activity android:name=".network.telephony.ToggleSubscriptionDialogActivity"
|
<activity android:name=".network.telephony.ToggleSubscriptionDialogActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
||||||
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
|
android:theme="@style/Theme.AlertDialog"/>
|
||||||
|
|
||||||
<activity android:name=".network.telephony.DeleteEuiccSubscriptionDialogActivity"
|
<activity android:name=".network.telephony.DeleteEuiccSubscriptionDialogActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
||||||
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
|
android:theme="@style/Theme.AlertDialog"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="Settings$TetherSettingsActivity"
|
android:name="Settings$TetherSettingsActivity"
|
||||||
@@ -4260,14 +4263,14 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
||||||
android:launchMode="singleInstance"
|
android:launchMode="singleInstance"
|
||||||
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
|
android:theme="@style/Theme.AlertDialog"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".sim.DsdsDialogActivity"
|
android:name=".sim.DsdsDialogActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
|
||||||
android:launchMode="singleInstance"
|
android:launchMode="singleInstance"
|
||||||
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
|
android:theme="@style/Theme.AlertDialog"/>
|
||||||
|
|
||||||
<service android:name=".sim.SimNotificationService"
|
<service android:name=".sim.SimNotificationService"
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|||||||
29
res/drawable/ic_settings_safety_center.xml
Normal file
29
res/drawable/ic_settings_safety_center.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright (C) 2021 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
<!-- TODO(b/208624929): Update to an UX approved icon. -->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:tint="?android:attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M18.5,1C16.01,1 14,3.01 14,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10c0,-1.1 -0.9,-2 -2,-2h-2V5.5C16,4.12 17.12,3 18.5,3C19.88,3 21,4.12 21,5.5V6h2V5.5C23,3.01 20.99,1 18.5,1zM18,10v10H6V10H18z"/>
|
||||||
|
</vector>
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/font_size_preview_text_group"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
style="@style/Theme.Material3.DayNight.Dialog.Alert">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/msg"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/carrier_list"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="56dp"
|
||||||
|
android:gravity="start|top"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="4dp"
|
||||||
|
android:baselineAligned="true">
|
||||||
|
<ImageView
|
||||||
|
android:src="@drawable/ic_info_outline_24dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:tint="?android:attr/textColorTertiary"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/info_outline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:text="@string/sim_action_switch_sub_dialog_info_outline_for_turning_off"
|
||||||
|
android:textColor="?android:attr/textColorSecondary" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -75,12 +75,6 @@
|
|||||||
android:contentDescription="@string/font_size_make_larger_desc"
|
android:contentDescription="@string/font_size_make_larger_desc"
|
||||||
style="@style/screen_size_imageview_style"/>
|
style="@style/screen_size_imageview_style"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/font_size_summary"
|
|
||||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|||||||
@@ -74,12 +74,6 @@
|
|||||||
android:contentDescription="@string/screen_zoom_make_larger_desc"
|
android:contentDescription="@string/screen_zoom_make_larger_desc"
|
||||||
style="@style/screen_size_imageview_style"/>
|
style="@style/screen_size_imageview_style"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/screen_zoom_summary"
|
|
||||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|||||||
@@ -19,4 +19,6 @@
|
|||||||
<!-- Dashboard number of columns -->
|
<!-- Dashboard number of columns -->
|
||||||
<integer name="dashboard_num_columns">2</integer>
|
<integer name="dashboard_num_columns">2</integer>
|
||||||
|
|
||||||
|
<!-- Whether to support large screen -->
|
||||||
|
<bool name="config_supported_large_screen">true</bool>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -63,6 +63,9 @@
|
|||||||
<dimen name="confirm_credentials_side_margin">0dp</dimen>
|
<dimen name="confirm_credentials_side_margin">0dp</dimen>
|
||||||
<dimen name="confirm_credentials_top_margin">64dp</dimen>
|
<dimen name="confirm_credentials_top_margin">64dp</dimen>
|
||||||
|
|
||||||
|
<!-- padding for font size preview in large screen -->
|
||||||
|
<dimen name="font_size_preview_padding_start">32dp</dimen>
|
||||||
|
|
||||||
<!-- Padding for screen pinning -->
|
<!-- Padding for screen pinning -->
|
||||||
<dimen name="screen_pinning_padding_start">40dp</dimen>
|
<dimen name="screen_pinning_padding_start">40dp</dimen>
|
||||||
<dimen name="screen_pinning_padding_end">40dp</dimen>
|
<dimen name="screen_pinning_padding_end">40dp</dimen>
|
||||||
|
|||||||
@@ -532,6 +532,9 @@
|
|||||||
<!-- Whether suw to support two panes -->
|
<!-- Whether suw to support two panes -->
|
||||||
<bool name="config_suw_supported_two_panes">false</bool>
|
<bool name="config_suw_supported_two_panes">false</bool>
|
||||||
|
|
||||||
|
<!-- Whether to support large screen -->
|
||||||
|
<bool name="config_supported_large_screen">false</bool>
|
||||||
|
|
||||||
<!-- Display settings screen, Color mode options. Must be the same length and order as
|
<!-- Display settings screen, Color mode options. Must be the same length and order as
|
||||||
config_color_mode_options_values below. Only the values that also appear in
|
config_color_mode_options_values below. Only the values that also appear in
|
||||||
frameworks/base/core/res/res/values/config.xml's config_availableColorModes are shown. -->
|
frameworks/base/core/res/res/values/config.xml's config_availableColorModes are shown. -->
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<string name="menu_key_display" translatable="false">top_level_display</string>
|
<string name="menu_key_display" translatable="false">top_level_display</string>
|
||||||
<string name="menu_key_wallpaper" translatable="false">top_level_wallpaper</string>
|
<string name="menu_key_wallpaper" translatable="false">top_level_wallpaper</string>
|
||||||
<string name="menu_key_accessibility" translatable="false">top_level_accessibility</string>
|
<string name="menu_key_accessibility" translatable="false">top_level_accessibility</string>
|
||||||
|
<string name="menu_key_safety_center" translatable="false">top_level_safety_center</string>
|
||||||
<string name="menu_key_security" translatable="false">top_level_security</string>
|
<string name="menu_key_security" translatable="false">top_level_security</string>
|
||||||
<string name="menu_key_privacy" translatable="false">top_level_privacy</string>
|
<string name="menu_key_privacy" translatable="false">top_level_privacy</string>
|
||||||
<string name="menu_key_location" translatable="false">top_level_location</string>
|
<string name="menu_key_location" translatable="false">top_level_location</string>
|
||||||
|
|||||||
@@ -722,6 +722,12 @@
|
|||||||
<string name="security_status_title">Security status</string>
|
<string name="security_status_title">Security status</string>
|
||||||
<!-- Summary for Security settings, explaining a few important settings under it [CHAR LIMIT=NONE] -->
|
<!-- Summary for Security settings, explaining a few important settings under it [CHAR LIMIT=NONE] -->
|
||||||
<string name="security_dashboard_summary">Screen lock, Find My Device, app security</string>
|
<string name="security_dashboard_summary">Screen lock, Find My Device, app security</string>
|
||||||
|
<!-- TODO(b/208624929): Update to an UX approved title and char limit. -->
|
||||||
|
<!-- Main Settings screen setting title for the item that takes you to the safety center [CHAR LIMIT=60] -->
|
||||||
|
<string name="safety_center_title">Security & privacy</string>
|
||||||
|
<!-- TODO(b/208624929): Update to an UX approved summary and char limit. -->
|
||||||
|
<!-- Main Settings screen setting summary for the item that takes you to the safety center [CHAR LIMIT=60] -->
|
||||||
|
<string name="safety_center_summary">Permissions, screen lock, app security</string>
|
||||||
|
|
||||||
<!-- Face enrollment and settings --><skip />
|
<!-- Face enrollment and settings --><skip />
|
||||||
<!-- Note: Update FaceEnrollParentalConsent.CONSENT_STRING_RESOURCES when any _consent_ strings are added or removed. -->
|
<!-- Note: Update FaceEnrollParentalConsent.CONSENT_STRING_RESOURCES when any _consent_ strings are added or removed. -->
|
||||||
@@ -871,11 +877,9 @@
|
|||||||
<!-- 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>
|
<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] -->
|
<!-- 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. After deletion, you will need your PIN, pattern, or password to unlock your phone or for authentication in apps.</string>
|
<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>
|
||||||
<!-- Dialog title shown when the user chooses to delete an existing enrolled face model. [CHAR LIMIT=35] -->
|
<!-- Dialog contents shown when the user removes an enrollment when configured as a convenience [CHAR LIMIT=NONE] -->
|
||||||
<string name="security_settings_face_settings_remove_model_dialog_title">Delete face model?</string>
|
<string name="security_settings_face_settings_remove_dialog_details_convenience">Your face model will be permanently and securely deleted.\n\nAfter deletion, you will need your PIN, pattern, or password to unlock your phone.</string>
|
||||||
<!-- Dialog contents shown when the user chooses to delete an existing enrolled face model. [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="security_settings_face_settings_remove_model_dialog_details">Your face model will be permanently and securely deleted.\n\nAfter deletion, you will need your fingerprint, PIN, pattern, or password to unlock your phone or for authentication in apps.</string>
|
|
||||||
<!-- Subtitle shown for contextual setting face enrollment [CHAR LIMIT=NONE] -->
|
<!-- Subtitle shown for contextual setting face enrollment [CHAR LIMIT=NONE] -->
|
||||||
<string name="security_settings_face_settings_context_subtitle">Use Face Unlock to unlock your phone</string>
|
<string name="security_settings_face_settings_context_subtitle">Use Face Unlock to unlock your phone</string>
|
||||||
|
|
||||||
@@ -4386,25 +4390,6 @@
|
|||||||
<!-- Header on first screen of choose work profile pattern flow [CHAR LIMIT=40] -->
|
<!-- Header on first screen of choose work profile pattern flow [CHAR LIMIT=40] -->
|
||||||
<string name="lockpassword_choose_your_profile_pattern_header">Set a work pattern</string>
|
<string name="lockpassword_choose_your_profile_pattern_header">Set a work pattern</string>
|
||||||
|
|
||||||
<!-- Header on first screen of choose device password flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpassword_choose_password_description" product="phone">For added security, set a password to unlock the phone</string>
|
|
||||||
<!-- Header on first screen of choose device PIN flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpassword_choose_pin_description" product="phone">For added security, set a PIN to unlock the phone</string>
|
|
||||||
<!-- Header on first screen of choose device pattern flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpattern_choose_pattern_description" product="phone">For added security, set a pattern to unlock the phone</string>
|
|
||||||
<!-- Header on first screen of choose device password flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpassword_choose_password_description" product="tablet">For added security, set a password to unlock the tablet</string>
|
|
||||||
<!-- Header on first screen of choose device PIN flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpassword_choose_pin_description" product="tablet">For added security, set a PIN to unlock the tablet</string>
|
|
||||||
<!-- Header on first screen of choose device pattern flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpattern_choose_pattern_description" product="tablet">For added security, set a pattern to unlock the tablet</string>
|
|
||||||
<!-- Header on first screen of choose device password flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpassword_choose_password_description" product="default">For added security, set a password to unlock the device</string>
|
|
||||||
<!-- Header on first screen of choose device PIN flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpassword_choose_pin_description" product="default">For added security, set a PIN to unlock the device</string>
|
|
||||||
<!-- Header on first screen of choose device pattern flow [CHAR LIMIT=NONE] -->
|
|
||||||
<string name="lockpattern_choose_pattern_description" product="default">For added security, set a pattern to unlock the device</string>
|
|
||||||
|
|
||||||
<!-- Header on first screen of choose password/PIN as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] -->
|
<!-- Header on first screen of choose password/PIN as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] -->
|
||||||
<string name="lockpassword_choose_your_password_header_for_fingerprint">To use fingerprint, set password</string>
|
<string name="lockpassword_choose_your_password_header_for_fingerprint">To use fingerprint, set password</string>
|
||||||
<!-- Header on first screen of choose pattern as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] -->
|
<!-- Header on first screen of choose pattern as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] -->
|
||||||
@@ -8122,11 +8107,17 @@
|
|||||||
<!-- Checkbox to always use for calls. [CHAR LIMIT=40] -->
|
<!-- Checkbox to always use for calls. [CHAR LIMIT=40] -->
|
||||||
<string name="sim_calls_always_use">Always use this for calls</string>
|
<string name="sim_calls_always_use">Always use this for calls</string>
|
||||||
<!-- Message for selecting sim for data in settings. [CHAR LIMIT=40] -->
|
<!-- Message for selecting sim for data in settings. [CHAR LIMIT=40] -->
|
||||||
<string name="select_sim_for_data">Select a SIM for data</string>
|
<string name="select_sim_for_data">Choose SIM for mobile data</string>
|
||||||
<!-- Message for selecting sim for SMS in settings. [CHAR LIMIT=40] -->
|
<!-- Message for selecting sim for SMS in settings. [CHAR LIMIT=40] -->
|
||||||
<string name="select_sim_for_sms">Select a SIM for SMS</string>
|
<string name="select_sim_for_sms">Select a SIM for SMS</string>
|
||||||
<!-- Message for switching data SIM; switching takes a while -->
|
<!-- Message for switching data SIM; switching takes a while -->
|
||||||
<string name="data_switch_started">Switching data SIM, this may take up to a minute\u2026</string>
|
<string name="data_switch_started">Switching data SIM, this may take up to a minute\u2026</string>
|
||||||
|
<!-- Title for selecting specific sim for data in settings. [CHAR LIMIT=40] -->
|
||||||
|
<string name="select_specific_sim_for_data_title">Use <xliff:g id="new_sim" example="carrierA">%1$s</xliff:g> for mobile data?</string>
|
||||||
|
<!-- Message for selecting specific sim for data in settings. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="select_specific_sim_for_data_msg">If you switch to <xliff:g id="new_sim" example="carrierA">%1$s</xliff:g>, <xliff:g id="old_sim" example="carrierB">%2$s</xliff:g> will no longer be used for mobile data.</string>
|
||||||
|
<!-- Button on a selecting specific sim dialog to confirm data in settings. [CHAR LIMIT=40] -->
|
||||||
|
<string name="select_specific_sim_for_data_button">Use <xliff:g id="new_sim" example="carrierA">%1$s</xliff:g></string>
|
||||||
<!-- Message for selecting sim for call in settings. [CHAR LIMIT=40] -->
|
<!-- Message for selecting sim for call in settings. [CHAR LIMIT=40] -->
|
||||||
<string name="select_sim_for_calls">Call with</string>
|
<string name="select_sim_for_calls">Call with</string>
|
||||||
<!-- Title for selecting a SIM card. [CHAR LIMIT=40] -->
|
<!-- Title for selecting a SIM card. [CHAR LIMIT=40] -->
|
||||||
@@ -12936,14 +12927,22 @@
|
|||||||
<string name="sim_action_switch_sub_dialog_title">Switch to <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>?</string>
|
<string name="sim_action_switch_sub_dialog_title">Switch to <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>?</string>
|
||||||
<!-- Title of confirmation dialog asking the user if they want to switch to the SIM card. [CHAR_LIMIT=NONE] -->
|
<!-- Title of confirmation dialog asking the user if they want to switch to the SIM card. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="sim_action_switch_psim_dialog_title">Switch to using SIM card?</string>
|
<string name="sim_action_switch_psim_dialog_title">Switch to using SIM card?</string>
|
||||||
|
<!-- Title of confirmation dialog asking the user if they want to switch subscription. [CHAR_LIMIT=NONE] -->
|
||||||
|
<string name="sim_action_switch_sub_dialog_mep_title">Use <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>?</string>
|
||||||
<!-- Body text of confirmation dialog for switching subscription that involves switching SIM slots. Indicates that only one SIM can be active at a time. Also that switching will not cancel the user's mobile service plan. [CHAR_LIMIT=NONE] -->
|
<!-- Body text of confirmation dialog for switching subscription that involves switching SIM slots. Indicates that only one SIM can be active at a time. Also that switching will not cancel the user's mobile service plan. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="sim_action_switch_sub_dialog_text">Only one SIM can be active at a time.\n\nSwitching to <xliff:g id="to_carrier_name" example="Google Fi">%1$s</xliff:g> won\u2019t cancel your <xliff:g id="from_carrier_name" example="Sprint">%2$s</xliff:g> service.</string>
|
<string name="sim_action_switch_sub_dialog_text">Only one SIM can be active at a time.\n\nSwitching to <xliff:g id="to_carrier_name" example="Google Fi">%1$s</xliff:g> won\u2019t cancel your <xliff:g id="from_carrier_name" example="Sprint">%2$s</xliff:g> service.</string>
|
||||||
<!-- Body text of confirmation dialog for switching subscription between two eSIM profiles. Indicates that only one downloaded SIM can be active at a time. Also that switching will not cancel the user's mobile service plan. [CHAR_LIMIT=NONE] -->
|
<!-- Body text of confirmation dialog for switching subscription between two eSIM profiles. Indicates that only one downloaded SIM can be active at a time. Also that switching will not cancel the user's mobile service plan. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="sim_action_switch_sub_dialog_text_downloaded">Only one downloaded SIM can be active at a time.\n\nSwitching to <xliff:g id="to_carrier_name" example="Google Fi">%1$s</xliff:g> won\u2019t cancel your <xliff:g id="from_carrier_name" example="Sprint">%2$s</xliff:g> service.</string>
|
<string name="sim_action_switch_sub_dialog_text_downloaded">Only one downloaded SIM can be active at a time.\n\nSwitching to <xliff:g id="to_carrier_name" example="Google Fi">%1$s</xliff:g> won\u2019t cancel your <xliff:g id="from_carrier_name" example="Sprint">%2$s</xliff:g> service.</string>
|
||||||
<!-- Body text of confirmation dialog for switching subscription between two eSIM profiles. Indicates that only one SIM can be active at a time. Also that switching will not cancel the user's mobile service plan. [CHAR_LIMIT=NONE] -->
|
<!-- Body text of confirmation dialog for switching subscription between two eSIM profiles. Indicates that only one SIM can be active at a time. Also that switching will not cancel the user's mobile service plan. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="sim_action_switch_sub_dialog_text_single_sim">Only one SIM can be active at a time.\n\nSwitching won\u2019t cancel your <xliff:g id="to_carrier_name" example="Google Fi">%1$s</xliff:g> service.</string>
|
<string name="sim_action_switch_sub_dialog_text_single_sim">Only one SIM can be active at a time.\n\nSwitching won\u2019t cancel your <xliff:g id="to_carrier_name" example="Google Fi">%1$s</xliff:g> service.</string>
|
||||||
|
<!-- Body text of confirmation dialog for switching subscription between two eSIM profiles. Indicates that only one downloaded SIM can be active at a time. Also that switching will not cancel the user's mobile service plan. [CHAR_LIMIT=NONE] -->
|
||||||
|
<string name="sim_action_switch_sub_dialog_mep_text">You can use 2 SIMs at a time. To use <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>, turn off another SIM.</string>
|
||||||
<!-- Text of confirm button in the confirmation dialog asking the user if they want to switch subscription. [CHAR_LIMIT=NONE] -->
|
<!-- Text of confirm button in the confirmation dialog asking the user if they want to switch subscription. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="sim_action_switch_sub_dialog_confirm">Switch to <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g></string>
|
<string name="sim_action_switch_sub_dialog_confirm">Switch to <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g></string>
|
||||||
|
<!-- Text of carrier list item in the mep confirmation dialog asking the user if they want to turn off the carrier. [CHAR_LIMIT=NONE] -->
|
||||||
|
<string name="sim_action_switch_sub_dialog_carrier_list_item_for_turning_off">Turn off <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g></string>
|
||||||
|
<!-- Text of carrier list item in the mep confirmation dialog asking the user if they want to turn off the carrier. [CHAR_LIMIT=NONE] -->
|
||||||
|
<string name="sim_action_switch_sub_dialog_info_outline_for_turning_off">Turning off a SIM won\u2019t cancel your service</string>
|
||||||
<!-- Status message indicating the device is in the process of disconnecting from one mobile network and immediately connecting to another. [CHAR_LIMIT=NONE] -->
|
<!-- Status message indicating the device is in the process of disconnecting from one mobile network and immediately connecting to another. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="sim_action_enabling_sim_without_carrier_name">Connecting to network…</string>
|
<string name="sim_action_enabling_sim_without_carrier_name">Connecting to network…</string>
|
||||||
<!-- Text of progress dialog indicating the subscription switch is in progress. [CHAR_LIMIT=NONE] -->
|
<!-- Text of progress dialog indicating the subscription switch is in progress. [CHAR_LIMIT=NONE] -->
|
||||||
|
|||||||
@@ -116,6 +116,15 @@
|
|||||||
settings:highlightableMenuKey="@string/menu_key_accessibility"
|
settings:highlightableMenuKey="@string/menu_key_accessibility"
|
||||||
settings:controller="com.android.settings.accessibility.TopLevelAccessibilityPreferenceController"/>
|
settings:controller="com.android.settings.accessibility.TopLevelAccessibilityPreferenceController"/>
|
||||||
|
|
||||||
|
<com.android.settings.widget.HomepagePreference
|
||||||
|
android:icon="@drawable/ic_settings_safety_center"
|
||||||
|
android:key="top_level_safety_center"
|
||||||
|
android:order="-55"
|
||||||
|
android:title="@string/safety_center_title"
|
||||||
|
android:summary="@string/safety_center_summary"
|
||||||
|
settings:highlightableMenuKey="@string/menu_key_safety_center"
|
||||||
|
settings:controller="com.android.settings.safetycenter.TopLevelSafetyCenterEntryPreferenceController"/>
|
||||||
|
|
||||||
<com.android.settings.widget.HomepagePreference
|
<com.android.settings.widget.HomepagePreference
|
||||||
android:fragment="com.android.settings.security.SecuritySettings"
|
android:fragment="com.android.settings.security.SecuritySettings"
|
||||||
android:icon="@drawable/ic_settings_security_white"
|
android:icon="@drawable/ic_settings_security_white"
|
||||||
@@ -133,7 +142,8 @@
|
|||||||
android:order="-40"
|
android:order="-40"
|
||||||
android:title="@string/privacy_dashboard_title"
|
android:title="@string/privacy_dashboard_title"
|
||||||
android:summary="@string/privacy_dashboard_summary"
|
android:summary="@string/privacy_dashboard_summary"
|
||||||
settings:highlightableMenuKey="@string/menu_key_privacy"/>
|
settings:highlightableMenuKey="@string/menu_key_privacy"
|
||||||
|
settings:controller="com.android.settings.privacy.TopLevelPrivacyEntryPreferenceController"/>
|
||||||
|
|
||||||
<com.android.settings.widget.HomepagePreference
|
<com.android.settings.widget.HomepagePreference
|
||||||
android:fragment="com.android.settings.location.LocationSettings"
|
android:fragment="com.android.settings.location.LocationSettings"
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ public class AccessibilityScreenSizeForSetupWizardActivity extends InstrumentedA
|
|||||||
: R.string.screen_zoom_title);
|
: R.string.screen_zoom_title);
|
||||||
((TextView) findViewById(R.id.sud_layout_subtitle)).setText(
|
((TextView) findViewById(R.id.sud_layout_subtitle)).setText(
|
||||||
getFragmentType(getIntent()) == FragmentType.FONT_SIZE
|
getFragmentType(getIntent()) == FragmentType.FONT_SIZE
|
||||||
? R.string.short_summary_font_size
|
? R.string.font_size_summary
|
||||||
: R.string.screen_zoom_short_summary);
|
: R.string.screen_zoom_summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuwSupportedTwoPanes() {
|
private boolean isSuwSupportedTwoPanes() {
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ import android.app.admin.DevicePolicyManager;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentSender;
|
import android.content.IntentSender;
|
||||||
|
import android.hardware.biometrics.SensorProperties;
|
||||||
|
import android.hardware.face.FaceManager;
|
||||||
|
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
@@ -273,4 +276,17 @@ public class BiometricUtils {
|
|||||||
public static boolean isReverseLandscape(@NonNull Context context) {
|
public static boolean isReverseLandscape(@NonNull Context context) {
|
||||||
return context.getDisplay().getRotation() == Surface.ROTATION_270;
|
return context.getDisplay().getRotation() == Surface.ROTATION_270;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param faceManager
|
||||||
|
* @return True if at least one sensor is set as a convenience.
|
||||||
|
*/
|
||||||
|
public static boolean isConvenience(@NonNull FaceManager faceManager) {
|
||||||
|
for (FaceSensorPropertiesInternal props : faceManager.getSensorPropertiesInternal()) {
|
||||||
|
if (props.sensorStrength == SensorProperties.STRENGTH_CONVENIENCE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import androidx.preference.Preference;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
|
import com.android.settings.biometrics.BiometricUtils;
|
||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
@@ -56,6 +57,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
|
|||||||
|
|
||||||
public static class ConfirmRemoveDialog extends InstrumentedDialogFragment {
|
public static class ConfirmRemoveDialog extends InstrumentedDialogFragment {
|
||||||
|
|
||||||
|
private boolean mIsConvenience;
|
||||||
private DialogInterface.OnClickListener mOnClickListener;
|
private DialogInterface.OnClickListener mOnClickListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -68,7 +70,9 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
|
|||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
|
||||||
builder.setTitle(R.string.security_settings_face_settings_remove_dialog_title)
|
builder.setTitle(R.string.security_settings_face_settings_remove_dialog_title)
|
||||||
.setMessage(R.string.security_settings_face_settings_remove_dialog_details)
|
.setMessage(mIsConvenience
|
||||||
|
? R.string.security_settings_face_settings_remove_dialog_details_convenience
|
||||||
|
: R.string.security_settings_face_settings_remove_dialog_details)
|
||||||
.setPositiveButton(R.string.delete, mOnClickListener)
|
.setPositiveButton(R.string.delete, mOnClickListener)
|
||||||
.setNegativeButton(R.string.cancel, mOnClickListener);
|
.setNegativeButton(R.string.cancel, mOnClickListener);
|
||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
@@ -76,6 +80,10 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
|
|||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIsConvenience(boolean isConvenience) {
|
||||||
|
mIsConvenience = isConvenience;
|
||||||
|
}
|
||||||
|
|
||||||
public void setOnClickListener(DialogInterface.OnClickListener listener) {
|
public void setOnClickListener(DialogInterface.OnClickListener listener) {
|
||||||
mOnClickListener = listener;
|
mOnClickListener = listener;
|
||||||
}
|
}
|
||||||
@@ -197,6 +205,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
|
|||||||
mRemoving = true;
|
mRemoving = true;
|
||||||
ConfirmRemoveDialog dialog = new ConfirmRemoveDialog();
|
ConfirmRemoveDialog dialog = new ConfirmRemoveDialog();
|
||||||
dialog.setOnClickListener(mOnClickListener);
|
dialog.setOnClickListener(mOnClickListener);
|
||||||
|
dialog.setIsConvenience(BiometricUtils.isConvenience(mFaceManager));
|
||||||
dialog.show(mActivity.getSupportFragmentManager(), ConfirmRemoveDialog.class.getName());
|
dialog.show(mActivity.getSupportFragmentManager(), ConfirmRemoveDialog.class.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,13 @@
|
|||||||
package com.android.settings.display;
|
package com.android.settings.display;
|
||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
|
||||||
@@ -33,6 +40,23 @@ public class FontSizePreferenceFragmentForSetupWizard
|
|||||||
return SettingsEnums.SUW_ACCESSIBILITY_FONT_SIZE;
|
return SettingsEnums.SUW_ACCESSIBILITY_FONT_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
final View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
if (getResources().getBoolean(R.bool.config_supported_large_screen)) {
|
||||||
|
final ViewPager viewPager = root.findViewById(R.id.preview_pager);
|
||||||
|
final View view = (View) viewPager.getAdapter().instantiateItem(viewPager,
|
||||||
|
viewPager.getCurrentItem());
|
||||||
|
final LinearLayout layout = view.findViewById(R.id.font_size_preview_text_group);
|
||||||
|
final int paddingStart = getResources().getDimensionPixelSize(
|
||||||
|
R.dimen.font_size_preview_padding_start);
|
||||||
|
layout.setPaddingRelative(paddingStart, layout.getPaddingTop(),
|
||||||
|
layout.getPaddingEnd(), layout.getPaddingBottom());
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
// Log the final choice in value if it's different from the previous value.
|
// Log the final choice in value if it's different from the previous value.
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void launchDeepLinkIntentToRight() {
|
private void launchDeepLinkIntentToRight() {
|
||||||
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this)) {
|
if (!mIsEmbeddingActivityEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ package com.android.settings.homepage;
|
|||||||
import static com.android.settings.search.actionbar.SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR;
|
import static com.android.settings.search.actionbar.SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR;
|
||||||
import static com.android.settingslib.search.SearchIndexable.MOBILE;
|
import static com.android.settingslib.search.SearchIndexable.MOBILE;
|
||||||
|
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@@ -53,6 +55,7 @@ public class TopLevelSettings extends DashboardFragment implements
|
|||||||
private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin";
|
private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin";
|
||||||
private static final String PREF_KEY_SUPPORT = "top_level_support";
|
private static final String PREF_KEY_SUPPORT = "top_level_support";
|
||||||
|
|
||||||
|
private boolean mIsEmbeddingActivityEnabled;
|
||||||
private TopLevelHighlightMixin mHighlightMixin;
|
private TopLevelHighlightMixin mHighlightMixin;
|
||||||
private boolean mFirstStarted = true;
|
private boolean mFirstStarted = true;
|
||||||
|
|
||||||
@@ -122,7 +125,9 @@ public class TopLevelSettings extends DashboardFragment implements
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext())) {
|
mIsEmbeddingActivityEnabled =
|
||||||
|
ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext());
|
||||||
|
if (!mIsEmbeddingActivityEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,15 +143,23 @@ public class TopLevelSettings extends DashboardFragment implements
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
if (mFirstStarted) {
|
if (mFirstStarted) {
|
||||||
mFirstStarted = false;
|
mFirstStarted = false;
|
||||||
} else if (!ActivityEmbeddingUtils.isTwoPaneResolution(getActivity())) {
|
} else if (mIsEmbeddingActivityEnabled && isOnlyOneActivityInTask()
|
||||||
|
&& !ActivityEmbeddingUtils.isTwoPaneResolution(getActivity())) {
|
||||||
// Set default highlight menu key for 1-pane homepage since it will show the placeholder
|
// Set default highlight menu key for 1-pane homepage since it will show the placeholder
|
||||||
// page once changing back to 2-pane.
|
// page once changing back to 2-pane.
|
||||||
|
Log.i(TAG, "Set default menu key");
|
||||||
setHighlightMenuKey(getString(SettingsHomepageActivity.DEFAULT_HIGHLIGHT_MENU_KEY),
|
setHighlightMenuKey(getString(SettingsHomepageActivity.DEFAULT_HIGHLIGHT_MENU_KEY),
|
||||||
/* scrollNeeded= */ false);
|
/* scrollNeeded= */ false);
|
||||||
}
|
}
|
||||||
super.onStart();
|
super.onStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isOnlyOneActivityInTask() {
|
||||||
|
final ActivityManager.RunningTaskInfo taskInfo = getSystemService(ActivityManager.class)
|
||||||
|
.getRunningTasks(1).get(0);
|
||||||
|
return taskInfo.numActivities == 1;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
@@ -225,8 +238,7 @@ public class TopLevelSettings extends DashboardFragment implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
||||||
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext())
|
if (!mIsEmbeddingActivityEnabled || !(getActivity() instanceof SettingsHomepageActivity)) {
|
||||||
|| !(getActivity() instanceof SettingsHomepageActivity)) {
|
|
||||||
return super.onCreateAdapter(preferenceScreen);
|
return super.onCreateAdapter(preferenceScreen);
|
||||||
}
|
}
|
||||||
return mHighlightMixin.onCreateAdapter(this, preferenceScreen);
|
return mHighlightMixin.onCreateAdapter(this, preferenceScreen);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.settings.network;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.app.FragmentManager;
|
import android.app.FragmentManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settings.AsyncTaskSidecar;
|
import com.android.settings.AsyncTaskSidecar;
|
||||||
@@ -41,11 +42,14 @@ public class SwitchSlotSidecar
|
|||||||
})
|
})
|
||||||
private @interface Command {
|
private @interface Command {
|
||||||
int SWITCH_TO_REMOVABLE_SIM = 0;
|
int SWITCH_TO_REMOVABLE_SIM = 0;
|
||||||
|
int SWITCH_TO_EUICC_SIM = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Param {
|
static class Param {
|
||||||
@Command int command;
|
@Command int command;
|
||||||
int slotId;
|
int slotId;
|
||||||
|
int port;
|
||||||
|
SubscriptionInfo removedSubInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Result {
|
static class Result {
|
||||||
@@ -65,13 +69,24 @@ public class SwitchSlotSidecar
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Starts switching to the removable slot. */
|
/** Starts switching to the removable slot. */
|
||||||
public void runSwitchToRemovableSlot(int id) {
|
public void runSwitchToRemovableSlot(int id, SubscriptionInfo removedSubInfo) {
|
||||||
Param param = new Param();
|
Param param = new Param();
|
||||||
param.command = Command.SWITCH_TO_REMOVABLE_SIM;
|
param.command = Command.SWITCH_TO_REMOVABLE_SIM;
|
||||||
param.slotId = id;
|
param.slotId = id;
|
||||||
|
param.removedSubInfo = removedSubInfo;
|
||||||
|
param.port = 0;
|
||||||
super.run(param);
|
super.run(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Starts switching to the removable slot. */
|
||||||
|
public void runSwitchToEuiccSlot(int id, int port, SubscriptionInfo removedSubInfo) {
|
||||||
|
Param param = new Param();
|
||||||
|
param.command = Command.SWITCH_TO_EUICC_SIM;
|
||||||
|
param.slotId = id;
|
||||||
|
param.removedSubInfo = removedSubInfo;
|
||||||
|
param.port = port;
|
||||||
|
super.run(param);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns the exception thrown during the execution of a command. Will be null in any state
|
* Returns the exception thrown during the execution of a command. Will be null in any state
|
||||||
* other than {@link State#SUCCESS}, and may be null in that state if there was not an error.
|
* other than {@link State#SUCCESS}, and may be null in that state if there was not an error.
|
||||||
@@ -91,7 +106,14 @@ public class SwitchSlotSidecar
|
|||||||
try {
|
try {
|
||||||
switch (param.command) {
|
switch (param.command) {
|
||||||
case Command.SWITCH_TO_REMOVABLE_SIM:
|
case Command.SWITCH_TO_REMOVABLE_SIM:
|
||||||
UiccSlotUtil.switchToRemovableSlot(param.slotId, getContext());
|
Log.i(TAG, "Start to switch to removable slot.");
|
||||||
|
UiccSlotUtil.switchToRemovableSlot(getContext(), param.slotId,
|
||||||
|
param.removedSubInfo);
|
||||||
|
break;
|
||||||
|
case Command.SWITCH_TO_EUICC_SIM:
|
||||||
|
Log.i(TAG, "Start to switch to euicc slot.");
|
||||||
|
UiccSlotUtil.switchToEuiccSlot(getContext(), param.slotId, param.port,
|
||||||
|
param.removedSubInfo);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(TAG, "Wrong command.");
|
Log.e(TAG, "Wrong command.");
|
||||||
|
|||||||
@@ -18,17 +18,30 @@ package com.android.settings.network;
|
|||||||
|
|
||||||
import android.app.FragmentManager;
|
import android.app.FragmentManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
import android.telephony.UiccCardInfo;
|
||||||
|
import android.telephony.UiccSlotMapping;
|
||||||
|
import android.telephony.euicc.EuiccManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settings.SidecarFragment;
|
import com.android.settings.SidecarFragment;
|
||||||
import com.android.settings.network.telephony.EuiccOperationSidecar;
|
import com.android.settings.network.telephony.EuiccOperationSidecar;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/** A headless fragment encapsulating long-running eSIM enabling/disabling operations. */
|
/** A headless fragment encapsulating long-running eSIM enabling/disabling operations. */
|
||||||
public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||||
private static final String TAG = "SwitchToEuiccSubscriptionSidecar";
|
private static final String TAG = "SwitchToEuiccSubscriptionSidecar";
|
||||||
private static final String ACTION_SWITCH_TO_SUBSCRIPTION =
|
private static final String ACTION_SWITCH_TO_SUBSCRIPTION =
|
||||||
"com.android.settings.network.SWITCH_TO_SUBSCRIPTION";
|
"com.android.settings.network.SWITCH_TO_SUBSCRIPTION";
|
||||||
|
private static final int ESIM_SLOT_ID = 1;
|
||||||
|
|
||||||
private PendingIntent mCallbackIntent;
|
private PendingIntent mCallbackIntent;
|
||||||
|
private int mSubId;
|
||||||
|
private int mPort;
|
||||||
|
|
||||||
/** Returns a SwitchToEuiccSubscriptionSidecar sidecar instance. */
|
/** Returns a SwitchToEuiccSubscriptionSidecar sidecar instance. */
|
||||||
public static SwitchToEuiccSubscriptionSidecar get(FragmentManager fm) {
|
public static SwitchToEuiccSubscriptionSidecar get(FragmentManager fm) {
|
||||||
@@ -46,10 +59,119 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
|||||||
return mCallbackIntent;
|
return mCallbackIntent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStateChange(SidecarFragment fragment) {
|
||||||
|
if (fragment == mSwitchSlotSidecar) {
|
||||||
|
onSwitchSlotSidecarStateChange();
|
||||||
|
} else {
|
||||||
|
Log.wtf(TAG, "Received state change from a sidecar not expected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Starts calling EuiccManager#switchToSubscription to enable/disable the eSIM profile. */
|
/** Starts calling EuiccManager#switchToSubscription to enable/disable the eSIM profile. */
|
||||||
|
// ToDo: delete this api and refactor the related code.
|
||||||
public void run(int subscriptionId) {
|
public void run(int subscriptionId) {
|
||||||
setState(State.RUNNING, Substate.UNUSED);
|
setState(State.RUNNING, Substate.UNUSED);
|
||||||
mCallbackIntent = createCallbackIntent();
|
mCallbackIntent = createCallbackIntent();
|
||||||
mEuiccManager.switchToSubscription(subscriptionId, mCallbackIntent);
|
mEuiccManager.switchToSubscription(subscriptionId, mCallbackIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts calling EuiccManager#switchToSubscription to enable/disable the eSIM profile.
|
||||||
|
*
|
||||||
|
* @param subscriptionId the esim's subscriptionId.
|
||||||
|
* @param port the esim's portId. If user wants to inactivate esim, then user must to assign the
|
||||||
|
* the port. If user wants to activate esim, then the port can be -1.
|
||||||
|
* @param removedSubInfo if the all of slots have sims, it should remove the one of active sim.
|
||||||
|
* If the removedSubInfo is null, then use the default value.
|
||||||
|
* The default value is the esim slot and portId 0.
|
||||||
|
*/
|
||||||
|
public void run(int subscriptionId, int port, SubscriptionInfo removedSubInfo) {
|
||||||
|
setState(State.RUNNING, Substate.UNUSED);
|
||||||
|
mCallbackIntent = createCallbackIntent();
|
||||||
|
mSubId = subscriptionId;
|
||||||
|
// To check whether the esim slot's port is active. If yes, skip setSlotMapping. If no,
|
||||||
|
// set this slot+port into setSimSlotMapping.
|
||||||
|
mPort = (port < 0) ? getTargetPortId(removedSubInfo) : port;
|
||||||
|
Log.i(TAG, "The SubId is " + mSubId + "The port is " + mPort);
|
||||||
|
|
||||||
|
mSwitchSlotSidecar.runSwitchToEuiccSlot(getTargetSlot(), mPort, removedSubInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getTargetPortId(SubscriptionInfo removedSubInfo) {
|
||||||
|
if (!mTelephonyManager.isMultiSimEnabled() || !isMultipleEnabledProfilesSupported()) {
|
||||||
|
// In the 'SS mode' or 'DSDS+no MEP', the port is 0.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the 'DSDS+MEP', if the removedSubInfo is esim, then the port is
|
||||||
|
// removedSubInfo's port.
|
||||||
|
if (removedSubInfo != null && removedSubInfo.isEmbedded()) {
|
||||||
|
return removedSubInfo.getPortIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
// In DSDS+MEP mode, the removedSubInfo is psim or is null, it means the this esim need
|
||||||
|
// another port in the esim slot.
|
||||||
|
// To find another esim's port and value is from 0;
|
||||||
|
int port = 0;
|
||||||
|
Collection<UiccSlotMapping> uiccSlotMappings = mTelephonyManager.getSimSlotMapping();
|
||||||
|
for (UiccSlotMapping uiccSlotMapping :
|
||||||
|
uiccSlotMappings.stream()
|
||||||
|
.filter(
|
||||||
|
uiccSlotMapping -> uiccSlotMapping.getPhysicalSlotIndex()
|
||||||
|
== getTargetSlot())
|
||||||
|
.collect(Collectors.toList())) {
|
||||||
|
if (uiccSlotMapping.getPortIndex() == port) {
|
||||||
|
port++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getTargetSlot() {
|
||||||
|
return ESIM_SLOT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSwitchSlotSidecarStateChange() {
|
||||||
|
switch (mSwitchSlotSidecar.getState()) {
|
||||||
|
case State.SUCCESS:
|
||||||
|
mSwitchSlotSidecar.reset();
|
||||||
|
Log.i(TAG,
|
||||||
|
"Successfully SimSlotMapping. Start to enable/disable esim");
|
||||||
|
switchToSubscription();
|
||||||
|
break;
|
||||||
|
case State.ERROR:
|
||||||
|
mSwitchSlotSidecar.reset();
|
||||||
|
Log.i(TAG, "Failed to set SimSlotMapping");
|
||||||
|
setState(State.ERROR, Substate.UNUSED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMultipleEnabledProfilesSupported() {
|
||||||
|
List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo();
|
||||||
|
if (cardInfos == null) {
|
||||||
|
Log.w(TAG, "UICC cards info list is empty.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return cardInfos.stream().anyMatch(
|
||||||
|
cardInfo -> cardInfo.isMultipleEnabledProfilesSupported());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchToSubscription() {
|
||||||
|
// The SimSlotMapping is ready, then to execute activate/inactivate esim.
|
||||||
|
EuiccManager.ResultListener callback = new EuiccManager.ResultListener() {
|
||||||
|
@Override
|
||||||
|
public void onComplete(int resultCode, Intent resultIntent) {
|
||||||
|
Log.i(TAG, String.format("Result code : %d;", resultCode));
|
||||||
|
if (resultCode == EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK) {
|
||||||
|
setState(State.SUCCESS, Substate.UNUSED);
|
||||||
|
} else {
|
||||||
|
setState(State.ERROR, resultCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mEuiccManager.switchToSubscription(mSubId, mPort, getContext().getMainExecutor(),
|
||||||
|
callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar
|
|||||||
|
|
||||||
// Stateless members.
|
// Stateless members.
|
||||||
private SwitchToEuiccSubscriptionSidecar mSwitchToSubscriptionSidecar;
|
private SwitchToEuiccSubscriptionSidecar mSwitchToSubscriptionSidecar;
|
||||||
private SwitchSlotSidecar mSwitchSlotSidecar;
|
|
||||||
private int mPhysicalSlotId;
|
private int mPhysicalSlotId;
|
||||||
|
private SubscriptionInfo mRemovedSubInfo;
|
||||||
|
|
||||||
/** Returns a SwitchToRemovableSlotSidecar sidecar instance. */
|
/** Returns a SwitchToRemovableSlotSidecar sidecar instance. */
|
||||||
public static SwitchToRemovableSlotSidecar get(FragmentManager fm) {
|
public static SwitchToRemovableSlotSidecar get(FragmentManager fm) {
|
||||||
@@ -51,20 +51,17 @@ public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
mSwitchToSubscriptionSidecar =
|
mSwitchToSubscriptionSidecar =
|
||||||
SwitchToEuiccSubscriptionSidecar.get(getChildFragmentManager());
|
SwitchToEuiccSubscriptionSidecar.get(getChildFragmentManager());
|
||||||
mSwitchSlotSidecar = SwitchSlotSidecar.get(getChildFragmentManager());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mSwitchToSubscriptionSidecar.addListener(this);
|
mSwitchToSubscriptionSidecar.addListener(this);
|
||||||
mSwitchSlotSidecar.addListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
mSwitchToSubscriptionSidecar.removeListener(this);
|
mSwitchToSubscriptionSidecar.removeListener(this);
|
||||||
mSwitchSlotSidecar.removeListener(this);
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,29 +87,46 @@ public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar
|
|||||||
*
|
*
|
||||||
* @param physicalSlotId removable physical SIM slot ID.
|
* @param physicalSlotId removable physical SIM slot ID.
|
||||||
*/
|
*/
|
||||||
|
// ToDo: delete this api and refactor the related code.
|
||||||
public void run(int physicalSlotId) {
|
public void run(int physicalSlotId) {
|
||||||
mPhysicalSlotId = physicalSlotId;
|
mPhysicalSlotId = physicalSlotId;
|
||||||
SubscriptionManager subscriptionManager =
|
SubscriptionManager subscriptionManager =
|
||||||
getContext().getSystemService(SubscriptionManager.class);
|
getContext().getSystemService(SubscriptionManager.class);
|
||||||
if (SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream()
|
if (SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream()
|
||||||
.anyMatch(SubscriptionInfo::isEmbedded)) {
|
.anyMatch(SubscriptionInfo::isEmbedded)) {
|
||||||
|
// In SS mode, the esim is active, then inactivate the esim.
|
||||||
Log.i(TAG, "There is an active eSIM profile. Disable the profile first.");
|
Log.i(TAG, "There is an active eSIM profile. Disable the profile first.");
|
||||||
// Use INVALID_SUBSCRIPTION_ID to disable the only active profile.
|
// Use INVALID_SUBSCRIPTION_ID to disable the only active profile.
|
||||||
mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 0, null);
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "There is no active eSIM profiles. Start to switch to removable slot.");
|
Log.i(TAG, "There is no active eSIM profiles. Start to switch to removable slot.");
|
||||||
mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId);
|
mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts switching to the removable slot.
|
||||||
|
*
|
||||||
|
* @param physicalSlotId removable physical SIM slot ID.
|
||||||
|
* @param removedSubInfo if the all of slots have sims, it should remove the one of active sim.
|
||||||
|
* If the removedSubInfo is null, then use the default value.
|
||||||
|
* The default value is the removable physical SIM slot and portId 0.
|
||||||
|
*/
|
||||||
|
public void run(int physicalSlotId, SubscriptionInfo removedSubInfo) {
|
||||||
|
mPhysicalSlotId = physicalSlotId;
|
||||||
|
mRemovedSubInfo = removedSubInfo;
|
||||||
|
|
||||||
|
Log.i(TAG, "Start to switch to removable slot.");
|
||||||
|
mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId, mRemovedSubInfo);
|
||||||
|
}
|
||||||
|
|
||||||
private void onSwitchToSubscriptionSidecarStateChange() {
|
private void onSwitchToSubscriptionSidecarStateChange() {
|
||||||
switch (mSwitchToSubscriptionSidecar.getState()) {
|
switch (mSwitchToSubscriptionSidecar.getState()) {
|
||||||
case State.SUCCESS:
|
case State.SUCCESS:
|
||||||
mSwitchToSubscriptionSidecar.reset();
|
mSwitchToSubscriptionSidecar.reset();
|
||||||
Log.i(
|
Log.i(TAG,
|
||||||
TAG,
|
|
||||||
"Successfully disabled eSIM profile. Start to switch to Removable slot.");
|
"Successfully disabled eSIM profile. Start to switch to Removable slot.");
|
||||||
mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId);
|
mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId, mRemovedSubInfo);
|
||||||
break;
|
break;
|
||||||
case State.ERROR:
|
case State.ERROR:
|
||||||
mSwitchToSubscriptionSidecar.reset();
|
mSwitchToSubscriptionSidecar.reset();
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ package com.android.settings.network;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.telephony.UiccSlotInfo;
|
import android.telephony.UiccSlotInfo;
|
||||||
|
import android.telephony.UiccSlotMapping;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
@@ -29,17 +31,21 @@ import com.google.common.collect.ImmutableList;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
// ToDo: to do the refactor for renaming
|
||||||
public class UiccSlotUtil {
|
public class UiccSlotUtil {
|
||||||
|
|
||||||
private static final String TAG = "UiccSlotUtil";
|
private static final String TAG = "UiccSlotUtil";
|
||||||
|
|
||||||
private static final long DEFAULT_WAIT_AFTER_SWITCH_TIMEOUT_MILLIS = 25 * 1000L;
|
private static final long DEFAULT_WAIT_AFTER_SWITCH_TIMEOUT_MILLIS = 25 * 1000L;
|
||||||
;
|
|
||||||
|
|
||||||
public static final int INVALID_PHYSICAL_SLOT_ID = -1;
|
public static final int INVALID_PHYSICAL_SLOT_ID = -1;
|
||||||
|
public static final int INVALID_PORT_ID = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mode for switching to eSIM slot which decides whether there is cleanup process, e.g.
|
* Mode for switching to eSIM slot which decides whether there is cleanup process, e.g.
|
||||||
@@ -80,40 +86,104 @@ public class UiccSlotUtil {
|
|||||||
* @param context the application context.
|
* @param context the application context.
|
||||||
* @throws UiccSlotsException if there is an error.
|
* @throws UiccSlotsException if there is an error.
|
||||||
*/
|
*/
|
||||||
|
//ToDo: delete this api and refactor the related code.
|
||||||
public static synchronized void switchToRemovableSlot(int slotId, Context context)
|
public static synchronized void switchToRemovableSlot(int slotId, Context context)
|
||||||
throws UiccSlotsException {
|
throws UiccSlotsException {
|
||||||
|
switchToRemovableSlot(context, slotId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches to the removable slot. It waits for SIM_STATE_LOADED after switch. If slotId is
|
||||||
|
* INVALID_PHYSICAL_SLOT_ID, the method will use the first detected inactive removable slot.
|
||||||
|
*
|
||||||
|
* @param slotId the physical removable slot id.
|
||||||
|
* @param context the application context.
|
||||||
|
* @param removedSubInfo In the DSDS+MEP mode, if the all of slots have sims, it should
|
||||||
|
* remove the one of active sim.
|
||||||
|
* If the removedSubInfo is null, then use the default value.
|
||||||
|
* The default value is the esim slot and portId 0.
|
||||||
|
* @throws UiccSlotsException if there is an error.
|
||||||
|
*/
|
||||||
|
public static synchronized void switchToRemovableSlot(Context context, int slotId,
|
||||||
|
SubscriptionInfo removedSubInfo) throws UiccSlotsException {
|
||||||
if (ThreadUtils.isMainThread()) {
|
if (ThreadUtils.isMainThread()) {
|
||||||
throw new IllegalThreadStateException(
|
throw new IllegalThreadStateException(
|
||||||
"Do not call switchToRemovableSlot on the main thread.");
|
"Do not call switchToRemovableSlot on the main thread.");
|
||||||
}
|
}
|
||||||
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
|
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
|
||||||
if (telMgr.isMultiSimEnabled()) {
|
int inactiveRemovableSlot = getInactiveRemovableSlot(telMgr.getUiccSlotsInfo(), slotId);
|
||||||
// If this device supports multiple active slots, don't mess with TelephonyManager.
|
performSwitchToSlot(telMgr,
|
||||||
Log.i(TAG, "Multiple active slots supported. Not calling switchSlots.");
|
prepareUiccSlotMappingsForRemovableSlot(telMgr.getSimSlotMapping(),
|
||||||
return;
|
inactiveRemovableSlot, removedSubInfo, telMgr.isMultiSimEnabled()),
|
||||||
}
|
context);
|
||||||
UiccSlotInfo[] slots = telMgr.getUiccSlotsInfo();
|
|
||||||
if (slotId == INVALID_PHYSICAL_SLOT_ID) {
|
|
||||||
for (int i = 0; i < slots.length; i++) {
|
|
||||||
if (slots[i].isRemovable()
|
|
||||||
&& !slots[i].getPorts().stream().findFirst().get().isActive()
|
|
||||||
&& slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_ERROR
|
|
||||||
&& slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_RESTRICTED) {
|
|
||||||
performSwitchToRemovableSlot(i, context);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (slotId >= slots.length || !slots[slotId].isRemovable()) {
|
|
||||||
throw new UiccSlotsException("The given slotId is not a removable slot: " + slotId);
|
|
||||||
}
|
|
||||||
if (!slots[slotId].getPorts().stream().findFirst().get().isActive()) {
|
|
||||||
performSwitchToRemovableSlot(slotId, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void performSwitchToRemovableSlot(int slotId, Context context)
|
/**
|
||||||
|
* Switches to the Euicc slot. It waits for SIM_STATE_LOADED after switch.
|
||||||
|
*
|
||||||
|
* @param context the application context.
|
||||||
|
* @param slotId the Euicc slot id.
|
||||||
|
* @param port the Euicc slot port id.
|
||||||
|
* @param removedSubInfo In the DSDS+MEP mode, if the all of slots have sims, it should
|
||||||
|
* remove the one of active sim.
|
||||||
|
* If the removedSubInfo is null, then it uses the default value.
|
||||||
|
* The default value is the esim slot and portId 0.
|
||||||
|
* @throws UiccSlotsException if there is an error.
|
||||||
|
*/
|
||||||
|
public static synchronized void switchToEuiccSlot(Context context, int slotId, int port,
|
||||||
|
SubscriptionInfo removedSubInfo) throws UiccSlotsException {
|
||||||
|
if (ThreadUtils.isMainThread()) {
|
||||||
|
throw new IllegalThreadStateException(
|
||||||
|
"Do not call switchToRemovableSlot on the main thread.");
|
||||||
|
}
|
||||||
|
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
|
||||||
|
Collection<UiccSlotMapping> uiccSlotMappings = telMgr.getSimSlotMapping();
|
||||||
|
Log.i(TAG, "The SimSlotMapping: " + uiccSlotMappings);
|
||||||
|
|
||||||
|
if (isTargetSlotActive(uiccSlotMappings, slotId, port)) {
|
||||||
|
Log.i(TAG, "The slot is active, then the sim can enable directly.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<UiccSlotMapping> newUiccSlotMappings = new ArrayList<>();
|
||||||
|
if (!telMgr.isMultiSimEnabled()) {
|
||||||
|
// In the 'SS mode', the port is 0.
|
||||||
|
newUiccSlotMappings.add(new UiccSlotMapping(port, slotId, 0));
|
||||||
|
} else {
|
||||||
|
// DSDS+MEP
|
||||||
|
// The target slot+port is not active, but the all of logical slots are full. It
|
||||||
|
// needs to replace one of logical slots.
|
||||||
|
int removedSlot =
|
||||||
|
(removedSubInfo != null) ? removedSubInfo.getSimSlotIndex() : slotId;
|
||||||
|
int removedPort = (removedSubInfo != null) ? removedSubInfo.getPortIndex() : 0;
|
||||||
|
Log.i(TAG,
|
||||||
|
String.format("Start to set SimSlotMapping from slot%d-port%d to slot%d-port%d",
|
||||||
|
slotId, port, removedSlot, removedPort));
|
||||||
|
newUiccSlotMappings =
|
||||||
|
uiccSlotMappings.stream().map(uiccSlotMapping -> {
|
||||||
|
if (uiccSlotMapping.getPhysicalSlotIndex() == removedSlot
|
||||||
|
&& uiccSlotMapping.getPortIndex() == removedPort) {
|
||||||
|
return new UiccSlotMapping(port, slotId,
|
||||||
|
uiccSlotMapping.getLogicalSlotIndex());
|
||||||
|
}
|
||||||
|
return uiccSlotMapping;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "The SimSlotMapping: " + newUiccSlotMappings);
|
||||||
|
performSwitchToSlot(telMgr, newUiccSlotMappings, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isTargetSlotActive(Collection<UiccSlotMapping> uiccSlotMappings,
|
||||||
|
int slotId, int port) {
|
||||||
|
return uiccSlotMappings.stream()
|
||||||
|
.anyMatch(
|
||||||
|
uiccSlotMapping -> uiccSlotMapping.getPhysicalSlotIndex() == slotId
|
||||||
|
&& uiccSlotMapping.getPortIndex() == port);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void performSwitchToSlot(TelephonyManager telMgr,
|
||||||
|
Collection<UiccSlotMapping> uiccSlotMappings, Context context)
|
||||||
throws UiccSlotsException {
|
throws UiccSlotsException {
|
||||||
CarrierConfigChangedReceiver receiver = null;
|
CarrierConfigChangedReceiver receiver = null;
|
||||||
long waitingTimeMillis =
|
long waitingTimeMillis =
|
||||||
@@ -125,7 +195,7 @@ public class UiccSlotUtil {
|
|||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
receiver = new CarrierConfigChangedReceiver(latch);
|
receiver = new CarrierConfigChangedReceiver(latch);
|
||||||
receiver.registerOn(context);
|
receiver.registerOn(context);
|
||||||
switchSlots(context, slotId);
|
telMgr.setSimSlotMapping(uiccSlotMappings);
|
||||||
latch.await(waitingTimeMillis, TimeUnit.MILLISECONDS);
|
latch.await(waitingTimeMillis, TimeUnit.MILLISECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
@@ -138,22 +208,80 @@ public class UiccSlotUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the logical slot to physical slot mapping. OEM should override this to provide
|
* @param slots The UiccSlotInfo list.
|
||||||
* device-specific implementation if the device supports switching slots.
|
* @param slotId The physical removable slot id.
|
||||||
*
|
* @return The inactive physical removable slot id. If the physical removable slot id is
|
||||||
* @param context the application context.
|
* active, then return -1.
|
||||||
* @param physicalSlots List of physical slot ids in the order of logical slots.
|
* @throws UiccSlotsException if there is an error.
|
||||||
*/
|
*/
|
||||||
private static void switchSlots(Context context, int... physicalSlots)
|
private static int getInactiveRemovableSlot(UiccSlotInfo[] slots, int slotId)
|
||||||
throws UiccSlotsException {
|
throws UiccSlotsException {
|
||||||
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
|
if (slots == null) {
|
||||||
if (telMgr.isMultiSimEnabled()) {
|
throw new UiccSlotsException("UiccSlotInfo is null");
|
||||||
// If this device supports multiple active slots, don't mess with TelephonyManager.
|
|
||||||
Log.i(TAG, "Multiple active slots supported. Not calling switchSlots.");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!telMgr.switchSlots(physicalSlots)) {
|
if (slotId == INVALID_PHYSICAL_SLOT_ID) {
|
||||||
throw new UiccSlotsException("Failed to switch slots");
|
for (int i = 0; i < slots.length; i++) {
|
||||||
|
if (slots[i].isRemovable()
|
||||||
|
&& !slots[i].getPorts().stream().findFirst().get().isActive()
|
||||||
|
&& slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_ERROR
|
||||||
|
&& slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_RESTRICTED) {
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (slotId >= slots.length || !slots[slotId].isRemovable()) {
|
||||||
|
throw new UiccSlotsException("The given slotId is not a removable slot: " + slotId);
|
||||||
|
}
|
||||||
|
if (!slots[slotId].getPorts().stream().findFirst().get().isActive()) {
|
||||||
|
return slotId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INVALID_PHYSICAL_SLOT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<UiccSlotMapping> prepareUiccSlotMappingsForRemovableSlot(
|
||||||
|
Collection<UiccSlotMapping> uiccSlotMappings, int slotId,
|
||||||
|
SubscriptionInfo removedSubInfo, boolean isMultiSimEnabled) {
|
||||||
|
if (slotId == INVALID_PHYSICAL_SLOT_ID
|
||||||
|
|| uiccSlotMappings.stream().anyMatch(uiccSlotMapping ->
|
||||||
|
uiccSlotMapping.getPhysicalSlotIndex() == slotId
|
||||||
|
&& uiccSlotMapping.getPortIndex() == 0)) {
|
||||||
|
// The slot is invalid slot id, then to skip this.
|
||||||
|
// The slot is active, then the sim can enable directly.
|
||||||
|
return uiccSlotMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<UiccSlotMapping> newUiccSlotMappings = new ArrayList<>();
|
||||||
|
if (!isMultiSimEnabled) {
|
||||||
|
// In the 'SS mode', the port is 0.
|
||||||
|
newUiccSlotMappings.add(new UiccSlotMapping(0, slotId, 0));
|
||||||
|
} else if (removedSubInfo != null) {
|
||||||
|
// DSDS+MEP
|
||||||
|
// The target slot+port is not active, but the all of logical slots are full. It
|
||||||
|
// needs to replace one of logical slots.
|
||||||
|
Log.i(TAG,
|
||||||
|
String.format("Start to set SimSlotMapping from slot%d-port%d to slot%d-port%d",
|
||||||
|
slotId, 0, removedSubInfo.getSimSlotIndex(),
|
||||||
|
removedSubInfo.getPortIndex()));
|
||||||
|
newUiccSlotMappings =
|
||||||
|
uiccSlotMappings.stream().map(uiccSlotMapping -> {
|
||||||
|
if (uiccSlotMapping.getPhysicalSlotIndex()
|
||||||
|
== removedSubInfo.getSimSlotIndex()
|
||||||
|
&& uiccSlotMapping.getPortIndex()
|
||||||
|
== removedSubInfo.getPortIndex()) {
|
||||||
|
return new UiccSlotMapping(0, slotId,
|
||||||
|
uiccSlotMapping.getLogicalSlotIndex());
|
||||||
|
}
|
||||||
|
return uiccSlotMapping;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
// DSDS+no MEP
|
||||||
|
// The removable slot should be in UiccSlotMapping.
|
||||||
|
newUiccSlotMappings = uiccSlotMappings;
|
||||||
|
Log.i(TAG, "The removedSubInfo is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "The SimSlotMapping: " + newUiccSlotMappings);
|
||||||
|
return newUiccSlotMappings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,14 @@
|
|||||||
|
|
||||||
package com.android.settings.network.telephony;
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
/** Fragment to show an alert dialog which only has the positive button. */
|
/** Fragment to show an alert dialog which only has the positive button. */
|
||||||
public class AlertDialogFragment extends BaseDialogFragment
|
public class AlertDialogFragment extends BaseDialogFragment
|
||||||
implements DialogInterface.OnClickListener {
|
implements DialogInterface.OnClickListener {
|
||||||
@@ -37,13 +38,13 @@ public class AlertDialogFragment extends BaseDialogFragment
|
|||||||
* @param title
|
* @param title
|
||||||
* @param msg
|
* @param msg
|
||||||
*/
|
*/
|
||||||
public static void show(Activity activity, String title, String msg) {
|
public static void show(FragmentActivity activity, String title, String msg) {
|
||||||
AlertDialogFragment fragment = new AlertDialogFragment();
|
AlertDialogFragment fragment = new AlertDialogFragment();
|
||||||
Bundle arguments = new Bundle();
|
Bundle arguments = new Bundle();
|
||||||
arguments.putString(ARG_TITLE, title);
|
arguments.putString(ARG_TITLE, title);
|
||||||
arguments.putString(ARG_MSG, msg);
|
arguments.putString(ARG_MSG, msg);
|
||||||
fragment.setArguments(arguments);
|
fragment.setArguments(arguments);
|
||||||
fragment.show(activity.getFragmentManager(), TAG);
|
fragment.show(activity.getSupportFragmentManager(), TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -55,7 +56,7 @@ public class AlertDialogFragment extends BaseDialogFragment
|
|||||||
if (!TextUtils.isEmpty(getArguments().getString(ARG_MSG))) {
|
if (!TextUtils.isEmpty(getArguments().getString(ARG_MSG))) {
|
||||||
builder.setMessage(getArguments().getString(ARG_MSG));
|
builder.setMessage(getArguments().getString(ARG_MSG));
|
||||||
}
|
}
|
||||||
return builder.show();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -17,11 +17,11 @@
|
|||||||
package com.android.settings.network.telephony;
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.DialogFragment;
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base dialog fragment class with the functionality to make a fragment or an activity as a listener
|
* Base dialog fragment class with the functionality to make a fragment or an activity as a listener
|
||||||
|
|||||||
@@ -16,13 +16,24 @@
|
|||||||
|
|
||||||
package com.android.settings.network.telephony;
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/** Fragment to show a confirm dialog. The caller should implement onConfirmListener. */
|
/** Fragment to show a confirm dialog. The caller should implement onConfirmListener. */
|
||||||
public class ConfirmDialogFragment extends BaseDialogFragment
|
public class ConfirmDialogFragment extends BaseDialogFragment
|
||||||
@@ -32,6 +43,7 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
|||||||
private static final String ARG_MSG = "msg";
|
private static final String ARG_MSG = "msg";
|
||||||
private static final String ARG_POS_BUTTON_STRING = "pos_button_string";
|
private static final String ARG_POS_BUTTON_STRING = "pos_button_string";
|
||||||
private static final String ARG_NEG_BUTTON_STRING = "neg_button_string";
|
private static final String ARG_NEG_BUTTON_STRING = "neg_button_string";
|
||||||
|
private static final String ARG_LIST = "list";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface defining the method that will be invoked when the user has done with the dialog.
|
* Interface defining the method that will be invoked when the user has done with the dialog.
|
||||||
@@ -39,15 +51,19 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
|||||||
public interface OnConfirmListener {
|
public interface OnConfirmListener {
|
||||||
/**
|
/**
|
||||||
* @param tag The tag in the caller.
|
* @param tag The tag in the caller.
|
||||||
* @param confirmed True if the user has clicked the positive button. False if the user has
|
* @param confirmed True if the user has clicked the positive button. False if the
|
||||||
|
* user has
|
||||||
* clicked the negative button or cancel the dialog.
|
* clicked the negative button or cancel the dialog.
|
||||||
|
* @param itemPosition It is the position of item, if user selects one of the list item.
|
||||||
|
* If the user select "cancel" or the dialog does not have list, then
|
||||||
|
* the value is -1.
|
||||||
*/
|
*/
|
||||||
void onConfirm(int tag, boolean confirmed);
|
void onConfirm(int tag, boolean confirmed, int itemPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Displays a confirmation dialog which has confirm and cancel buttons. */
|
/** Displays a confirmation dialog which has confirm and cancel buttons. */
|
||||||
public static <T> void show(
|
public static <T> void show(
|
||||||
Activity activity,
|
FragmentActivity activity,
|
||||||
Class<T> callbackInterfaceClass,
|
Class<T> callbackInterfaceClass,
|
||||||
int tagInCaller,
|
int tagInCaller,
|
||||||
String title,
|
String title,
|
||||||
@@ -62,7 +78,29 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
|||||||
arguments.putString(ARG_NEG_BUTTON_STRING, negButtonString);
|
arguments.putString(ARG_NEG_BUTTON_STRING, negButtonString);
|
||||||
setListener(activity, null, callbackInterfaceClass, tagInCaller, arguments);
|
setListener(activity, null, callbackInterfaceClass, tagInCaller, arguments);
|
||||||
fragment.setArguments(arguments);
|
fragment.setArguments(arguments);
|
||||||
fragment.show(activity.getFragmentManager(), TAG);
|
fragment.show(activity.getSupportFragmentManager(), TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Displays a confirmation dialog which has confirm and cancel buttons and carrier list.*/
|
||||||
|
public static <T> void show(
|
||||||
|
FragmentActivity activity,
|
||||||
|
Class<T> callbackInterfaceClass,
|
||||||
|
int tagInCaller,
|
||||||
|
String title,
|
||||||
|
String msg,
|
||||||
|
String posButtonString,
|
||||||
|
String negButtonString,
|
||||||
|
ArrayList<String> list) {
|
||||||
|
ConfirmDialogFragment fragment = new ConfirmDialogFragment();
|
||||||
|
Bundle arguments = new Bundle();
|
||||||
|
arguments.putString(ARG_TITLE, title);
|
||||||
|
arguments.putCharSequence(ARG_MSG, msg);
|
||||||
|
arguments.putString(ARG_POS_BUTTON_STRING, posButtonString);
|
||||||
|
arguments.putString(ARG_NEG_BUTTON_STRING, negButtonString);
|
||||||
|
arguments.putStringArrayList(ARG_LIST, list);
|
||||||
|
setListener(activity, null, callbackInterfaceClass, tagInCaller, arguments);
|
||||||
|
fragment.setArguments(arguments);
|
||||||
|
fragment.show(activity.getSupportFragmentManager(), TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -71,37 +109,77 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
|||||||
String message = getArguments().getString(ARG_MSG);
|
String message = getArguments().getString(ARG_MSG);
|
||||||
String posBtnString = getArguments().getString(ARG_POS_BUTTON_STRING);
|
String posBtnString = getArguments().getString(ARG_POS_BUTTON_STRING);
|
||||||
String negBtnString = getArguments().getString(ARG_NEG_BUTTON_STRING);
|
String negBtnString = getArguments().getString(ARG_NEG_BUTTON_STRING);
|
||||||
|
ArrayList<String> list = getArguments().getStringArrayList(ARG_LIST);
|
||||||
|
|
||||||
Log.i("Showing dialog with title = %s", title);
|
Log.i(TAG, "Showing dialog with title =" + title);
|
||||||
AlertDialog.Builder builder =
|
AlertDialog.Builder builder =
|
||||||
new AlertDialog.Builder(getContext())
|
new AlertDialog.Builder(getContext())
|
||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
.setPositiveButton(posBtnString, this)
|
.setPositiveButton(posBtnString, this)
|
||||||
.setNegativeButton(negBtnString, this);
|
.setNegativeButton(negBtnString, this);
|
||||||
|
|
||||||
|
if (list != null && !list.isEmpty()) {
|
||||||
|
Log.i(TAG, "list =" + list.toString());
|
||||||
|
|
||||||
|
View content = LayoutInflater.from(getContext()).inflate(
|
||||||
|
R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
|
||||||
|
|
||||||
|
TextView dialogMessage = content.findViewById(R.id.msg);
|
||||||
|
if (!TextUtils.isEmpty(message) && dialogMessage != null) {
|
||||||
|
dialogMessage.setText(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ArrayAdapter<String> arrayAdapterItems = new ArrayAdapter<String>(
|
||||||
|
getContext(), android.R.layout.select_dialog_item, list);
|
||||||
|
final ListView lvItems = content.findViewById(R.id.carrier_list);
|
||||||
|
if (lvItems != null) {
|
||||||
|
lvItems.setAdapter(arrayAdapterItems);
|
||||||
|
lvItems.setChoiceMode(ListView.CHOICE_MODE_NONE);
|
||||||
|
lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||||
|
long id) {
|
||||||
|
Log.i(TAG, "list onClick =" + position);
|
||||||
|
Log.i(TAG, "list item =" + list.get(position));
|
||||||
|
|
||||||
|
if (position == list.size() - 1) {
|
||||||
|
// user select the "cancel" item;
|
||||||
|
informCaller(false, -1);
|
||||||
|
} else {
|
||||||
|
informCaller(true, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
builder.setView(content);
|
||||||
|
} else {
|
||||||
if (!TextUtils.isEmpty(message)) {
|
if (!TextUtils.isEmpty(message)) {
|
||||||
builder.setMessage(message);
|
builder.setMessage(message);
|
||||||
}
|
}
|
||||||
AlertDialog dialog = builder.show();
|
}
|
||||||
|
|
||||||
|
AlertDialog dialog = builder.create();
|
||||||
dialog.setCanceledOnTouchOutside(false);
|
dialog.setCanceledOnTouchOutside(false);
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
informCaller(which == DialogInterface.BUTTON_POSITIVE);
|
Log.i(TAG, "dialog onClick =" + which);
|
||||||
|
|
||||||
|
informCaller(which == DialogInterface.BUTTON_POSITIVE, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCancel(DialogInterface dialog) {
|
public void onCancel(DialogInterface dialog) {
|
||||||
informCaller(false);
|
informCaller(false, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void informCaller(boolean confirmed) {
|
private void informCaller(boolean confirmed, int itemPosition) {
|
||||||
OnConfirmListener listener = getListener(OnConfirmListener.class);
|
OnConfirmListener listener = getListener(OnConfirmListener.class);
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
listener.onConfirm(getTagInCaller(), confirmed);
|
listener.onConfirm(getTagInCaller(), confirmed, itemPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class DeleteEuiccSubscriptionDialogActivity extends SubscriptionActionDia
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfirm(int tag, boolean confirmed) {
|
public void onConfirm(int tag, boolean confirmed, int itemPosition) {
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -24,10 +24,12 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
import android.telephony.euicc.EuiccManager;
|
import android.telephony.euicc.EuiccManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settings.SidecarFragment;
|
import com.android.settings.SidecarFragment;
|
||||||
|
import com.android.settings.network.SwitchSlotSidecar;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@@ -37,7 +39,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
* should implement its own get() function to return an instance of that class, and implement the
|
* should implement its own get() function to return an instance of that class, and implement the
|
||||||
* functional class like run() to actually trigger the function in EuiccManager.
|
* functional class like run() to actually trigger the function in EuiccManager.
|
||||||
*/
|
*/
|
||||||
public abstract class EuiccOperationSidecar extends SidecarFragment {
|
public abstract class EuiccOperationSidecar extends SidecarFragment
|
||||||
|
implements SidecarFragment.Listener{
|
||||||
private static final String TAG = "EuiccOperationSidecar";
|
private static final String TAG = "EuiccOperationSidecar";
|
||||||
private static final int REQUEST_CODE = 0;
|
private static final int REQUEST_CODE = 0;
|
||||||
private static final String EXTRA_OP_ID = "op_id";
|
private static final String EXTRA_OP_ID = "op_id";
|
||||||
@@ -45,6 +48,9 @@ public abstract class EuiccOperationSidecar extends SidecarFragment {
|
|||||||
new AtomicInteger((int) SystemClock.elapsedRealtime());
|
new AtomicInteger((int) SystemClock.elapsedRealtime());
|
||||||
|
|
||||||
protected EuiccManager mEuiccManager;
|
protected EuiccManager mEuiccManager;
|
||||||
|
protected TelephonyManager mTelephonyManager;
|
||||||
|
protected SwitchSlotSidecar mSwitchSlotSidecar;
|
||||||
|
|
||||||
|
|
||||||
private int mResultCode;
|
private int mResultCode;
|
||||||
private int mDetailedCode;
|
private int mDetailedCode;
|
||||||
@@ -107,6 +113,8 @@ public abstract class EuiccOperationSidecar extends SidecarFragment {
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
mEuiccManager = getContext().getSystemService(EuiccManager.class);
|
mEuiccManager = getContext().getSystemService(EuiccManager.class);
|
||||||
|
mTelephonyManager = getContext().getSystemService(TelephonyManager.class);
|
||||||
|
mSwitchSlotSidecar = SwitchSlotSidecar.get(getChildFragmentManager());
|
||||||
|
|
||||||
getContext()
|
getContext()
|
||||||
.getApplicationContext()
|
.getApplicationContext()
|
||||||
@@ -118,12 +126,42 @@ public abstract class EuiccOperationSidecar extends SidecarFragment {
|
|||||||
Context.RECEIVER_EXPORTED);
|
Context.RECEIVER_EXPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
mSwitchSlotSidecar.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
mSwitchSlotSidecar.removeListener(this);
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
getContext().getApplicationContext().unregisterReceiver(mReceiver);
|
getContext().getApplicationContext().unregisterReceiver(mReceiver);
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStateChange(SidecarFragment fragment) {
|
||||||
|
if (fragment == mSwitchSlotSidecar) {
|
||||||
|
switch (mSwitchSlotSidecar.getState()) {
|
||||||
|
case State.SUCCESS:
|
||||||
|
mSwitchSlotSidecar.reset();
|
||||||
|
Log.i(TAG, "mSwitchSlotSidecar SUCCESS");
|
||||||
|
break;
|
||||||
|
case State.ERROR:
|
||||||
|
mSwitchSlotSidecar.reset();
|
||||||
|
Log.i(TAG, "mSwitchSlotSidecar ERROR");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.wtf(TAG, "Received state change from a sidecar not expected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getResultCode() {
|
public int getResultCode() {
|
||||||
return mResultCode;
|
return mResultCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,13 @@
|
|||||||
|
|
||||||
package com.android.settings.network.telephony;
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
/** The base class for subscription action dialogs */
|
/** The base class for subscription action dialogs */
|
||||||
public class SubscriptionActionDialogActivity extends Activity {
|
public class SubscriptionActionDialogActivity extends FragmentActivity {
|
||||||
|
|
||||||
private static final String TAG = "SubscriptionActionDialogActivity";
|
private static final String TAG = "SubscriptionActionDialogActivity";
|
||||||
// Arguments
|
// Arguments
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.os.UserManager;
|
|||||||
import android.telephony.SubscriptionInfo;
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.telephony.UiccCardInfo;
|
||||||
import android.telephony.UiccSlotInfo;
|
import android.telephony.UiccSlotInfo;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -40,7 +41,9 @@ import com.android.settings.sim.SimActivationNotifier;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/** This dialog activity handles both eSIM and pSIM subscriptions enabling and disabling. */
|
/** This dialog activity handles both eSIM and pSIM subscriptions enabling and disabling. */
|
||||||
public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogActivity
|
public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogActivity
|
||||||
@@ -55,6 +58,8 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
private static final int DIALOG_TAG_ENABLE_SIM_CONFIRMATION = 2;
|
private static final int DIALOG_TAG_ENABLE_SIM_CONFIRMATION = 2;
|
||||||
private static final int DIALOG_TAG_ENABLE_DSDS_CONFIRMATION = 3;
|
private static final int DIALOG_TAG_ENABLE_DSDS_CONFIRMATION = 3;
|
||||||
private static final int DIALOG_TAG_ENABLE_DSDS_REBOOT_CONFIRMATION = 4;
|
private static final int DIALOG_TAG_ENABLE_DSDS_REBOOT_CONFIRMATION = 4;
|
||||||
|
private static final int DIALOG_TAG_ENABLE_SIM_CONFIRMATION_MEP = 5;
|
||||||
|
|
||||||
// Number of SIMs for DSDS
|
// Number of SIMs for DSDS
|
||||||
private static final int NUM_OF_SIMS_FOR_DSDS = 2;
|
private static final int NUM_OF_SIMS_FOR_DSDS = 2;
|
||||||
// Support RTL mode
|
// Support RTL mode
|
||||||
@@ -85,11 +90,11 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
private boolean mIsEsimOperation;
|
private boolean mIsEsimOperation;
|
||||||
private TelephonyManager mTelMgr;
|
private TelephonyManager mTelMgr;
|
||||||
private boolean isRtlMode;
|
private boolean isRtlMode;
|
||||||
|
private List<SubscriptionInfo> mActiveSubInfos;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
int subId = intent.getIntExtra(ARG_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
int subId = intent.getIntExtra(ARG_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||||
mTelMgr = getSystemService(TelephonyManager.class);
|
mTelMgr = getSystemService(TelephonyManager.class);
|
||||||
@@ -107,6 +112,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mActiveSubInfos = SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager);
|
||||||
mSubInfo = SubscriptionUtil.getSubById(mSubscriptionManager, subId);
|
mSubInfo = SubscriptionUtil.getSubById(mSubscriptionManager, subId);
|
||||||
mIsEsimOperation = mSubInfo != null && mSubInfo.isEmbedded();
|
mIsEsimOperation = mSubInfo != null && mSubInfo.isEmbedded();
|
||||||
mSwitchToEuiccSubscriptionSidecar =
|
mSwitchToEuiccSubscriptionSidecar =
|
||||||
@@ -116,6 +122,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
mEnable = intent.getBooleanExtra(ARG_enable, true);
|
mEnable = intent.getBooleanExtra(ARG_enable, true);
|
||||||
isRtlMode = getResources().getConfiguration().getLayoutDirection()
|
isRtlMode = getResources().getConfiguration().getLayoutDirection()
|
||||||
== View.LAYOUT_DIRECTION_RTL;
|
== View.LAYOUT_DIRECTION_RTL;
|
||||||
|
Log.i(TAG, "isMultipleEnabledProfilesSupported():" + isMultipleEnabledProfilesSupported());
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
if (mEnable) {
|
if (mEnable) {
|
||||||
@@ -154,7 +161,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfirm(int tag, boolean confirmed) {
|
public void onConfirm(int tag, boolean confirmed, int itemPosition) {
|
||||||
if (!confirmed
|
if (!confirmed
|
||||||
&& tag != DIALOG_TAG_ENABLE_DSDS_CONFIRMATION
|
&& tag != DIALOG_TAG_ENABLE_DSDS_CONFIRMATION
|
||||||
&& tag != DIALOG_TAG_ENABLE_DSDS_REBOOT_CONFIRMATION) {
|
&& tag != DIALOG_TAG_ENABLE_DSDS_REBOOT_CONFIRMATION) {
|
||||||
@@ -162,14 +169,16 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SubscriptionInfo removedSubInfo = null;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case DIALOG_TAG_DISABLE_SIM_CONFIRMATION:
|
case DIALOG_TAG_DISABLE_SIM_CONFIRMATION:
|
||||||
if (mIsEsimOperation) {
|
if (mIsEsimOperation) {
|
||||||
Log.i(TAG, "Disabling the eSIM profile.");
|
Log.i(TAG, "Disabling the eSIM profile.");
|
||||||
showProgressDialog(
|
showProgressDialog(
|
||||||
getString(R.string.privileged_action_disable_sub_dialog_progress));
|
getString(R.string.privileged_action_disable_sub_dialog_progress));
|
||||||
|
int port = mSubInfo != null ? mSubInfo.getPortIndex() : 0;
|
||||||
mSwitchToEuiccSubscriptionSidecar.run(
|
mSwitchToEuiccSubscriptionSidecar.run(
|
||||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
SubscriptionManager.INVALID_SUBSCRIPTION_ID, port, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Disabling the pSIM profile.");
|
Log.i(TAG, "Disabling the pSIM profile.");
|
||||||
@@ -201,6 +210,11 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
SimActivationNotifier.setShowSimSettingsNotification(this, true);
|
SimActivationNotifier.setShowSimSettingsNotification(this, true);
|
||||||
mTelMgr.switchMultiSimConfig(NUM_OF_SIMS_FOR_DSDS);
|
mTelMgr.switchMultiSimConfig(NUM_OF_SIMS_FOR_DSDS);
|
||||||
break;
|
break;
|
||||||
|
case DIALOG_TAG_ENABLE_SIM_CONFIRMATION_MEP:
|
||||||
|
if (itemPosition != -1) {
|
||||||
|
removedSubInfo = (mActiveSubInfos != null) ? mActiveSubInfos.get(itemPosition)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
case DIALOG_TAG_ENABLE_SIM_CONFIRMATION:
|
case DIALOG_TAG_ENABLE_SIM_CONFIRMATION:
|
||||||
Log.i(TAG, "User confirmed to enable the subscription.");
|
Log.i(TAG, "User confirmed to enable the subscription.");
|
||||||
if (mIsEsimOperation) {
|
if (mIsEsimOperation) {
|
||||||
@@ -209,12 +223,15 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
R.string.sim_action_switch_sub_dialog_progress,
|
R.string.sim_action_switch_sub_dialog_progress,
|
||||||
SubscriptionUtil.getUniqueSubscriptionDisplayName(
|
SubscriptionUtil.getUniqueSubscriptionDisplayName(
|
||||||
mSubInfo, this)));
|
mSubInfo, this)));
|
||||||
mSwitchToEuiccSubscriptionSidecar.run(mSubInfo.getSubscriptionId());
|
mSwitchToEuiccSubscriptionSidecar.run(mSubInfo.getSubscriptionId(),
|
||||||
|
UiccSlotUtil.INVALID_PORT_ID,
|
||||||
|
removedSubInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
showProgressDialog(
|
showProgressDialog(
|
||||||
getString(R.string.sim_action_enabling_sim_without_carrier_name));
|
getString(R.string.sim_action_enabling_sim_without_carrier_name));
|
||||||
mSwitchToRemovableSlotSidecar.run(UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID);
|
mSwitchToRemovableSlotSidecar.run(UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID,
|
||||||
|
removedSubInfo);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(TAG, "Unrecognized confirmation dialog tag: " + tag);
|
Log.e(TAG, "Unrecognized confirmation dialog tag: " + tag);
|
||||||
@@ -225,8 +242,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
private void handleSwitchToEuiccSubscriptionSidecarStateChange() {
|
private void handleSwitchToEuiccSubscriptionSidecarStateChange() {
|
||||||
switch (mSwitchToEuiccSubscriptionSidecar.getState()) {
|
switch (mSwitchToEuiccSubscriptionSidecar.getState()) {
|
||||||
case SidecarFragment.State.SUCCESS:
|
case SidecarFragment.State.SUCCESS:
|
||||||
Log.i(
|
Log.i(TAG,
|
||||||
TAG,
|
|
||||||
String.format(
|
String.format(
|
||||||
"Successfully %s the eSIM profile.",
|
"Successfully %s the eSIM profile.",
|
||||||
mEnable ? "enable" : "disable"));
|
mEnable ? "enable" : "disable"));
|
||||||
@@ -235,8 +251,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
finish();
|
finish();
|
||||||
break;
|
break;
|
||||||
case SidecarFragment.State.ERROR:
|
case SidecarFragment.State.ERROR:
|
||||||
Log.i(
|
Log.i(TAG,
|
||||||
TAG,
|
|
||||||
String.format(
|
String.format(
|
||||||
"Failed to %s the eSIM profile.", mEnable ? "enable" : "disable"));
|
"Failed to %s the eSIM profile.", mEnable ? "enable" : "disable"));
|
||||||
mSwitchToEuiccSubscriptionSidecar.reset();
|
mSwitchToEuiccSubscriptionSidecar.reset();
|
||||||
@@ -290,7 +305,8 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
if (mIsEsimOperation) {
|
if (mIsEsimOperation) {
|
||||||
Log.i(TAG, "DSDS enabled, start to enable profile: " + mSubInfo.getSubscriptionId());
|
Log.i(TAG, "DSDS enabled, start to enable profile: " + mSubInfo.getSubscriptionId());
|
||||||
// For eSIM operations, we simply switch to the selected eSIM profile.
|
// For eSIM operations, we simply switch to the selected eSIM profile.
|
||||||
mSwitchToEuiccSubscriptionSidecar.run(mSubInfo.getSubscriptionId());
|
mSwitchToEuiccSubscriptionSidecar.run(mSubInfo.getSubscriptionId(),
|
||||||
|
UiccSlotUtil.INVALID_PORT_ID, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,9 +321,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
mSubscriptionManager.setUiccApplicationsEnabled(mSubInfo.getSubscriptionId(), mEnable);
|
mSubscriptionManager.setUiccApplicationsEnabled(mSubInfo.getSubscriptionId(), mEnable);
|
||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
Log.i(
|
Log.i(TAG, "The device does not support toggling pSIM. It is enough to just "
|
||||||
TAG,
|
|
||||||
"The device does not support toggling pSIM. It is enough to just "
|
|
||||||
+ "enable the removable slot.");
|
+ "enable the removable slot.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,7 +333,10 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
showEnableDsdsConfirmDialog();
|
showEnableDsdsConfirmDialog();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!mIsEsimOperation && mTelMgr.isMultiSimEnabled()) {
|
if (!mIsEsimOperation && mTelMgr.isMultiSimEnabled()
|
||||||
|
&& isRemovableSimEnabled()) {
|
||||||
|
// This case is for switching on psim when device is not multiple enable profile
|
||||||
|
// supported.
|
||||||
Log.i(TAG, "Toggle on pSIM, no dialog displayed.");
|
Log.i(TAG, "Toggle on pSIM, no dialog displayed.");
|
||||||
handleTogglePsimAction();
|
handleTogglePsimAction();
|
||||||
finish();
|
finish();
|
||||||
@@ -372,27 +389,55 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showEnableSimConfirmDialog() {
|
private void showEnableSimConfirmDialog() {
|
||||||
List<SubscriptionInfo> activeSubs =
|
if (mActiveSubInfos == null || mActiveSubInfos.isEmpty()) {
|
||||||
SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager);
|
|
||||||
SubscriptionInfo activeSub = activeSubs.isEmpty() ? null : activeSubs.get(0);
|
|
||||||
if (activeSub == null) {
|
|
||||||
Log.i(TAG, "No active subscriptions available.");
|
Log.i(TAG, "No active subscriptions available.");
|
||||||
showNonSwitchSimConfirmDialog();
|
showNonSwitchSimConfirmDialog();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Found active subscription.");
|
Log.i(TAG, "mActiveSubInfos:" + mActiveSubInfos);
|
||||||
boolean isBetweenEsim = mIsEsimOperation && activeSub.isEmbedded();
|
|
||||||
if (mTelMgr.isMultiSimEnabled() && !isBetweenEsim) {
|
boolean isSwitchingBetweenEsims = mIsEsimOperation
|
||||||
|
&& mActiveSubInfos.stream().anyMatch(activeSubInfo -> activeSubInfo.isEmbedded());
|
||||||
|
boolean isMultiSimEnabled = mTelMgr.isMultiSimEnabled();
|
||||||
|
if (isMultiSimEnabled
|
||||||
|
&& !isMultipleEnabledProfilesSupported()
|
||||||
|
&& !isSwitchingBetweenEsims) {
|
||||||
|
// Showing the "no switch dialog" for below cases.
|
||||||
|
// DSDS mode + no MEP +
|
||||||
|
// (there is the active psim -> esim switch on => active (psim + esim))
|
||||||
showNonSwitchSimConfirmDialog();
|
showNonSwitchSimConfirmDialog();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isMultiSimEnabled && isMultipleEnabledProfilesSupported()) {
|
||||||
|
if (mActiveSubInfos.size() < NUM_OF_SIMS_FOR_DSDS) {
|
||||||
|
// The sim can add into device directly, so showing the "no switch dialog".
|
||||||
|
// DSDS + MEP + (active sim < NUM_OF_SIMS_FOR_DSDS)
|
||||||
|
showNonSwitchSimConfirmDialog();
|
||||||
|
} else {
|
||||||
|
// The all of slots have sim, it needs to show the "MEP switch dialog".
|
||||||
|
// DSDS + MEP + two active sims
|
||||||
|
showMepSwitchSimConfirmDialog();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Showing the "switch dialog" for below cases.
|
||||||
|
// case1: SS mode + psim switch on from esim.
|
||||||
|
// case2: SS mode + esim switch from psim.
|
||||||
|
// case3: DSDS mode + No MEP + esim switch on from another esim.
|
||||||
|
SubscriptionInfo activeSub =
|
||||||
|
(isMultiSimEnabled && isSwitchingBetweenEsims)
|
||||||
|
? mActiveSubInfos.stream()
|
||||||
|
.filter(activeSubInfo -> activeSubInfo.isEmbedded())
|
||||||
|
.findFirst().get()
|
||||||
|
: mActiveSubInfos.get(0);
|
||||||
ConfirmDialogFragment.show(
|
ConfirmDialogFragment.show(
|
||||||
this,
|
this,
|
||||||
ConfirmDialogFragment.OnConfirmListener.class,
|
ConfirmDialogFragment.OnConfirmListener.class,
|
||||||
DIALOG_TAG_ENABLE_SIM_CONFIRMATION,
|
DIALOG_TAG_ENABLE_SIM_CONFIRMATION,
|
||||||
getSwitchSubscriptionTitle(),
|
getSwitchSubscriptionTitle(),
|
||||||
getSwitchDialogBodyMsg(activeSub, isBetweenEsim),
|
getSwitchDialogBodyMsg(activeSub, isSwitchingBetweenEsims),
|
||||||
getSwitchDialogPosBtnText(),
|
getSwitchDialogPosBtnText(),
|
||||||
getString(R.string.sim_action_cancel));
|
getString(R.string.sim_action_cancel));
|
||||||
}
|
}
|
||||||
@@ -408,6 +453,35 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
getString(R.string.sim_action_cancel));
|
getString(R.string.sim_action_cancel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showMepSwitchSimConfirmDialog() {
|
||||||
|
Log.i(TAG, "showMepSwitchSimConfirmDialog");
|
||||||
|
final CharSequence displayName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
|
||||||
|
mSubInfo, this);
|
||||||
|
String title = getString(R.string.sim_action_switch_sub_dialog_mep_title, displayName);
|
||||||
|
final StringBuilder switchDialogMsg = new StringBuilder();
|
||||||
|
switchDialogMsg.append(
|
||||||
|
getString(R.string.sim_action_switch_sub_dialog_mep_text, displayName));
|
||||||
|
if (isRtlMode) {
|
||||||
|
/* There are two lines of message in the dialog, and the RTL symbols must be added
|
||||||
|
* before and after each sentence, so use the line break symbol to find the position.
|
||||||
|
* (Each message are all with two line break symbols)
|
||||||
|
*/
|
||||||
|
switchDialogMsg.insert(0, RTL_MARK)
|
||||||
|
.insert(switchDialogMsg.indexOf(LINE_BREAK) - LINE_BREAK_OFFSET_ONE, RTL_MARK)
|
||||||
|
.insert(switchDialogMsg.indexOf(LINE_BREAK) + LINE_BREAK_OFFSET_TWO, RTL_MARK)
|
||||||
|
.insert(switchDialogMsg.length(), RTL_MARK);
|
||||||
|
}
|
||||||
|
ConfirmDialogFragment.show(
|
||||||
|
this,
|
||||||
|
ConfirmDialogFragment.OnConfirmListener.class,
|
||||||
|
DIALOG_TAG_ENABLE_SIM_CONFIRMATION_MEP,
|
||||||
|
title,
|
||||||
|
switchDialogMsg.toString(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
getSwitchDialogBodyList());
|
||||||
|
}
|
||||||
|
|
||||||
private String getSwitchDialogPosBtnText() {
|
private String getSwitchDialogPosBtnText() {
|
||||||
return mIsEsimOperation
|
return mIsEsimOperation
|
||||||
? getString(
|
? getString(
|
||||||
@@ -468,6 +542,20 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
return switchDialogMsg.toString();
|
return switchDialogMsg.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<String> getSwitchDialogBodyList() {
|
||||||
|
ArrayList<String> list = new ArrayList<String>(mActiveSubInfos.stream()
|
||||||
|
.map(subInfo -> {
|
||||||
|
CharSequence subInfoName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
|
||||||
|
subInfo, this);
|
||||||
|
return getString(
|
||||||
|
R.string.sim_action_switch_sub_dialog_carrier_list_item_for_turning_off,
|
||||||
|
subInfoName);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
list.add(getString(R.string.sim_action_cancel));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isDsdsConditionSatisfied() {
|
private boolean isDsdsConditionSatisfied() {
|
||||||
if (mTelMgr.isMultiSimEnabled()) {
|
if (mTelMgr.isMultiSimEnabled()) {
|
||||||
Log.i(TAG, "DSDS is already enabled. Condition not satisfied.");
|
Log.i(TAG, "DSDS is already enabled. Condition not satisfied.");
|
||||||
@@ -477,17 +565,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
Log.i(TAG, "Hardware does not support DSDS.");
|
Log.i(TAG, "Hardware does not support DSDS.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(mTelMgr);
|
boolean isRemovableSimEnabled = isRemovableSimEnabled();
|
||||||
boolean isRemovableSimEnabled =
|
|
||||||
slotInfos.stream()
|
|
||||||
.anyMatch(
|
|
||||||
slot ->
|
|
||||||
slot != null
|
|
||||||
&& slot.isRemovable()
|
|
||||||
&& slot.getPorts().stream().anyMatch(
|
|
||||||
port -> port.isActive())
|
|
||||||
&& slot.getCardStateInfo()
|
|
||||||
== UiccSlotInfo.CARD_STATE_INFO_PRESENT);
|
|
||||||
if (mIsEsimOperation && isRemovableSimEnabled) {
|
if (mIsEsimOperation && isRemovableSimEnabled) {
|
||||||
Log.i(TAG, "eSIM operation and removable SIM is enabled. DSDS condition satisfied.");
|
Log.i(TAG, "eSIM operation and removable SIM is enabled. DSDS condition satisfied.");
|
||||||
return true;
|
return true;
|
||||||
@@ -496,13 +574,36 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
|
|||||||
SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager).stream()
|
SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager).stream()
|
||||||
.anyMatch(SubscriptionInfo::isEmbedded);
|
.anyMatch(SubscriptionInfo::isEmbedded);
|
||||||
if (!mIsEsimOperation && isEsimProfileEnabled) {
|
if (!mIsEsimOperation && isEsimProfileEnabled) {
|
||||||
Log.i(
|
Log.i(TAG, "Removable SIM operation and eSIM profile is enabled. DSDS condition"
|
||||||
TAG,
|
|
||||||
"Removable SIM operation and eSIM profile is enabled. DSDS condition"
|
|
||||||
+ " satisfied.");
|
+ " satisfied.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "DSDS condition not satisfied.");
|
Log.i(TAG, "DSDS condition not satisfied.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isRemovableSimEnabled() {
|
||||||
|
ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(mTelMgr);
|
||||||
|
boolean isRemovableSimEnabled =
|
||||||
|
slotInfos.stream()
|
||||||
|
.anyMatch(
|
||||||
|
slot -> slot != null
|
||||||
|
&& slot.isRemovable()
|
||||||
|
&& slot.getPorts().stream().anyMatch(
|
||||||
|
port -> port.isActive())
|
||||||
|
&& slot.getCardStateInfo()
|
||||||
|
== UiccSlotInfo.CARD_STATE_INFO_PRESENT);
|
||||||
|
Log.i(TAG, "isRemovableSimEnabled: " + isRemovableSimEnabled);
|
||||||
|
return isRemovableSimEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMultipleEnabledProfilesSupported() {
|
||||||
|
List<UiccCardInfo> cardInfos = mTelMgr.getUiccCardsInfo();
|
||||||
|
if (cardInfos == null) {
|
||||||
|
Log.w(TAG, "UICC cards info list is empty.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return cardInfos.stream().anyMatch(
|
||||||
|
cardInfo -> cardInfo.isMultipleEnabledProfilesSupported());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
mContext = getActivity();
|
mContext = getActivity();
|
||||||
|
|
||||||
final Intent intent = getActivity().getIntent();
|
final Intent intent = getActivity().getIntent();
|
||||||
@@ -81,7 +82,6 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onCreate(icicle);
|
|
||||||
mCustomBehaviorPreference = getPreferenceScreen().findPreference(CUSTOM_BEHAVIOR_KEY);
|
mCustomBehaviorPreference = getPreferenceScreen().findPreference(CUSTOM_BEHAVIOR_KEY);
|
||||||
mCustomBehaviorPreference.setOnPreferenceClickListener(
|
mCustomBehaviorPreference.setOnPreferenceClickListener(
|
||||||
new Preference.OnPreferenceClickListener() {
|
new Preference.OnPreferenceClickListener() {
|
||||||
|
|||||||
@@ -268,9 +268,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
R.string.lockpassword_choose_your_pin_header_for_fingerprint,
|
R.string.lockpassword_choose_your_pin_header_for_fingerprint,
|
||||||
R.string.lockpassword_choose_your_pin_header_for_face,
|
R.string.lockpassword_choose_your_pin_header_for_face,
|
||||||
R.string.lockpassword_choose_your_pin_header_for_biometrics,
|
R.string.lockpassword_choose_your_pin_header_for_biometrics,
|
||||||
R.string.lockpassword_choose_password_description,
|
|
||||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||||
R.string.lockpassword_choose_pin_description,
|
|
||||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||||
R.string.next_label),
|
R.string.next_label),
|
||||||
|
|
||||||
@@ -287,8 +285,6 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
R.string.lockpassword_confirm_your_pin_header,
|
R.string.lockpassword_confirm_your_pin_header,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
0,
|
|
||||||
R.string.lockpassword_confirm_label),
|
R.string.lockpassword_confirm_label),
|
||||||
|
|
||||||
ConfirmWrong(
|
ConfirmWrong(
|
||||||
@@ -304,8 +300,6 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
R.string.lockpassword_confirm_pins_dont_match,
|
R.string.lockpassword_confirm_pins_dont_match,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
0,
|
|
||||||
R.string.lockpassword_confirm_label);
|
R.string.lockpassword_confirm_label);
|
||||||
|
|
||||||
Stage(int hintInAlpha,
|
Stage(int hintInAlpha,
|
||||||
@@ -318,9 +312,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
int hintInNumericForFingerprint,
|
int hintInNumericForFingerprint,
|
||||||
int hintInNumericForFace,
|
int hintInNumericForFace,
|
||||||
int hintInNumericForBiometrics,
|
int hintInNumericForBiometrics,
|
||||||
int messageInAlpha,
|
|
||||||
int messageInAlphaForBiometrics,
|
int messageInAlphaForBiometrics,
|
||||||
int messageInNumeric,
|
|
||||||
int messageInNumericForBiometrics,
|
int messageInNumericForBiometrics,
|
||||||
int nextButtonText) {
|
int nextButtonText) {
|
||||||
|
|
||||||
@@ -336,10 +328,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
this.numericHintForFace = hintInNumericForFace;
|
this.numericHintForFace = hintInNumericForFace;
|
||||||
this.numericHintForBiometrics = hintInNumericForBiometrics;
|
this.numericHintForBiometrics = hintInNumericForBiometrics;
|
||||||
|
|
||||||
this.alphaMessage = messageInAlpha;
|
|
||||||
this.alphaMessageForBiometrics = messageInAlphaForBiometrics;
|
this.alphaMessageForBiometrics = messageInAlphaForBiometrics;
|
||||||
|
|
||||||
this.numericMessage = messageInNumeric;
|
|
||||||
this.numericMessageForBiometrics = messageInNumericForBiometrics;
|
this.numericMessageForBiometrics = messageInNumericForBiometrics;
|
||||||
|
|
||||||
this.buttonText = nextButtonText;
|
this.buttonText = nextButtonText;
|
||||||
@@ -365,11 +354,9 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
public final int numericHintForBiometrics;
|
public final int numericHintForBiometrics;
|
||||||
|
|
||||||
// Password description
|
// Password description
|
||||||
public final int alphaMessage;
|
|
||||||
public final int alphaMessageForBiometrics;
|
public final int alphaMessageForBiometrics;
|
||||||
|
|
||||||
// PIN description
|
// PIN description
|
||||||
public final int numericMessage;
|
|
||||||
public final int numericMessageForBiometrics;
|
public final int numericMessageForBiometrics;
|
||||||
|
|
||||||
public final int buttonText;
|
public final int buttonText;
|
||||||
@@ -407,7 +394,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
|
|
||||||
case TYPE_NONE:
|
case TYPE_NONE:
|
||||||
default:
|
default:
|
||||||
return isAlpha ? alphaMessage : numericMessage;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -869,13 +856,18 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
setNextEnabled(canInput && length >= LockPatternUtils.MIN_LOCK_PASSWORD_SIZE);
|
setNextEnabled(canInput && length >= LockPatternUtils.MIN_LOCK_PASSWORD_SIZE);
|
||||||
mSkipOrClearButton.setVisibility(toVisibility(canInput && length > 0));
|
mSkipOrClearButton.setVisibility(toVisibility(canInput && length > 0));
|
||||||
}
|
}
|
||||||
int message = mUiStage.getMessage(mIsAlphaMode, getStageType());
|
final int stage = getStageType();
|
||||||
|
if (getStageType() != Stage.TYPE_NONE) {
|
||||||
|
int message = mUiStage.getMessage(mIsAlphaMode, stage);
|
||||||
if (message != 0) {
|
if (message != 0) {
|
||||||
mMessage.setVisibility(View.VISIBLE);
|
mMessage.setVisibility(View.VISIBLE);
|
||||||
mMessage.setText(message);
|
mMessage.setText(message);
|
||||||
} else {
|
} else {
|
||||||
mMessage.setVisibility(View.INVISIBLE);
|
mMessage.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mMessage.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
setNextText(mUiStage.buttonText);
|
setNextText(mUiStage.buttonText);
|
||||||
mPasswordEntryInputDisabler.setInputEnabled(canInput);
|
mPasswordEntryInputDisabler.setInputEnabled(canInput);
|
||||||
|
|||||||
@@ -363,54 +363,49 @@ public class ChooseLockPattern extends SettingsActivity {
|
|||||||
|
|
||||||
Introduction(
|
Introduction(
|
||||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||||
R.string.lockpattern_choose_pattern_description,
|
|
||||||
R.string.lockpattern_recording_intro_header,
|
R.string.lockpattern_recording_intro_header,
|
||||||
LeftButtonMode.Gone, RightButtonMode.ContinueDisabled,
|
LeftButtonMode.Gone, RightButtonMode.ContinueDisabled,
|
||||||
ID_EMPTY_MESSAGE, true),
|
ID_EMPTY_MESSAGE, true),
|
||||||
HelpScreen(
|
HelpScreen(
|
||||||
ID_EMPTY_MESSAGE, ID_EMPTY_MESSAGE, R.string.lockpattern_settings_help_how_to_record,
|
ID_EMPTY_MESSAGE, R.string.lockpattern_settings_help_how_to_record,
|
||||||
LeftButtonMode.Gone, RightButtonMode.Ok, ID_EMPTY_MESSAGE, false),
|
LeftButtonMode.Gone, RightButtonMode.Ok, ID_EMPTY_MESSAGE, false),
|
||||||
ChoiceTooShort(
|
ChoiceTooShort(
|
||||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||||
R.string.lockpattern_choose_pattern_description,
|
|
||||||
R.string.lockpattern_recording_incorrect_too_short,
|
R.string.lockpattern_recording_incorrect_too_short,
|
||||||
LeftButtonMode.Retry, RightButtonMode.ContinueDisabled,
|
LeftButtonMode.Retry, RightButtonMode.ContinueDisabled,
|
||||||
ID_EMPTY_MESSAGE, true),
|
ID_EMPTY_MESSAGE, true),
|
||||||
FirstChoiceValid(
|
FirstChoiceValid(
|
||||||
R.string.lock_settings_picker_biometrics_added_security_message,
|
R.string.lock_settings_picker_biometrics_added_security_message,
|
||||||
R.string.lockpattern_choose_pattern_description,
|
|
||||||
R.string.lockpattern_pattern_entered_header,
|
R.string.lockpattern_pattern_entered_header,
|
||||||
LeftButtonMode.Retry, RightButtonMode.Continue, ID_EMPTY_MESSAGE, false),
|
LeftButtonMode.Retry, RightButtonMode.Continue, ID_EMPTY_MESSAGE, false),
|
||||||
NeedToConfirm(
|
NeedToConfirm(
|
||||||
ID_EMPTY_MESSAGE, ID_EMPTY_MESSAGE, R.string.lockpattern_need_to_confirm,
|
ID_EMPTY_MESSAGE, R.string.lockpattern_need_to_confirm,
|
||||||
LeftButtonMode.Gone, RightButtonMode.ConfirmDisabled,
|
LeftButtonMode.Gone, RightButtonMode.ConfirmDisabled,
|
||||||
ID_EMPTY_MESSAGE, true),
|
ID_EMPTY_MESSAGE, true),
|
||||||
ConfirmWrong(
|
ConfirmWrong(
|
||||||
ID_EMPTY_MESSAGE, ID_EMPTY_MESSAGE, R.string.lockpattern_need_to_unlock_wrong,
|
ID_EMPTY_MESSAGE, R.string.lockpattern_need_to_unlock_wrong,
|
||||||
LeftButtonMode.Gone, RightButtonMode.ConfirmDisabled,
|
LeftButtonMode.Gone, RightButtonMode.ConfirmDisabled,
|
||||||
ID_EMPTY_MESSAGE, true),
|
ID_EMPTY_MESSAGE, true),
|
||||||
ChoiceConfirmed(
|
ChoiceConfirmed(
|
||||||
ID_EMPTY_MESSAGE, ID_EMPTY_MESSAGE, R.string.lockpattern_pattern_confirmed_header,
|
ID_EMPTY_MESSAGE, R.string.lockpattern_pattern_confirmed_header,
|
||||||
LeftButtonMode.Gone, RightButtonMode.Confirm, ID_EMPTY_MESSAGE, false);
|
LeftButtonMode.Gone, RightButtonMode.Confirm, ID_EMPTY_MESSAGE, false);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param messageForBiometrics The message displayed at the top, above header for
|
* @param messageForBiometrics The message displayed at the top, above header for
|
||||||
* fingerprint flow.
|
* fingerprint flow.
|
||||||
* @param message The message displayed at the top.
|
|
||||||
* @param headerMessage The message displayed at the top.
|
* @param headerMessage The message displayed at the top.
|
||||||
* @param leftMode The mode of the left button.
|
* @param leftMode The mode of the left button.
|
||||||
* @param rightMode The mode of the right button.
|
* @param rightMode The mode of the right button.
|
||||||
* @param footerMessage The footer message.
|
* @param footerMessage The footer message.
|
||||||
* @param patternEnabled Whether the pattern widget is enabled.
|
* @param patternEnabled Whether the pattern widget is enabled.
|
||||||
*/
|
*/
|
||||||
Stage(int messageForBiometrics, int message, int headerMessage,
|
Stage(int messageForBiometrics, int headerMessage,
|
||||||
LeftButtonMode leftMode,
|
LeftButtonMode leftMode,
|
||||||
RightButtonMode rightMode,
|
RightButtonMode rightMode,
|
||||||
int footerMessage, boolean patternEnabled) {
|
int footerMessage, boolean patternEnabled) {
|
||||||
this.headerMessage = headerMessage;
|
this.headerMessage = headerMessage;
|
||||||
this.messageForBiometrics = messageForBiometrics;
|
this.messageForBiometrics = messageForBiometrics;
|
||||||
this.message = message;
|
|
||||||
this.leftMode = leftMode;
|
this.leftMode = leftMode;
|
||||||
this.rightMode = rightMode;
|
this.rightMode = rightMode;
|
||||||
this.footerMessage = footerMessage;
|
this.footerMessage = footerMessage;
|
||||||
@@ -419,7 +414,6 @@ public class ChooseLockPattern extends SettingsActivity {
|
|||||||
|
|
||||||
final int headerMessage;
|
final int headerMessage;
|
||||||
final int messageForBiometrics;
|
final int messageForBiometrics;
|
||||||
final int message;
|
|
||||||
final LeftButtonMode leftMode;
|
final LeftButtonMode leftMode;
|
||||||
final RightButtonMode rightMode;
|
final RightButtonMode rightMode;
|
||||||
final int footerMessage;
|
final int footerMessage;
|
||||||
@@ -735,11 +729,14 @@ public class ChooseLockPattern extends SettingsActivity {
|
|||||||
}
|
}
|
||||||
final GlifLayout layout = getActivity().findViewById(R.id.setup_wizard_layout);
|
final GlifLayout layout = getActivity().findViewById(R.id.setup_wizard_layout);
|
||||||
final boolean forAnyBiometric = mForFingerprint || mForFace || mForBiometrics;
|
final boolean forAnyBiometric = mForFingerprint || mForFace || mForBiometrics;
|
||||||
int message = forAnyBiometric ? stage.messageForBiometrics : stage.message;
|
if (forAnyBiometric) {
|
||||||
if (message == ID_EMPTY_MESSAGE) {
|
if (stage.messageForBiometrics == ID_EMPTY_MESSAGE) {
|
||||||
layout.setDescriptionText("");
|
layout.setDescriptionText("");
|
||||||
} else {
|
} else {
|
||||||
layout.setDescriptionText(message);
|
layout.setDescriptionText(stage.messageForBiometrics);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
layout.getDescriptionTextView().setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
if (stage.footerMessage == ID_EMPTY_MESSAGE) {
|
if (stage.footerMessage == ID_EMPTY_MESSAGE) {
|
||||||
mFooterText.setText("");
|
mFooterText.setText("");
|
||||||
|
|||||||
@@ -142,14 +142,8 @@ public class SetupChooseLockPattern extends ChooseLockPattern {
|
|||||||
mLeftButtonIsSkip = false;
|
mLeftButtonIsSkip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show generic pattern message when pattern lock screen launch in Setup wizard flow
|
|
||||||
// before fingerprint and face setup.
|
|
||||||
final GlifLayout layout = getActivity().findViewById(R.id.setup_wizard_layout);
|
final GlifLayout layout = getActivity().findViewById(R.id.setup_wizard_layout);
|
||||||
if (stage.message == ID_EMPTY_MESSAGE) {
|
|
||||||
layout.setDescriptionText("");
|
layout.setDescriptionText("");
|
||||||
} else {
|
|
||||||
layout.setDescriptionText(stage.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.privacy;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settings.safetycenter.SafetyCenterStatus;
|
||||||
|
|
||||||
|
/** The preference controller for the top level privacy tile. */
|
||||||
|
public class TopLevelPrivacyEntryPreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
|
public TopLevelPrivacyEntryPreferenceController(@NonNull Context context, @NonNull String key) {
|
||||||
|
super(context, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
if (!SafetyCenterStatus.isEnabled()) {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
return CONDITIONALLY_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.safetycenter;
|
||||||
|
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
/** Knows whether safety center is enabled or disabled. */
|
||||||
|
public class SafetyCenterStatus {
|
||||||
|
|
||||||
|
/** Whether SafetyCenter page is enabled. */
|
||||||
|
@VisibleForTesting
|
||||||
|
public static final String SAFETY_CENTER_IS_ENABLED = "safety_center_is_enabled";
|
||||||
|
|
||||||
|
/** Returns true is SafetyCenter page is enabled, false otherwise. */
|
||||||
|
public static boolean isEnabled() {
|
||||||
|
// TODO(b/208625216): use SafetyManager API instead
|
||||||
|
return DeviceConfig.getBoolean(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY, SAFETY_CENTER_IS_ENABLED, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.safetycenter;
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
|
||||||
|
/** Controller for the SafetyCenter entry in top level Settings. */
|
||||||
|
public class TopLevelSafetyCenterEntryPreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
|
private static final String TAG = "TopLevelSafetyCenterEntryPreferenceController";
|
||||||
|
|
||||||
|
public TopLevelSafetyCenterEntryPreferenceController(Context context, String preferenceKey) {
|
||||||
|
super(context, preferenceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
if (SafetyCenterStatus.isEnabled()) {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
return CONDITIONALLY_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||||
|
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
||||||
|
return super.handlePreferenceTreeClick(preference);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mContext.startActivity(new Intent(Intent.ACTION_SAFETY_CENTER));
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Log.e(TAG, "Unable to open safety center", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import androidx.preference.Preference;
|
|||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
import com.android.settings.safetycenter.SafetyCenterStatus;
|
||||||
|
|
||||||
public class TopLevelSecurityEntryPreferenceController extends BasePreferenceController {
|
public class TopLevelSecurityEntryPreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
@@ -37,8 +38,11 @@ public class TopLevelSecurityEntryPreferenceController extends BasePreferenceCon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
|
if (!SafetyCenterStatus.isEnabled()) {
|
||||||
return AVAILABLE;
|
return AVAILABLE;
|
||||||
}
|
}
|
||||||
|
return CONDITIONALLY_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class DsdsDialogActivity extends SubscriptionActionDialogActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfirm(int tag, boolean confirmed) {
|
public void onConfirm(int tag, boolean confirmed, int itemPosition) {
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
Log.i(TAG, "User cancel the dialog to enable DSDS.");
|
Log.i(TAG, "User cancel the dialog to enable DSDS.");
|
||||||
startChooseSimActivity();
|
startChooseSimActivity();
|
||||||
|
|||||||
@@ -160,9 +160,11 @@ public class SimDialogActivity extends FragmentActivity {
|
|||||||
final TelephonyManager telephonyManager = getSystemService(
|
final TelephonyManager telephonyManager = getSystemService(
|
||||||
TelephonyManager.class).createForSubscriptionId(subId);
|
TelephonyManager.class).createForSubscriptionId(subId);
|
||||||
subscriptionManager.setDefaultDataSubId(subId);
|
subscriptionManager.setDefaultDataSubId(subId);
|
||||||
|
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||||
telephonyManager.setDataEnabled(true);
|
telephonyManager.setDataEnabled(true);
|
||||||
Toast.makeText(this, R.string.data_switch_started, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.data_switch_started, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setDefaultCallsSubId(final int subId) {
|
private void setDefaultCallsSubId(final int subId) {
|
||||||
final PhoneAccountHandle phoneAccount = subscriptionIdToPhoneAccountHandle(subId);
|
final PhoneAccountHandle phoneAccount = subscriptionIdToPhoneAccountHandle(subId);
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class SwitchToEsimConfirmDialogActivity extends SubscriptionActionDialogA
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfirm(int tag, boolean confirmed) {
|
public void onConfirm(int tag, boolean confirmed, int itemPosition) {
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
AlertDialogFragment.show(
|
AlertDialogFragment.show(
|
||||||
this,
|
this,
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.privacy;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.settings.safetycenter.SafetyCenterStatus;
|
||||||
|
import com.android.settings.security.TopLevelSecurityEntryPreferenceController;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class TopLevelPrivacyEntryPreferenceControllerTest {
|
||||||
|
|
||||||
|
private static final String PREFERENCE_KEY = "top_level_privacy";
|
||||||
|
|
||||||
|
private TopLevelPrivacyEntryPreferenceController mTopLevelPrivacyEntryPreferenceController;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
|
||||||
|
mTopLevelPrivacyEntryPreferenceController =
|
||||||
|
new TopLevelPrivacyEntryPreferenceController(mContext, PREFERENCE_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsUnavailable() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(true),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(mTopLevelPrivacyEntryPreferenceController.getAvailabilityStatus())
|
||||||
|
.isEqualTo(TopLevelSecurityEntryPreferenceController.CONDITIONALLY_UNAVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsAvailable() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(false),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(mTopLevelPrivacyEntryPreferenceController.getAvailabilityStatus())
|
||||||
|
.isEqualTo(TopLevelSecurityEntryPreferenceController.AVAILABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.safetycenter;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class SafetyCenterStatusTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isEnabled_whenFlagTrue_returnsTrue() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(true),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(SafetyCenterStatus.isEnabled()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isEnabled_whenFlagFalse_returnsFalse() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(false),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(SafetyCenterStatus.isEnabled()).isFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.safetycenter;
|
||||||
|
|
||||||
|
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.doThrow;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class TopLevelSafetyCenterEntryPreferenceControllerTest {
|
||||||
|
|
||||||
|
private static final String PREFERENCE_KEY = "top_level_safety_center";
|
||||||
|
|
||||||
|
private TopLevelSafetyCenterEntryPreferenceController
|
||||||
|
mTopLevelSafetyCenterEntryPreferenceController;
|
||||||
|
private Preference mPreference;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
mPreference = new Preference(ApplicationProvider.getApplicationContext());
|
||||||
|
mPreference.setKey(PREFERENCE_KEY);
|
||||||
|
|
||||||
|
doNothing().when(mContext).startActivity(any(Intent.class));
|
||||||
|
mTopLevelSafetyCenterEntryPreferenceController =
|
||||||
|
new TopLevelSafetyCenterEntryPreferenceController(mContext, PREFERENCE_KEY);
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handlePreferenceTreeClick_forDifferentPreferenceKey_isNotHandled() {
|
||||||
|
Preference preference = new Preference(ApplicationProvider.getApplicationContext());
|
||||||
|
preference.setKey("some_other_preference");
|
||||||
|
|
||||||
|
boolean preferenceHandled =
|
||||||
|
mTopLevelSafetyCenterEntryPreferenceController.handlePreferenceTreeClick(
|
||||||
|
preference);
|
||||||
|
|
||||||
|
assertThat(preferenceHandled).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handlePreferenceTreeClick_launchesIntendedIntent() {
|
||||||
|
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||||
|
|
||||||
|
boolean preferenceHandled = mTopLevelSafetyCenterEntryPreferenceController
|
||||||
|
.handlePreferenceTreeClick(mPreference);
|
||||||
|
|
||||||
|
assertThat(preferenceHandled).isTrue();
|
||||||
|
verify(mContext).startActivity(intentCaptor.capture());
|
||||||
|
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handlePreferenceTreeClick_onStartActivityThrows_returnsFalse() {
|
||||||
|
doThrow(ActivityNotFoundException.class)
|
||||||
|
.when(mContext).startActivity(any(Intent.class));
|
||||||
|
|
||||||
|
boolean preferenceHandled = mTopLevelSafetyCenterEntryPreferenceController
|
||||||
|
.handlePreferenceTreeClick(mPreference);
|
||||||
|
|
||||||
|
assertThat(preferenceHandled).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsUnavailable() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(false),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(mTopLevelSafetyCenterEntryPreferenceController.getAvailabilityStatus())
|
||||||
|
.isEqualTo(TopLevelSafetyCenterEntryPreferenceController.CONDITIONALLY_UNAVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsAvailable() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(true),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(mTopLevelSafetyCenterEntryPreferenceController.getAvailabilityStatus())
|
||||||
|
.isEqualTo(TopLevelSafetyCenterEntryPreferenceController.AVAILABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,14 +25,18 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
|
import com.android.settings.safetycenter.SafetyCenterStatus;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -60,6 +64,9 @@ public class TopLevelSecurityEntryPreferenceControllerTest {
|
|||||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||||
mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider();
|
mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider();
|
||||||
|
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
|
||||||
mPreference = new Preference(ApplicationProvider.getApplicationContext());
|
mPreference = new Preference(ApplicationProvider.getApplicationContext());
|
||||||
mPreference.setKey(PREFERENCE_KEY);
|
mPreference.setKey(PREFERENCE_KEY);
|
||||||
|
|
||||||
@@ -68,6 +75,12 @@ public class TopLevelSecurityEntryPreferenceControllerTest {
|
|||||||
new TopLevelSecurityEntryPreferenceController(mContext, PREFERENCE_KEY);
|
new TopLevelSecurityEntryPreferenceController(mContext, PREFERENCE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlePreferenceTreeClick_forDifferentPreferenceKey_isNotHandled() {
|
public void handlePreferenceTreeClick_forDifferentPreferenceKey_isNotHandled() {
|
||||||
Preference preference = new Preference(ApplicationProvider.getApplicationContext());
|
Preference preference = new Preference(ApplicationProvider.getApplicationContext());
|
||||||
@@ -121,4 +134,28 @@ public class TopLevelSecurityEntryPreferenceControllerTest {
|
|||||||
|
|
||||||
assertThat(preferenceHandled).isFalse();
|
assertThat(preferenceHandled).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsUnavailable() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(true),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(mTopLevelSecurityEntryPreferenceController.getAvailabilityStatus())
|
||||||
|
.isEqualTo(TopLevelSecurityEntryPreferenceController.CONDITIONALLY_UNAVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsAvailable() {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_PRIVACY,
|
||||||
|
SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
|
||||||
|
/* value = */ Boolean.toString(false),
|
||||||
|
/* makeDefault = */ false);
|
||||||
|
|
||||||
|
assertThat(mTopLevelSecurityEntryPreferenceController.getAvailabilityStatus())
|
||||||
|
.isEqualTo(TopLevelSecurityEntryPreferenceController.AVAILABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user