Snap for 6425864 from b821580ff1 to mainline-release

Change-Id: I560cd8bc09272428b68a924dfa73f3fec0d0d2b3
This commit is contained in:
android-build-team Robot
2020-04-24 07:03:52 +00:00
62 changed files with 1352 additions and 225 deletions

View File

@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:width="18dp"
android:height="18dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">

View File

@@ -0,0 +1,26 @@
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
android:fillColor="#FFFFFF"/>
</vector>

View File

@@ -25,5 +25,5 @@
2zm4-8c0 1.1 .9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zm-4 2c1.1 0 2-.9
2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6 6c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2
2zm0 6c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"
android:fillColor="#FFFFFFFF"/>
android:fillColor="?android:attr/colorPrimary"/>
</vector>

View File

@@ -20,7 +20,7 @@
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="@android:color/white"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M3,6h18V4H3C1.9,4 1,4.9 1,6v12c0,1.1 0.9,2 2,2h4v-2H3V6zM13,12H9v1.78C8.39,14.33 8,15.11 8,16c0,0.89 0.39,1.67 1,2.22V20h4v-1.78c0.61,-0.55 1,-1.34 1,-2.22s-0.39,-1.67 -1,-2.22V12zM11,17.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5S11.83,17.5 11,17.5zM22,8h-6c-0.5,0 -1,0.5 -1,1v10c0,0.5 0.5,1 1,1h6c0.5,0 1,-0.5 1,-1V9C23,8.5 22.5,8 22,8zM21,18h-4v-8h4V18z"/>
</vector>

View File

@@ -19,6 +19,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M11,18h2v-2h-2V18zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5C16,7.79 14.21,6 12,6z"/>
</vector>

View File

@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7v-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM11,7h2v2h-2V7zM11,11h2v6h-2V11z"/>
</vector>

View File

@@ -21,5 +21,5 @@
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M20,2H4c-1.1,0 -2,0.9 -2,2v18l4,-4h14c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2z"/>
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM20,16L4,16L4,4h16v12zM6,12h8v2L6,14zM6,9h12v2L6,11zM6,6h12v2L6,8z"/>
</vector>

View File

@@ -19,9 +19,9 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.5,4c-2.61,0.7 -5.67,1 -8.5,1S6.11,4.7 3.5,4L3,6c1.86,0.5 4,0.83 6,1v13h2v-6h2v6h2V7c2,-0.17 4.14,-0.5 6,-1L20.5,4zM12,4c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2s-2,0.9 -2,2S10.9,4 12,4z"/>
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M7,24h2v-2H7V24zM11,24h2v-2h-2V24zM15,24h2v-2h-2V24z"/>
</vector>

View File

@@ -19,9 +19,9 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M19,3H5C3.89,3 3,3.9 3,5v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM19,5v10.79C16.52,14.37 13.23,14 12,14s-4.52,0.37 -7,1.79V5H19zM5,19v-0.77C6.74,16.66 10.32,16 12,16s5.26,0.66 7,2.23V19H5z"/>
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,13c1.94,0 3.5,-1.56 3.5,-3.5C15.5,7.56 13.94,6 12,6c-1.94,0 -3.5,1.56 -3.5,3.5C8.5,11.44 10.06,13 12,13zM12,8c0.83,0 1.5,0.67 1.5,1.5c0,0.83 -0.67,1.5 -1.5,1.5c-0.83,0 -1.5,-0.67 -1.5,-1.5C10.5,8.67 11.17,8 12,8z"/>
</vector>

View File

@@ -19,6 +19,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33v15.33C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V5.33C17,4.6 16.4,4 15.67,4z"/>
</vector>

View File

@@ -19,6 +19,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M20,8.69V4h-4.69L12,0.69L8.69,4H4v4.69L0.69,12L4,15.31V20h4.69L12,23.31L15.31,20H20v-4.69L23.31,12L20,8.69zM18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48zM12,17c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5V17z"/>
</vector>

View File

@@ -19,9 +19,9 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
</vector>

View File

@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M21.25,16.5v-0.66c0,-1.13 -1.03,-2.09 -2.25,-2.09s-2.25,0.96 -2.25,2.09v0.66H16V22h6v-5.5H21.25zM19.75,16.5h-1.5v-0.66c0,-0.29 0.38,-0.59 0.75,-0.59s0.75,0.3 0.75,0.59V16.5z"/>
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,17c-3.79,0 -7.17,-2.13 -8.82,-5.5C4.83,8.13 8.21,6 12,6s7.17,2.13 8.82,5.5H23C21.27,7.11 17,4 12,4S2.73,7.11 1,11.5C2.73,15.89 7,19 12,19c0.68,0 1.35,-0.06 2,-0.17v-2.05C13.35,16.91 12.69,17 12,17z"/>
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M16.43,12.23c0.04,-0.24 0.07,-0.48 0.07,-0.73C16.5,9.02 14.48,7 12,7s-4.5,2.02 -4.5,4.5S9.52,16 12,16c0.77,0 1.48,-0.21 2.12,-0.55C14.41,14.08 15.27,12.93 16.43,12.23zM12,14.2c-1.49,0 -2.7,-1.21 -2.7,-2.7s1.21,-2.7 2.7,-2.7s2.7,1.21 2.7,2.7S13.49,14.2 12,14.2z"/>
</vector>

View File

@@ -19,6 +19,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L9,8L9,6zM18,20L6,20L6,10h12v10zM12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
</vector>

View File

@@ -19,12 +19,12 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M11,7h2v2h-2z"/>
<path
android:fillColor="#FFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M11,11h2v6h-2z"/>
<path
android:fillColor="#FFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,6.48 17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-4.41 3.59,-8 8,-8s8,3.59 8,8C20,16.41 16.41,20 12,20z"/>
</vector>

View File

@@ -16,4 +16,4 @@
<com.android.settings.widget.TintDrawable
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_settings_wireless"
android:tint="@android:color/white" />
android:tint="?android:attr/colorPrimary" />

View File

@@ -19,6 +19,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M3,20h18v-4H3V20zM5,17h2v2H5V17zM3,4v4h18V4H3zM7,7H5V5h2V7zM3,14h18v-4H3V14zM5,11h2v2H5V11z"/>
</vector>

View File

@@ -20,12 +20,12 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M3,9v6h4l5,5V4L7,9H3zM10,8.83v6.34L7.83,13H5v-2h2.83L10,8.83z"/>
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05C15.48,15.29 16.5,13.77 16.5,12z"/>
<path
android:fillColor="#FFFFFFFF"
android:fillColor="?android:attr/colorPrimary"
android:pathData="M14,3.23v2.06c2.89,0.86 5,3.54 5,6.71c0,3.17 -2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77C21,7.72 18.01,4.14 14,3.23z"/>
</vector>

View File

@@ -0,0 +1,58 @@
<!--
Copyright (C) 2020 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.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textDirection="locale"
android:scrollbarStyle="outsideOverlay">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextSwitcher
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:measureAllChildren="false" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="176dp"
android:paddingTop="16dp"
android:paddingBottom="16dp" />
<LinearLayout
android:id="@+id/indicator_container"
android:layout_width="wrap_content"
android:layout_height="10dp"
android:layout_gravity="center" />
<TextSwitcher
android:id="@+id/instruction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:measureAllChildren="false" />
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 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="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="143dp"
android:src="@drawable/ic_promote_conversation"/>
<TextView
android:layout_width="316dp"
android:layout_height="wrap_content"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginTop="47dp"
android:text="@string/conversation_onboarding_title"/>
<TextView
android:layout_width="316dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="24dp"
android:text="@string/conversation_onboarding_summary"/>
</LinearLayout>

View File

@@ -24,6 +24,8 @@
<string name="allow">Allow</string>
<!-- Strings for Dialog deny button -->
<string name="deny">Deny</string>
<!-- Used in confirmation dialogs as the action that the user will tap to turn on the feature. [CHAR LIMIT=40]-->
<string name="confirmation_turn_on">Turn on</string>
<!-- Device Info screen. Used for a status item's value when the proper value is not known -->
<string name="device_info_default">Unknown</string>
@@ -7266,19 +7268,33 @@
<string name="enhanced_4g_lte_mode_summary">Use LTE services to improve voice and other communications (recommended)</string>
<!-- Enhaced 4G LTE Mode summary for 4g calling. [CHAR LIMIT=100] -->
<string name="enhanced_4g_lte_mode_summary_4g_calling">Use 4G services to improve voice and other communications (recommended)</string>
<!-- Title of a preference determining whether or not the user has enabled contact discovery,
which is a service that uses the phone numbers in your contacts to determine if your
<!-- Title of a preference determining whether or not the user has allowed the device to share
their contacts' phone numbers with their carrier in order to implement contact discovery,
which is a service that exchanges contacts with the carrier to determine if your
contacts support advanced calling features, such as video calling. [CHAR LIMIT=50]-->
<string name="contact_discovery_opt_in_title">Contact discovery</string>
<!-- Summary of a preference determining whether or not the user has enabled contact discovery.
[CHAR LIMIT=110] -->
<string name="contact_discovery_opt_in_summary">Allows your carrier to discover which calling features your contacts support.</string>
<!-- Title of the dialog shown when the user tries to enable Contact Discovery.
<string name="contact_discovery_opt_in_title">Send contacts to carrier</string>
<!-- Summary of a preference determining whether or not the user has enabled contact discovery,
which is a service that exchanges contacts with the carrier to determine if your contacts
support enhanced features, such as video calling and RCS messaging. [CHAR LIMIT=110] -->
<string name="contact_discovery_opt_in_summary">Send your contacts\u2019 phone numbers to provide enhanced features</string>
<!-- Title of the dialog shown when the user tries to enable Contact Discovery, which is a
service that exchanges contacts with the carrier to determine if your contacts support
enhanced features, such as video calling and RCS messaging. [CHAR LIMIT=50] -->
<string name="contact_discovery_opt_in_dialog_title">Send contacts to <xliff:g id="carrier" example="T-mobile">%1$s</xliff:g>?</string>
<!-- Title of the dialog shown when the carrier name is not known and the user tries to enable
Contact Discovery, which is a service that exchanges contacts with the carrier to determine
if your contacts support enhanced features, such as video calling and RCS messaging.
[CHAR LIMIT=50] -->
<string name="contact_discovery_opt_in_dialog_title">Enable contact discovery?</string>
<!-- Text displayed in the dialog shown when the user tries to enable Contact Discovery.
[CHAR LIMIT=NONE]-->
<string name="contact_discovery_opt_in_dialog_message">All of the phone numbers in your contacts will be periodically sent to your carrier in order to discover which calling features are supported.</string>
<string name="contact_discovery_opt_in_dialog_title_no_carrier_defined">Send contacts to your carrier?</string>
<!-- The text displayed in the dialog shown when the user tries to enable Contact Discovery,
which is a service that exchanges contacts with the carrier to determine if your contacts
support enhanced features, such as video calling and RCS messaging. [CHAR LIMIT=NONE]-->
<string name="contact_discovery_opt_in_dialog_message">Your contacts\u2019 phone numbers will be periodically sent to <xliff:g id="carrier" example="T-mobile">%1$s</xliff:g>.<xliff:g id="empty_line" example=" ">\n\n</xliff:g>This info identifies whether your contacts can use certain features, like video calls or some messaging features.</string>
<!-- The text displayed in the dialog shown when the mobile carrier's name is not known and the
user tries to enable Contact Discovery, which is a service that exchanges contacts with
the carrier to determine if your contacts support enhanced features, such as video calling
and RCS messaging. [CHAR LIMIT=NONE]-->
<string name="contact_discovery_opt_in_dialog_message_no_carrier_defined">Your contacts\u2019 phone numbers will be periodically sent to your carrier.<xliff:g id="empty_line" example=" ">\n\n</xliff:g>This info identifies whether your contacts can use certain features, like video calls or some messaging features.</string>
<!-- Preferred network type title. [CHAR LIMIT=50] -->
<string name="preferred_network_type_title">Preferred network type</string>
<!-- Preferred network type summary. [CHAR LIMIT=100] -->
@@ -8367,14 +8383,31 @@
<!-- [CHAR LIMIT=100] preference category title -->
<string name="important_conversations">Priority conversations</string>
<!-- preference category summary -->
<string name="important_conversations_summary_bubbles">Show at top of conversation section and appear as floating bubbles</string>
<!-- preference category summary -->
<string name="important_conversations_summary">Show at top of conversation section</string>
<!-- [CHAR LIMIT=100] preference category title -->
<string name="other_conversations">Other conversations</string>
<string name="other_conversations">Modified conversations</string>
<!-- summary for other conversations list -->
<string name="other_conversations_summary">Conversations you\u2019ve made changes to</string>
<!-- [CHAR LIMIT=100] Setting to automatically bubble all notifications from favorite conversations -->
<string name="important_bubble">Bubble important conversations</string>
<string name="important_bubble">Bubble priority conversations</string>
<!-- [CHAR LIMIT=NONE] description of how notifications from important conversations behave -->
<string name="important_conversation_behavior_summary">Important conversations show at the top of the pull-down shade. You can also set them to bubble and interrupt Do Not Disturb.</string>
<string name="important_conversation_behavior_summary">Priority conversations show at the top of the pull-down shade. You can also set them to bubble and interrupt Do Not Disturb.</string>
<!-- title for conversation onboarding -->
<string name="conversation_onboarding_title">Priority and modified conversations will appear here</string>
<!-- summary for conversation onboarding -->
<string name="conversation_onboarding_summary">Once you mark a conversation as priority, or make any other changes to conversations, they will appear here.
\n\nTo change conversation settings:
\nSwipe down from the top of the screen to open the pull-down shade, then touch &amp; hold a conversation.</string>
<!-- Importance title strings for the Importance page. Also the second part of the importance
summary on the channel page-->
@@ -8446,7 +8479,7 @@
<string name="notification_channel_summary_high">When device is unlocked, show notifications as a banner across the top of the screen</string>
<!-- [CHAR LIMIT=100] Label for on/off toggle -->
<string name="notification_switch_label">All <xliff:g id="app_name" example="Android Services">%1$s</xliff:g> notifications</string>
<string name="notification_switch_label">All \"<xliff:g id="app_name" example="Android Services">%1$s</xliff:g>\" notifications</string>
<!-- Default Apps > Default notification assistant -->
<string name="default_notification_assistant">Adaptive Notifications</string>
@@ -11905,18 +11938,27 @@
<!-- Power menu setting option cards, passes, device controls [CHAR LIMIT=NONE] -->
<string name="power_menu_cards_passes_device_controls">Show cards, passes, and device controls</string>
<!-- Power menu setting lock screen category name [CHAR LIMIT=40] -->
<string name="power_menu_lock_screen_category">Lock screen</string>
<!-- Power menu setting option none [CHAR LIMIT=NONE] -->
<string name="power_menu_none">Don\u2019t show any content</string>
<!-- Power menu setting Privacy [CHAR LIMIT=40] -->
<string name="power_menu_privacy">Privacy</string>
<string name="power_menu_privacy">Sensitive content</string>
<!-- Power menu setting privacy show all [CHAR LIMIT=NONE] -->
<string name="power_menu_privacy_show">Show cards and controls when locked</string>
<!-- Power menu setting privacy show controls [CHAR LIMIT=NONE] -->
<string name="power_menu_privacy_show_controls">Show controls when locked</string>
<!-- Power menu setting privacy hide all [CHAR LIMIT=NONE] -->
<string name="power_menu_privacy_hide">Hide cards and controls when locked</string>
<!-- Power menu setting privacy no secure screen lock set [CHAR_LIMIT=NONE] -->
<string name="power_menu_privacy_not_secure">To use, first set a screen lock</string>
<!-- Device controls toggle name [CHAR LIMIT=60] -->
<string name="device_controls_setting_toggle">Show device controls</string>

View File

@@ -20,6 +20,12 @@
android:key="conversation_list"
android:title="@string/zen_mode_conversations_title">
<com.android.settingslib.widget.LayoutPreference
android:key="no_conversations"
android:layout="@layout/conversation_onboarding"
android:selectable="false"
settings:isPreferenceVisible="false"/>
<PreferenceCategory
android:key="important_conversations"
android:title="@string/important_conversations"

View File

@@ -31,4 +31,13 @@
android:title="@string/device_controls_sentence"
android:fragment="com.android.settings.gestures.DeviceControlsSettings"
settings:controller="com.android.settings.gestures.DeviceControlsPreferenceController" />
<PreferenceCategory
android:title="@string/power_menu_lock_screen_category" >
<SwitchPreference
android:key="gesture_power_menu_privacy"
android:title="@string/power_menu_privacy"
settings:controller="com.android.settings.gestures.PowerMenuPrivacyPreferenceController" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -16,35 +16,55 @@
package com.android.settings.accessibility;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextSwitcher;
import android.widget.TextView;
import androidx.annotation.AnimRes;
import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.core.util.Preconditions;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.android.settings.R;
import com.android.settings.Utils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
/**
* Utility class for creating the dialog that guides users for gesture navigation for
* accessibility services.
*/
public class AccessibilityGestureNavigationTutorial {
public final class AccessibilityGestureNavigationTutorial {
/** IntDef enum for dialog type. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({
@@ -59,6 +79,8 @@ public class AccessibilityGestureNavigationTutorial {
int GESTURE_NAVIGATION_SETTINGS = 2;
}
private AccessibilityGestureNavigationTutorial() {}
private static final DialogInterface.OnClickListener mOnClickListener =
(DialogInterface dialog, int which) -> dialog.dismiss();
@@ -91,6 +113,13 @@ public class AccessibilityGestureNavigationTutorial {
return createDialog(context, DialogType.LAUNCH_SERVICE_BY_GESTURE_NAVIGATION);
}
static AlertDialog createAccessibilityTutorialDialog(Context context, int shortcutTypes) {
return new AlertDialog.Builder(context)
.setView(createShortcutNavigationContentView(context, shortcutTypes))
.setNegativeButton(R.string.accessibility_tutorial_dialog_button, mOnClickListener)
.create();
}
/**
* Get a content View for a dialog to confirm that they want to enable a service.
*
@@ -201,4 +230,302 @@ public class AccessibilityGestureNavigationTutorial {
typedArray.recycle();
return colorResId;
}
private static class TutorialPagerAdapter extends PagerAdapter {
private final List<TutorialPage> mTutorialPages;
private TutorialPagerAdapter(List<TutorialPage> tutorialPages) {
this.mTutorialPages = tutorialPages;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
final View itemView = mTutorialPages.get(position).getImageView();
container.addView(itemView);
return itemView;
}
@Override
public int getCount() {
return mTutorialPages.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view == o;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position,
@NonNull Object object) {
final View itemView = mTutorialPages.get(position).getImageView();
container.removeView(itemView);
}
}
private static ImageView createImageView(Context context, int imageRes) {
final ImageView imageView = new ImageView(context);
imageView.setImageResource(imageRes);
imageView.setAdjustViewBounds(true);
return imageView;
}
private static View createShortcutNavigationContentView(Context context, int shortcutTypes) {
final LayoutInflater inflater = context.getSystemService(LayoutInflater.class);
final View contentView = inflater.inflate(
R.layout.accessibility_shortcut_tutorial_dialog, /* root= */ null);
final List<TutorialPage> tutorialPages =
createShortcutTutorialPages(context, shortcutTypes);
Preconditions.checkArgument(!tutorialPages.isEmpty(),
/* errorMessage= */ "Unexpected tutorial pages size");
final LinearLayout indicatorContainer = contentView.findViewById(R.id.indicator_container);
indicatorContainer.setVisibility(tutorialPages.size() > 1 ? VISIBLE : GONE);
for (TutorialPage page : tutorialPages) {
indicatorContainer.addView(page.getIndicatorIcon());
}
tutorialPages.get(/* firstIndex */ 0).getIndicatorIcon().setEnabled(true);
final TextSwitcher title = contentView.findViewById(R.id.title);
title.setFactory(() -> makeTitleView(context));
title.setText(tutorialPages.get(/* firstIndex */ 0).getTitle());
final TextSwitcher instruction = contentView.findViewById(R.id.instruction);
instruction.setFactory(() -> makeInstructionView(context));
instruction.setText(tutorialPages.get(/* firstIndex */ 0).getInstruction());
final ViewPager viewPager = contentView.findViewById(R.id.view_pager);
viewPager.setAdapter(new TutorialPagerAdapter(tutorialPages));
viewPager.addOnPageChangeListener(
new TutorialPageChangeListener(context, title, instruction, tutorialPages));
return contentView;
}
private static View makeTitleView(Context context) {
final String familyName =
context.getString(
com.android.internal.R.string.config_headlineFontFamilyMedium);
final TextView textView = new TextView(context);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, /* size= */ 20);
textView.setTextColor(Utils.getColorAttr(context, android.R.attr.textColorPrimary));
textView.setGravity(Gravity.CENTER);
textView.setTypeface(Typeface.create(familyName, Typeface.NORMAL));
return textView;
}
private static View makeInstructionView(Context context) {
final TextView textView = new TextView(context);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, /* size= */ 16);
textView.setTextColor(Utils.getColorAttr(context, android.R.attr.textColorPrimary));
textView.setTypeface(
Typeface.create(/* familyName= */ "sans-serif", Typeface.NORMAL));
return textView;
}
private static TutorialPage createSoftwareTutorialPage(@NonNull Context context) {
final CharSequence title = getSoftwareTitle(context);
final ImageView image = createSoftwareImage(context);
final CharSequence instruction = getSoftwareInstruction(context);
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
return new TutorialPage(title, image, indicatorIcon, instruction);
}
private static TutorialPage createHardwareTutorialPage(@NonNull Context context) {
final CharSequence title =
context.getText(R.string.accessibility_tutorial_dialog_title_volume);
final ImageView image =
createImageView(context, R.drawable.accessibility_shortcut_type_hardware);
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
final CharSequence instruction =
context.getText(R.string.accessibility_tutorial_dialog_message_volume);
indicatorIcon.setEnabled(false);
return new TutorialPage(title, image, indicatorIcon, instruction);
}
private static TutorialPage createTripleTapTutorialPage(@NonNull Context context) {
final CharSequence title =
context.getText(R.string.accessibility_tutorial_dialog_title_triple);
final ImageView image =
createImageView(context, R.drawable.accessibility_shortcut_type_triple_tap);
final CharSequence instruction =
context.getText(R.string.accessibility_tutorial_dialog_message_triple);
final ImageView indicatorIcon =
createImageView(context, R.drawable.ic_accessibility_page_indicator);
indicatorIcon.setEnabled(false);
return new TutorialPage(title, image, indicatorIcon, instruction);
}
@VisibleForTesting
static List<TutorialPage> createShortcutTutorialPages(@NonNull Context context,
int shortcutTypes) {
final List<TutorialPage> tutorialPages = new ArrayList<>();
if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) {
tutorialPages.add(createSoftwareTutorialPage(context));
}
if ((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE) {
tutorialPages.add(createHardwareTutorialPage(context));
}
if ((shortcutTypes & UserShortcutType.TRIPLETAP) == UserShortcutType.TRIPLETAP) {
tutorialPages.add(createTripleTapTutorialPage(context));
}
return tutorialPages;
}
private static CharSequence getSoftwareTitle(Context context) {
final boolean isGestureNavigationEnabled =
AccessibilityUtil.isGestureNavigateEnabled(context);
final boolean isTouchExploreEnabled = AccessibilityUtil.isTouchExploreEnabled(context);
return (isGestureNavigationEnabled || isTouchExploreEnabled)
? context.getText(R.string.accessibility_tutorial_dialog_title_gesture)
: context.getText(R.string.accessibility_tutorial_dialog_title_button);
}
private static ImageView createSoftwareImage(Context context) {
int resId = R.drawable.accessibility_shortcut_type_software;
if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
resId = AccessibilityUtil.isTouchExploreEnabled(context)
? R.drawable.accessibility_shortcut_type_software_gesture_talkback
: R.drawable.accessibility_shortcut_type_software_gesture;
}
return createImageView(context, resId);
}
private static CharSequence getSoftwareInstruction(Context context) {
final boolean isGestureNavigateEnabled =
AccessibilityUtil.isGestureNavigateEnabled(context);
final boolean isTouchExploreEnabled = AccessibilityUtil.isTouchExploreEnabled(context);
int resId = R.string.accessibility_tutorial_dialog_message_button;
if (isGestureNavigateEnabled) {
resId = isTouchExploreEnabled
? R.string.accessibility_tutorial_dialog_message_gesture_talkback
: R.string.accessibility_tutorial_dialog_message_gesture;
}
CharSequence text = context.getText(resId);
if (resId == R.string.accessibility_tutorial_dialog_message_button) {
text = getSoftwareInstructionWithIcon(context, text);
}
return text;
}
private static CharSequence getSoftwareInstructionWithIcon(Context context, CharSequence text) {
final String message = text.toString();
final SpannableString spannableInstruction = SpannableString.valueOf(message);
final int indexIconStart = message.indexOf("%s");
final int indexIconEnd = indexIconStart + 2;
final ImageView iconView = new ImageView(context);
iconView.setImageDrawable(context.getDrawable(R.drawable.ic_accessibility_new));
final Drawable icon = iconView.getDrawable().mutate();
final ImageSpan imageSpan = new ImageSpan(icon);
imageSpan.setContentDescription("");
icon.setBounds(/* left= */ 0, /* top= */ 0,
icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
spannableInstruction.setSpan(imageSpan, indexIconStart, indexIconEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannableInstruction;
}
private static class TutorialPage {
private final CharSequence mTitle;
private final ImageView mImageView;
private final ImageView mIndicatorIcon;
private final CharSequence mInstruction;
TutorialPage(CharSequence title, ImageView imageView, ImageView indicatorIcon,
CharSequence instruction) {
this.mTitle = title;
this.mImageView = imageView;
this.mIndicatorIcon = indicatorIcon;
this.mInstruction = instruction;
}
public CharSequence getTitle() {
return mTitle;
}
public ImageView getImageView() {
return mImageView;
}
public ImageView getIndicatorIcon() {
return mIndicatorIcon;
}
public CharSequence getInstruction() {
return mInstruction;
}
}
private static class TutorialPageChangeListener implements ViewPager.OnPageChangeListener {
private int mLastTutorialPagePosition = 0;
private final Context mContext;
private final TextSwitcher mTitle;
private final TextSwitcher mInstruction;
private final List<TutorialPage> mTutorialPages;
TutorialPageChangeListener(Context context, ViewGroup title, ViewGroup instruction,
List<TutorialPage> tutorialPages) {
this.mContext = context;
this.mTitle = (TextSwitcher) title;
this.mInstruction = (TextSwitcher) instruction;
this.mTutorialPages = tutorialPages;
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
// Do nothing.
}
@Override
public void onPageSelected(int position) {
final boolean isPreviousPosition =
mLastTutorialPagePosition > position;
@AnimRes
final int inAnimationResId = isPreviousPosition
? android.R.anim.slide_in_left
: com.android.internal.R.anim.slide_in_right;
@AnimRes
final int outAnimationResId = isPreviousPosition
? android.R.anim.slide_out_right
: com.android.internal.R.anim.slide_out_left;
mTitle.setInAnimation(mContext, inAnimationResId);
mTitle.setOutAnimation(mContext, outAnimationResId);
mTitle.setText(mTutorialPages.get(position).getTitle());
mInstruction.setInAnimation(mContext, inAnimationResId);
mInstruction.setOutAnimation(mContext, outAnimationResId);
mInstruction.setText(mTutorialPages.get(position).getInstruction());
for (TutorialPage page : mTutorialPages) {
page.getIndicatorIcon().setEnabled(false);
}
mTutorialPages.get(position).getIndicatorIcon().setEnabled(true);
mLastTutorialPagePosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
// Do nothing.
}
}
}

View File

@@ -192,7 +192,7 @@ public class AccessibilitySettings extends DashboardFragment {
}
// Observe changes from accessibility selection menu
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
mSettingsContentObserver = new SettingsContentObserver(mHandler, shortcutFeatureKeys) {
@Override

View File

@@ -342,7 +342,7 @@ final class AccessibilityUtil {
static String convertKeyFromSettings(@UserShortcutType int shortcutType) {
switch (shortcutType) {
case UserShortcutType.SOFTWARE:
return Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
return Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
case UserShortcutType.HARDWARE:
return Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
case UserShortcutType.TRIPLETAP:

View File

@@ -100,6 +100,12 @@ public class LaunchAccessibilityActivityPreferenceFragment extends
showDialog(DialogEnums.EDIT_SHORTCUT);
}
@Override
int getUserShortcutTypes() {
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
mComponentName);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Do not call super. We don't want to see the "Help & feedback" option on this page so as

View File

@@ -18,6 +18,7 @@ package com.android.settings.accessibility;
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.os.Bundle;
import android.view.View;
@@ -48,6 +49,22 @@ public class LegacyAccessibilityServicePreferenceFragment extends
setAllowedPreferredShortcutType(UserShortcutType.HARDWARE);
}
@Override
int getUserShortcutTypes() {
int shortcutTypes = super.getUserShortcutTypes();
final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
final boolean hasRequestAccessibilityButtonFlag =
(info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
if (hasRequestAccessibilityButtonFlag) {
shortcutTypes |= UserShortcutType.SOFTWARE;
} else {
shortcutTypes &= (~UserShortcutType.SOFTWARE);
}
return shortcutTypes;
}
private void setAllowedPreferredShortcutType(int type) {
final AccessibilityUserShortcutType shortcut = new AccessibilityUserShortcutType(
mComponentName.flattenToString(), type);

View File

@@ -120,7 +120,7 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
Context.ACCESSIBILITY_SERVICE);
final String assignedId = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
if (!TextUtils.isEmpty(assignedId) && !MAGNIFICATION_COMPONENT_ID.equals(assignedId)) {
final ComponentName assignedComponentName = ComponentName.unflattenFromString(
assignedId);

View File

@@ -106,7 +106,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends
// capabilities. For
// example, before JellyBean MR2 the user was granting the explore by touch
// one.
private AccessibilityServiceInfo getAccessibilityServiceInfo() {
AccessibilityServiceInfo getAccessibilityServiceInfo() {
final List<AccessibilityServiceInfo> infos = AccessibilityManager.getInstance(
getPrefContext()).getInstalledAccessibilityServiceList();
@@ -164,16 +164,6 @@ public class ToggleAccessibilityServicePreferenceFragment extends
this::onDialogButtonFromDisableToggleClicked);
break;
}
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL: {
if (AccessibilityUtil.isGestureNavigateEnabled(getPrefContext())) {
mDialog = AccessibilityGestureNavigationTutorial
.showGestureNavigationTutorialDialog(getPrefContext());
} else {
mDialog = AccessibilityGestureNavigationTutorial
.showAccessibilityButtonTutorialDialog(getPrefContext());
}
break;
}
default: {
mDialog = super.onCreateDialog(dialogId);
}
@@ -197,6 +187,12 @@ public class ToggleAccessibilityServicePreferenceFragment extends
}
}
@Override
int getUserShortcutTypes() {
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
mComponentName);
}
@Override
protected void updateToggleServiceTitle(SwitchPreference switchPreference) {
final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
@@ -301,6 +297,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends
} else {
AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes,
mComponentName);
showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
}
} else {
AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes,
@@ -414,6 +411,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends
final int shortcutTypes = getUserShortcutTypes(getPrefContext(), UserShortcutType.SOFTWARE);
AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes, mComponentName);
mIsDialogShown.set(false);
showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
mDialog.dismiss();
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));

View File

@@ -153,7 +153,7 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (KEY_DELAY_MODE.equals(key)) {
int delayMillis = getSharedPreferenceForDelayValue();
final int delayMillis = getSharedPreferenceForDelayValue();
updateCustomDelayValue(delayMillis);
}
}
@@ -172,10 +172,11 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro
}
private int getSharedPreferenceForDelayValue() {
int delayMillis = mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE,
final int delayMillis = Settings.Secure.getInt(mContentResolver,
Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
AccessibilityManager.AUTOCLICK_DELAY_DEFAULT);
return delayMillis;
return mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE, delayMillis);
}
private void putSecureInt(String name, int value) {
@@ -190,14 +191,14 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro
}
private void minusDelayByImageView() {
int delayMillis = getSharedPreferenceForDelayValue();
final int delayMillis = getSharedPreferenceForDelayValue();
if (delayMillis > MIN_AUTOCLICK_DELAY_MS) {
updateCustomDelayValue(delayMillis - AUTOCLICK_DELAY_STEP);
}
}
private void plusDelayByImageView() {
int delayMillis = getSharedPreferenceForDelayValue();
final int delayMillis = getSharedPreferenceForDelayValue();
if (delayMillis < MAX_AUTOCLICK_DELAY_MS) {
updateCustomDelayValue(delayMillis + AUTOCLICK_DELAY_STEP);
}

View File

@@ -116,7 +116,7 @@ public class ToggleAutoclickPreferenceController extends BasePreferenceControlle
@Override
public void onRadioButtonClicked(RadioButtonPreference preference) {
int value = mAccessibilityAutoclickKeyToValueMap.get(mPreferenceKey);
final int value = mAccessibilityAutoclickKeyToValueMap.get(mPreferenceKey);
handleRadioButtonPreferenceChange(value);
if (mOnChangeListener != null) {
mOnChangeListener.onCheckedChanged(mDelayModePref);
@@ -137,11 +137,15 @@ public class ToggleAutoclickPreferenceController extends BasePreferenceControlle
public void updateState(Preference preference) {
super.updateState(preference);
mCurrentUiAutoClickMode = getSharedPreferenceForAutoClickMode();
final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 0) == 1;
mCurrentUiAutoClickMode =
enabled ? getSharedPreferenceForAutoClickMode() : AUTOCLICK_OFF_MODE;
// Reset RadioButton.
mDelayModePref.setChecked(false);
int mode = mAccessibilityAutoclickKeyToValueMap.get(mDelayModePref.getKey());
final int mode = mAccessibilityAutoclickKeyToValueMap.get(mDelayModePref.getKey());
updatePreferenceCheckedState(mode);
updatePreferenceVisibleState(mode);
}
@@ -155,10 +159,10 @@ public class ToggleAutoclickPreferenceController extends BasePreferenceControlle
}
private void setAutoclickModeToKeyMap() {
String[] autoclickKeys = mResources.getStringArray(
final String[] autoclickKeys = mResources.getStringArray(
R.array.accessibility_autoclick_control_selector_keys);
int[] autoclickValues = mResources.getIntArray(
final int[] autoclickValues = mResources.getIntArray(
R.array.accessibility_autoclick_selector_values);
final int autoclickValueCount = autoclickValues.length;
@@ -168,19 +172,14 @@ public class ToggleAutoclickPreferenceController extends BasePreferenceControlle
}
private void handleRadioButtonPreferenceChange(int preference) {
if (preference == AUTOCLICK_OFF_MODE) {
putSecureInt(Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, /*value= */ 0);
} else {
putSecureInt(Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, /*value= */ 1);
}
putSecureInt(Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
(preference != AUTOCLICK_OFF_MODE) ? /* enabled */ 1 : /* disabled */ 0);
mSharedPreferences.edit().putInt(KEY_DELAY_MODE, preference).apply();
if (preference == AUTOCLICK_CUSTOM_MODE) {
return;
if (preference != AUTOCLICK_CUSTOM_MODE) {
putSecureInt(CONTROL_AUTOCLICK_DELAY_SECURE, preference);
}
putSecureInt(CONTROL_AUTOCLICK_DELAY_SECURE, preference);
}
private void putSecureInt(String name, int value) {
@@ -188,6 +187,6 @@ public class ToggleAutoclickPreferenceController extends BasePreferenceControlle
}
private int getSharedPreferenceForAutoClickMode() {
return mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_OFF_MODE);
return mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_CUSTOM_MODE);
}
}

View File

@@ -124,6 +124,12 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
showDialog(DialogEnums.EDIT_SHORTCUT);
}
@Override
int getUserShortcutTypes() {
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
mComponentName);
}
private void updateSwitchBarToggleSwitch() {
final boolean checked = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON;
if (mToggleServiceDividerSwitchPreference.isChecked() == checked) {

View File

@@ -198,6 +198,12 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
showDialog(DialogEnums.EDIT_SHORTCUT);
}
@Override
int getUserShortcutTypes() {
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
mComponentName);
}
private void updateSwitchBarToggleSwitch() {
final boolean checked = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON;
if (mToggleServiceDividerSwitchPreference.isChecked() == checked) {

View File

@@ -42,7 +42,6 @@ import android.view.accessibility.AccessibilityManager.TouchExplorationStateChan
import android.widget.CheckBox;
import android.widget.ImageView;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
@@ -250,14 +249,21 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
@Override
public Dialog onCreateDialog(int dialogId) {
Dialog dialog;
switch (dialogId) {
case DialogEnums.EDIT_SHORTCUT:
final CharSequence dialogTitle = getPrefContext().getString(
R.string.accessibility_shortcut_title, mPackageName);
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
getPrefContext(), dialogTitle, this::callOnAlertDialogCheckboxClicked);
initializeDialogCheckBox(dialog);
return dialog;
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
dialog = AccessibilityGestureNavigationTutorial
.createAccessibilityTutorialDialog(getPrefContext(),
getUserShortcutTypes());
dialog.setCanceledOnTouchOutside(false);
return dialog;
default:
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
}
@@ -268,6 +274,8 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
switch (dialogId) {
case DialogEnums.EDIT_SHORTCUT:
return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT;
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
return SettingsEnums.DIALOG_ACCESSIBILITY_TUTORIAL;
default:
return SettingsEnums.ACTION_UNKNOWN;
}
@@ -334,6 +342,11 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
removeActionBarToggleSwitch();
}
/**
* Returns the shortcut type list which has been checked by user.
*/
abstract int getUserShortcutTypes();
protected void updateToggleServiceTitle(SwitchPreference switchPreference) {
switchPreference.setTitle(R.string.accessibility_service_master_switch_title);
}
@@ -658,6 +671,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
if (preference.isChecked()) {
AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes,
mComponentName);
showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
} else {
AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes,
mComponentName);

View File

@@ -224,24 +224,22 @@ public class ToggleScreenMagnificationPreferenceFragment extends
@Override
public Dialog onCreateDialog(int dialogId) {
final AlertDialog dialog;
switch (dialogId) {
case DialogEnums.GESTURE_NAVIGATION_TUTORIAL:
return AccessibilityGestureNavigationTutorial
.showGestureNavigationTutorialDialog(getPrefContext());
case DialogEnums.ACCESSIBILITY_BUTTON_TUTORIAL:
return AccessibilityGestureNavigationTutorial
.showAccessibilityButtonTutorialDialog(getPrefContext());
case DialogEnums.MAGNIFICATION_EDIT_SHORTCUT:
final CharSequence dialogTitle = getPrefContext().getString(
R.string.accessibility_shortcut_title, mPackageName);
final AlertDialog dialog =
AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
dialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
getPrefContext(), dialogTitle,
this::callOnAlertDialogCheckboxClicked);
initializeDialogCheckBox(dialog);
return dialog;
default:
return super.onCreateDialog(dialogId);
}
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
}
private void setDialogTextAreaClickListener(View dialogView, CheckBox checkBox) {
@@ -408,18 +406,21 @@ public class ToggleScreenMagnificationPreferenceFragment extends
case DialogEnums.MAGNIFICATION_EDIT_SHORTCUT:
return SettingsEnums.DIALOG_MAGNIFICATION_EDIT_SHORTCUT;
default:
return 0;
return super.getDialogMetricsCategory(dialogId);
}
}
@Override
int getUserShortcutTypes() {
return getUserShortcutTypeFromSettings(getPrefContext());
}
@Override
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
if (enabled && TextUtils.equals(
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
preferenceKey)) {
showDialog(AccessibilityUtil.isGestureNavigateEnabled(getPrefContext())
? DialogEnums.GESTURE_NAVIGATION_TUTORIAL
: DialogEnums.ACCESSIBILITY_BUTTON_TUTORIAL);
showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
}
MagnificationPreferenceFragment.setChecked(getContentResolver(), preferenceKey, enabled);
}
@@ -449,6 +450,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends
final int shortcutTypes = getUserShortcutTypes(getPrefContext(), UserShortcutType.SOFTWARE);
if (preference.isChecked()) {
optInAllMagnificationValuesToSettings(getPrefContext(), shortcutTypes);
showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
} else {
optOutAllMagnificationValuesFromSettings(getPrefContext(), shortcutTypes);
}

View File

@@ -320,6 +320,14 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
addPreferencesFromResource(resId);
final PreferenceScreen screen = getPreferenceScreen();
screen.setOnExpandButtonClickListener(this);
displayResourceTilesToScreen(screen);
}
/**
* Perform {@link AbstractPreferenceController#displayPreference(PreferenceScreen)}
* on all {@link AbstractPreferenceController}s.
*/
protected void displayResourceTilesToScreen(PreferenceScreen screen) {
mPreferenceControllers.values().stream().flatMap(Collection::stream).forEach(
controller -> controller.displayPreference(screen));
}

View File

@@ -50,15 +50,12 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
public int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
public boolean mChecked;
public boolean mMultiSimDialog;
@VisibleForTesting
ProxySubscriptionManager mProxySubscriptionMgr;
private MobileDataEnabledListener mDataStateListener;
public CellDataPreference(Context context, AttributeSet attrs) {
super(context, attrs, TypedArrayUtils.getAttr(context,
androidx.preference.R.attr.switchPreferenceStyle,
android.R.attr.switchPreferenceStyle));
mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(context);
mDataStateListener = new MobileDataEnabledListener(context, this);
}
@@ -88,13 +85,15 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
public void onAttached() {
super.onAttached();
mDataStateListener.start(mSubId);
mProxySubscriptionMgr.addActiveSubscriptionsListener(mOnSubscriptionsChangeListener);
getProxySubscriptionManager()
.addActiveSubscriptionsListener(mOnSubscriptionsChangeListener);
}
@Override
public void onDetached() {
mDataStateListener.stop();
mProxySubscriptionMgr.removeActiveSubscriptionsListener(mOnSubscriptionsChangeListener);
getProxySubscriptionManager()
.removeActiveSubscriptionsListener(mOnSubscriptionsChangeListener);
super.onDetached();
}
@@ -104,8 +103,8 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
throw new IllegalArgumentException("CellDataPreference needs a SubscriptionInfo");
}
mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(getContext());
mProxySubscriptionMgr.addActiveSubscriptionsListener(mOnSubscriptionsChangeListener);
getProxySubscriptionManager()
.addActiveSubscriptionsListener(mOnSubscriptionsChangeListener);
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
mSubId = subId;
@@ -115,6 +114,16 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
updateChecked();
}
@VisibleForTesting
ProxySubscriptionManager getProxySubscriptionManager() {
return ProxySubscriptionManager.getInstance(getContext());
}
@VisibleForTesting
SubscriptionInfo getActiveSubscriptionInfo(int subId) {
return getProxySubscriptionManager().getActiveSubscriptionInfo(subId);
}
private void updateChecked() {
setChecked(getContext().getSystemService(TelephonyManager.class).getDataEnabled(mSubId));
}
@@ -122,7 +131,7 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
private void updateEnabled() {
// If this subscription is not active, for example, SIM card is taken out, we disable
// the button.
setEnabled(mProxySubscriptionMgr.getActiveSubscriptionInfo(mSubId) != null);
setEnabled(getActiveSubscriptionInfo(mSubId) != null);
}
@Override
@@ -130,9 +139,8 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
final Context context = getContext();
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
.action(context, SettingsEnums.ACTION_CELL_DATA_TOGGLE, !mChecked);
final SubscriptionInfo currentSir = mProxySubscriptionMgr.getActiveSubscriptionInfo(
mSubId);
final SubscriptionInfo nextSir = mProxySubscriptionMgr.getActiveSubscriptionInfo(
final SubscriptionInfo currentSir = getActiveSubscriptionInfo(mSubId);
final SubscriptionInfo nextSir = getActiveSubscriptionInfo(
SubscriptionManager.getDefaultDataSubscriptionId());
if (mChecked) {
setMobileDataEnabled(false);
@@ -186,9 +194,8 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
private void showMultiSimDialog(Builder builder,
DialogInterface.OnClickListener listener) {
final SubscriptionInfo currentSir = mProxySubscriptionMgr.getActiveSubscriptionInfo(
mSubId);
final SubscriptionInfo nextSir = mProxySubscriptionMgr.getActiveSubscriptionInfo(
final SubscriptionInfo currentSir = getActiveSubscriptionInfo(mSubId);
final SubscriptionInfo nextSir = getActiveSubscriptionInfo(
SubscriptionManager.getDefaultDataSubscriptionId());
final String previousName = (nextSir == null)
@@ -205,8 +212,7 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
}
private void disableDataForOtherSubscriptions(int subId) {
final SubscriptionInfo subInfo = mProxySubscriptionMgr.getActiveSubscriptionInfo(
subId);
final SubscriptionInfo subInfo = getActiveSubscriptionInfo(subId);
if (subInfo != null) {
getContext().getSystemService(TelephonyManager.class).setDataEnabled(subId, false);
}
@@ -218,7 +224,7 @@ public class CellDataPreference extends CustomDialogPreferenceCompat
return;
}
if (mMultiSimDialog) {
mProxySubscriptionMgr.get().setDefaultDataSubId(mSubId);
getProxySubscriptionManager().get().setDefaultDataSubId(mSubId);
setMobileDataEnabled(true);
disableDataForOtherSubscriptions(mSubId);
} else {

View File

@@ -78,10 +78,7 @@ public class DataUsageSummary extends DataUsageBaseFragment implements DataUsage
super.onCreate(icicle);
Context context = getContext();
// Enable ProxySubscriptionMgr with Lifecycle support for all controllers
// live within this fragment
mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(context);
mProxySubscriptionMgr.setLifecycle(getLifecycle());
enableProxySubscriptionManager(context);
boolean hasMobileData = DataUsageUtils.hasMobileData(context);
@@ -151,6 +148,14 @@ public class DataUsageSummary extends DataUsageBaseFragment implements DataUsage
addMobileSection(subId, null);
}
@VisibleForTesting
void enableProxySubscriptionManager(Context context) {
// Enable ProxySubscriptionMgr with Lifecycle support for all controllers
// live within this fragment
mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(context);
mProxySubscriptionMgr.setLifecycle(getLifecycle());
}
private void addMobileSection(int subId, SubscriptionInfo subInfo) {
TemplatePreferenceCategory category = (TemplatePreferenceCategory)
inflatePreferences(R.xml.data_usage_cellular);

View File

@@ -64,7 +64,7 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
private static final float RELATIVE_SIZE_LARGE = 1.25f * 1.25f; // (1/0.8)^2
private static final float RELATIVE_SIZE_SMALL = 1.0f / RELATIVE_SIZE_LARGE; // 0.8^2
private final EntityHeaderController mEntityHeaderController;
private EntityHeaderController mEntityHeaderController;
private final Lifecycle mLifecycle;
private final PreferenceFragmentCompat mFragment;
protected DataUsageController mDataUsageController;
@@ -103,8 +103,6 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
Lifecycle lifecycle, PreferenceFragmentCompat fragment, int subscriptionId) {
super(activity, KEY);
mEntityHeaderController = EntityHeaderController.newInstance(activity,
fragment, null);
mLifecycle = lifecycle;
mFragment = fragment;
init(subscriptionId);
@@ -122,14 +120,14 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
mContext.getSystemService(NetworkPolicyManager.class);
mPolicyEditor = new NetworkPolicyEditor(policyManager);
mHasMobileData = SubscriptionManager.isValidSubscriptionId(mSubId)
&& DataUsageUtils.hasMobileData(mContext);
mHasMobileData = DataUsageUtils.hasMobileData(mContext);
mDataUsageController = new DataUsageController(mContext);
mDataUsageController.setSubscriptionId(mSubId);
mDataInfoController = new DataUsageInfoController();
if (mHasMobileData) {
final SubscriptionInfo subInfo = getSubscriptionInfo(mSubId);
if (subInfo != null) {
mDataUsageTemplate = R.string.cell_data_template;
} else if (DataUsageUtils.hasWifiRadio(mContext)) {
mDataUsageTemplate = R.string.wifi_data_template;
@@ -165,6 +163,10 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
@Override
public void onStart() {
if (mEntityHeaderController == null) {
mEntityHeaderController =
EntityHeaderController.newInstance((Activity) mContext, mFragment, null);
}
RecyclerView view = mFragment.getListView();
mEntityHeaderController.setRecyclerView(view, mLifecycle);
mEntityHeaderController.styleActionBar((Activity) mContext);
@@ -178,18 +180,16 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
@VisibleForTesting
SubscriptionInfo getSubscriptionInfo(int subscriptionId) {
if (!mHasMobileData) {
return null;
}
return ProxySubscriptionManager.getInstance(mContext)
.getAccessibleSubscriptionInfo(subscriptionId);
}
@VisibleForTesting
boolean hasSim() {
return DataUsageUtils.hasSim(mContext);
}
@Override
public int getAvailabilityStatus(int subId) {
return hasSim()
return (getSubscriptionInfo(subId) != null)
|| DataUsageUtils.hasWifiRadio(mContext) ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@@ -197,16 +197,19 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
public void updateState(Preference preference) {
DataUsageSummaryPreference summaryPreference = (DataUsageSummaryPreference) preference;
final DataUsageController.DataUsageInfo info;
final SubscriptionInfo subInfo = getSubscriptionInfo(mSubId);
if (hasSim()) {
info = mDataUsageController.getDataUsageInfo(mDefaultTemplate);
if (subInfo == null) {
mDefaultTemplate = NetworkTemplate.buildTemplateWifiWildcard();
}
final DataUsageController.DataUsageInfo info =
mDataUsageController.getDataUsageInfo(mDefaultTemplate);
if (subInfo != null) {
mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate));
summaryPreference.setWifiMode(/* isWifiMode */ false,
/* usagePeriod */ null, /* isSingleWifi */ false);
} else {
info = mDataUsageController.getDataUsageInfo(
NetworkTemplate.buildTemplateWifiWildcard());
summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */
info.period, /* isSingleWifi */ false);
summaryPreference.setLimitInfo(null);

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2020 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.gestures;
import android.content.ContentResolver;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
public class PowerMenuPrivacyPreferenceController extends TogglePreferenceController {
private static final String SETTING_KEY = Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT;
private static final String CARDS_AVAILABLE_KEY =
Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
private static final String CARDS_ENABLED_KEY = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
private static final String CONTROLS_ENABLED_KEY = Settings.Secure.CONTROLS_ENABLED;
public PowerMenuPrivacyPreferenceController(Context context,
String preferenceKey) {
super(context, preferenceKey);
}
@Override
public boolean isChecked() {
return Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 0) != 0;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putInt(mContext.getContentResolver(), SETTING_KEY,
isChecked ? 1 : 0);
}
@Override
public CharSequence getSummary() {
boolean cardsAvailable = Settings.Secure.getInt(mContext.getContentResolver(),
CARDS_AVAILABLE_KEY, 0) != 0;
final int res;
if (!isSecure()) {
res = R.string.power_menu_privacy_not_secure;
} else if (cardsAvailable) {
res = R.string.power_menu_privacy_show;
} else {
res = R.string.power_menu_privacy_show_controls;
}
return mContext.getText(res);
}
@Override
public int getAvailabilityStatus() {
// hide if lockscreen isn't secure for this user
return isEnabled() && isSecure() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
preference.setEnabled(getAvailabilityStatus() != DISABLED_DEPENDENT_SETTING);
refreshSummary(preference);
}
private boolean isEnabled() {
final ContentResolver resolver = mContext.getContentResolver();
boolean cardsAvailable = Settings.Secure.getInt(resolver, CARDS_AVAILABLE_KEY, 0) != 0;
boolean cardsEnabled = Settings.Secure.getInt(resolver, CARDS_ENABLED_KEY, 0) != 0;
boolean controlsEnabled = Settings.Secure.getInt(resolver, CONTROLS_ENABLED_KEY, 0) != 0;
return (cardsAvailable && cardsEnabled) || controlsEnabled;
}
private boolean isSecure() {
final LockPatternUtils utils = FeatureFactory.getFactory(mContext)
.getSecurityFeatureProvider()
.getLockPatternUtils(mContext);
int userId = UserHandle.myUserId();
return utils.isSecure(userId);
}
}

View File

@@ -23,6 +23,7 @@ import android.content.DialogInterface;
import android.os.Bundle;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsRcsManager;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentManager;
@@ -39,9 +40,11 @@ public class ContactDiscoveryDialogFragment extends InstrumentedDialogFragment
implements DialogInterface.OnClickListener {
private static final String SUB_ID_KEY = "sub_id_key";
private static final String CARRIER_NAME_KEY = "carrier_name_key";
private static final String DIALOG_TAG = "discovery_dialog:";
private int mSubId;
private CharSequence mCarrierName;
private ImsManager mImsManager;
/**
@@ -50,10 +53,11 @@ public class ContactDiscoveryDialogFragment extends InstrumentedDialogFragment
* @param subId The subscription ID to associate with this Dialog.
* @return a new instance of ContactDiscoveryDialogFragment.
*/
public static ContactDiscoveryDialogFragment newInstance(int subId) {
public static ContactDiscoveryDialogFragment newInstance(int subId, CharSequence carrierName) {
final ContactDiscoveryDialogFragment dialogFragment = new ContactDiscoveryDialogFragment();
final Bundle args = new Bundle();
args.putInt(SUB_ID_KEY, subId);
args.putCharSequence(CARRIER_NAME_KEY, carrierName);
dialogFragment.setArguments(args);
return dialogFragment;
@@ -64,18 +68,30 @@ public class ContactDiscoveryDialogFragment extends InstrumentedDialogFragment
super.onAttach(context);
final Bundle args = getArguments();
mSubId = args.getInt(SUB_ID_KEY);
mCarrierName = args.getCharSequence(CARRIER_NAME_KEY);
mImsManager = getImsManager(context);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
final int title = R.string.contact_discovery_opt_in_dialog_title;
int message = R.string.contact_discovery_opt_in_dialog_message;
builder.setMessage(getResources().getString(message))
CharSequence title;
CharSequence message;
if (!TextUtils.isEmpty(mCarrierName)) {
title = getContext().getString(
R.string.contact_discovery_opt_in_dialog_title, mCarrierName);
message = getContext().getString(
R.string.contact_discovery_opt_in_dialog_message, mCarrierName);
} else {
title = getContext().getString(
R.string.contact_discovery_opt_in_dialog_title_no_carrier_defined);
message = getContext().getString(
R.string.contact_discovery_opt_in_dialog_message_no_carrier_defined);
}
builder.setMessage(message)
.setTitle(title)
.setIconAttribute(android.R.attr.alertDialogIcon)
.setPositiveButton(android.R.string.ok, this)
.setPositiveButton(R.string.confirmation_turn_on, this)
.setNegativeButton(android.R.string.cancel, this);
return builder.create();
}

View File

@@ -22,6 +22,7 @@ import android.net.Uri;
import android.os.PersistableBundle;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.ims.ImsManager;
import android.util.Log;
@@ -34,6 +35,8 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.settings.network.SubscriptionUtil;
/**
* Controller for the "Contact Discovery" option present in MobileNetworkSettings.
@@ -130,7 +133,19 @@ public class ContactDiscoveryPreferenceController extends TelephonyTogglePrefere
private void showContentDiscoveryDialog() {
ContactDiscoveryDialogFragment dialog = ContactDiscoveryDialogFragment.newInstance(
mSubId);
mSubId, getCarrierDisplayName(preference.getContext()));
dialog.show(mFragmentManager, ContactDiscoveryDialogFragment.getFragmentTag(mSubId));
}
private CharSequence getCarrierDisplayName(Context context) {
CharSequence result = "";
for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(context)) {
if (mSubId == info.getSubscriptionId()) {
result = info.getDisplayName();
break;
}
}
return result;
}
}

View File

@@ -22,22 +22,33 @@ import android.net.NetworkTemplate;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settingslib.net.DataUsageController;
import com.android.settingslib.utils.ThreadUtils;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
/**
* Preference controller for "Data usage"
*/
public class DataUsagePreferenceController extends TelephonyBasePreferenceController {
private NetworkTemplate mTemplate;
private static final String LOG_TAG = "DataUsagePreferCtrl";
private Future<NetworkTemplate> mTemplateFuture;
private AtomicReference<NetworkTemplate> mTemplate;
public DataUsagePreferenceController(Context context, String key) {
super(context, key);
mTemplate = new AtomicReference<NetworkTemplate>();
}
@Override
@@ -53,7 +64,7 @@ public class DataUsagePreferenceController extends TelephonyBasePreferenceContro
return false;
}
final Intent intent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE);
intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mTemplate);
intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, getNetworkTemplate());
intent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
mContext.startActivity(intent);
@@ -78,22 +89,49 @@ public class DataUsagePreferenceController extends TelephonyBasePreferenceContro
public void init(int subId) {
mSubId = subId;
mTemplate.set(null);
mTemplateFuture = ThreadUtils.postOnBackgroundThread(()
-> fetchMobileTemplate(mContext, mSubId));
}
private NetworkTemplate fetchMobileTemplate(Context context, int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
return;
return null;
}
mTemplate = DataUsageUtils.getDefaultTemplate(mContext, mSubId);
return DataUsageUtils.getMobileTemplate(context, subId);
}
private NetworkTemplate getNetworkTemplate() {
if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
return null;
}
NetworkTemplate template = mTemplate.get();
if (template != null) {
return template;
}
try {
template = mTemplateFuture.get();
mTemplate.set(template);
} catch (ExecutionException | InterruptedException | NullPointerException exception) {
Log.e(LOG_TAG, "Fail to get data usage template", exception);
}
return template;
}
@VisibleForTesting
DataUsageController.DataUsageInfo getDataUsageInfo(DataUsageController controller) {
return controller.getDataUsageInfo(getNetworkTemplate());
}
private CharSequence getDataUsageSummary(Context context, int subId) {
final DataUsageController controller = new DataUsageController(context);
controller.setSubscriptionId(subId);
final DataUsageController.DataUsageInfo usageInfo = controller.getDataUsageInfo(mTemplate);
final DataUsageController.DataUsageInfo usageInfo = getDataUsageInfo(controller);
long usageLevel = usageInfo.usageLevel;
if (usageLevel <= 0L) {
usageLevel = controller.getHistoricalUsageLevel(mTemplate);
usageLevel = controller.getHistoricalUsageLevel(getNetworkTemplate());
}
if (usageLevel <= 0L) {
return null;

View File

@@ -22,6 +22,7 @@ import android.os.Bundle;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsRcsManager;
import android.text.TextUtils;
import android.util.Log;
@@ -79,7 +80,8 @@ public class MobileNetworkActivity extends SettingsBaseActivity
int oldSubId = mCurSubscriptionId;
mCurSubscriptionId = updateSubscriptionIndex;
mFragmentForceReload = (mCurSubscriptionId == oldSubId);
updateSubscriptions(getSubscription());
final SubscriptionInfo info = getSubscription();
updateSubscriptions(info);
// If the subscription has changed or the new intent doesnt contain the opt in action,
// remove the old discovery dialog. If the activity is being recreated, we will see
@@ -91,7 +93,7 @@ public class MobileNetworkActivity extends SettingsBaseActivity
// evaluate showing the new discovery dialog if this intent contains an action to show the
// opt-in.
if (doesIntentContainOptInAction(intent)) {
maybeShowContactDiscoveryDialog(updateSubscriptionIndex);
maybeShowContactDiscoveryDialog(info);
}
}
@@ -125,7 +127,7 @@ public class MobileNetworkActivity extends SettingsBaseActivity
final SubscriptionInfo subscription = getSubscription();
updateTitleAndNavigation(subscription);
maybeShowContactDiscoveryDialog(mCurSubscriptionId);
maybeShowContactDiscoveryDialog(subscription);
// Since onChanged() will take place immediately when addActiveSubscriptionsListener(),
// perform registration after mCurSubscriptionId been configured.
@@ -276,7 +278,13 @@ public class MobileNetworkActivity extends SettingsBaseActivity
.findFragmentByTag(ContactDiscoveryDialogFragment.getFragmentTag(subId));
}
private void maybeShowContactDiscoveryDialog(int subId) {
private void maybeShowContactDiscoveryDialog(SubscriptionInfo info) {
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
CharSequence carrierName = "";
if (info != null) {
subId = info.getSubscriptionId();
carrierName = info.getDisplayName();
}
// If this activity was launched using ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN, show the
// associated dialog only if the opt-in has not been granted yet.
boolean showOptInDialog = doesIntentContainOptInAction(getIntent())
@@ -287,7 +295,7 @@ public class MobileNetworkActivity extends SettingsBaseActivity
ContactDiscoveryDialogFragment fragment = getContactDiscoveryFragment(subId);
if (showOptInDialog) {
if (fragment == null) {
fragment = ContactDiscoveryDialogFragment.newInstance(subId);
fragment = ContactDiscoveryDialogFragment.newInstance(subId, carrierName);
}
// Only try to show the dialog if it has not already been added, otherwise we may
// accidentally add it multiple times, causing multiple dialogs.

View File

@@ -53,6 +53,7 @@ public class ConversationListSettings extends DashboardFragment {
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
mControllers = new ArrayList<>();
mControllers.add(new NoConversationsPreferenceController(context, mBackend));
mControllers.add(new PriorityConversationsPreferenceController(context, mBackend));
mControllers.add(new AllConversationsPreferenceController(context, mBackend));
return new ArrayList<>(mControllers);

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification.app;
import android.content.Context;
import android.os.AsyncTask;
import android.service.notification.ConversationChannelWrapper;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import com.android.settings.notification.NotificationBackend;
import java.util.Collections;
import java.util.List;
public class NoConversationsPreferenceController extends ConversationListPreferenceController {
private static final String KEY = "no_conversations";
private List<ConversationChannelWrapper> mConversations;
public NoConversationsPreferenceController(Context context,
NotificationBackend backend) {
super(context, backend);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
boolean matchesFilter(ConversationChannelWrapper conversation) {
return false;
}
@Override
public void updateState(Preference preference) {
// Load conversations
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
mConversations = mBackend.getConversations(false).getList();
return null;
}
@Override
protected void onPostExecute(Void unused) {
if (mContext == null) {
return;
}
preference.setVisible(mConversations.size() == 0);
}
}.execute();
}
}

View File

@@ -30,6 +30,8 @@ import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
@@ -71,6 +73,7 @@ public class NotificationHistoryActivity extends Activity {
private HistoryLoader mHistoryLoader;
private INotificationManager mNm;
private UserManager mUm;
private PackageManager mPm;
private CountDownLatch mCountdownLatch;
private Future mCountdownFuture;
@@ -104,6 +107,8 @@ public class NotificationHistoryActivity extends Activity {
TextView label = viewForPackage.findViewById(R.id.label);
label.setText(nhp.label != null ? nhp.label : nhp.pkgName);
label.setContentDescription(mUm.getBadgedLabelForUser(label.getText(),
UserHandle.getUserHandleForUid(nhp.uid)));
ImageView icon = viewForPackage.findViewById(R.id.icon);
icon.setImageDrawable(nhp.icon);
@@ -140,6 +145,7 @@ public class NotificationHistoryActivity extends Activity {
super.onResume();
mPm = getPackageManager();
mUm = getSystemService(UserManager.class);
// wait for history loading and recent/snooze loading
mCountdownLatch = new CountDownLatch(2);

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 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.accessibility;
import static com.android.settings.accessibility.AccessibilityGestureNavigationTutorial.createAccessibilityTutorialDialog;
import static com.android.settings.accessibility.AccessibilityGestureNavigationTutorial.createShortcutTutorialPages;
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import androidx.appcompat.app.AlertDialog;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/** Tests for {@link AccessibilityGestureNavigationTutorial}. */
@RunWith(RobolectricTestRunner.class)
public final class AccessibilityGestureNavigationTutorialTest {
private Context mContext;
private int mShortcutTypes;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mShortcutTypes = /* initial */ 0;
}
@Test(expected = IllegalArgumentException.class)
public void createTutorialPages_shortcutListIsEmpty_throwsException() {
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
}
@Test
public void createTutorialPages_turnOnTripleTapShortcut_hasOnePage() {
mShortcutTypes |= UserShortcutType.TRIPLETAP;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
assertThat(createShortcutTutorialPages(mContext,
mShortcutTypes)).hasSize(/* expectedSize= */ 1);
assertThat(alertDialog).isNotNull();
}
@Test
public void createTutorialPages_turnOnSoftwareShortcut_hasOnePage() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
assertThat(createShortcutTutorialPages(mContext,
mShortcutTypes)).hasSize(/* expectedSize= */ 1);
assertThat(alertDialog).isNotNull();
}
@Test
public void createTutorialPages_turnOnSoftwareAndHardwareShortcuts_hasTwoPages() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
mShortcutTypes |= UserShortcutType.HARDWARE;
final AlertDialog alertDialog =
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
assertThat(createShortcutTutorialPages(mContext,
mShortcutTypes)).hasSize(/* expectedSize= */ 2);
assertThat(alertDialog).isNotNull();
}
}

View File

@@ -52,7 +52,7 @@ public final class AccessibilityUtilTest {
private static final ComponentName DUMMY_COMPONENT_NAME2 = new ComponentName(DUMMY_PACKAGE_NAME,
DUMMY_CLASS_NAME2);
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;

View File

@@ -129,6 +129,11 @@ public class ToggleFeaturePreferenceFragmentTest {
return 0;
}
@Override
int getUserShortcutTypes() {
return 0;
}
@Override
public int getPreferenceScreenResId() {
return R.xml.placeholder_prefs;

View File

@@ -40,7 +40,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
private static final ComponentName DUMMY_COMPONENT_NAME = new ComponentName(DUMMY_PACKAGE_NAME,
DUMMY_CLASS_NAME);
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
private static final String TRIPLETAP_SHORTCUT_KEY =

View File

@@ -17,11 +17,14 @@ package com.android.settings.datausage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
@@ -31,7 +34,6 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settings.network.ProxySubscriptionManager;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -40,12 +42,13 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
@Ignore
public class CellDataPreferenceTest {
@Mock
private ProxySubscriptionManager mProxySubscriptionMgr;
@Mock
private SubscriptionManager mSubscriptionManager;
@Mock
private SubscriptionInfo mSubInfo;
private Context mContext;
@@ -57,8 +60,20 @@ public class CellDataPreferenceTest {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPreference = new CellDataPreference(mContext, null);
mPreference.mProxySubscriptionMgr = mProxySubscriptionMgr;
mPreference = new CellDataPreference(mContext, null) {
@Override
ProxySubscriptionManager getProxySubscriptionManager() {
return mProxySubscriptionMgr;
}
@Override
SubscriptionInfo getActiveSubscriptionInfo(int subId) {
return mSubInfo;
}
};
doNothing().when(mSubscriptionManager).setDefaultDataSubId(anyInt());
doReturn(mSubscriptionManager).when(mProxySubscriptionMgr).get();
doNothing().when(mProxySubscriptionMgr).addActiveSubscriptionsListener(any());
doNothing().when(mProxySubscriptionMgr).removeActiveSubscriptionsListener(any());
final LayoutInflater inflater = LayoutInflater.from(mContext);
final View view = inflater.inflate(mPreference.getLayoutResource(),
@@ -69,14 +84,13 @@ public class CellDataPreferenceTest {
@Test
public void noActiveSub_shouldDisable() {
doReturn(null).when(mProxySubscriptionMgr).getActiveSubscriptionInfo(anyInt());
mSubInfo = null;
mPreference.mOnSubscriptionsChangeListener.onChanged();
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void hasActiveSub_shouldEnable() {
doReturn(mSubInfo).when(mProxySubscriptionMgr).getActiveSubscriptionInfo(anyInt());
mPreference.mOnSubscriptionsChangeListener.onChanged();
assertThat(mPreference.isEnabled()).isTrue();
}

View File

@@ -19,7 +19,6 @@ package com.android.settings.datausage;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
@@ -159,8 +158,6 @@ public class DataUsageSummaryPreferenceControllerTest {
doReturn(CARRIER_NAME).when(mSubscriptionInfo).getCarrierName();
doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(mDefaultSubscriptionId);
doReturn(mSubscriptionPlans).when(mController).getSubscriptionPlans(mDefaultSubscriptionId);
doReturn(true).when(mController).hasSim();
}
@After
@@ -355,56 +352,16 @@ public class DataUsageSummaryPreferenceControllerTest {
false /* isSingleWifi */);
}
@Test
public void testSummaryUpdate_noSim_shouldSetWifiMode() {
mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mController.mDataUsageController = mDataUsageController;
doReturn(TelephonyManager.SIM_STATE_ABSENT).when(mTelephonyManager).getSimState();
doReturn(false).when(mController).hasSim();
final long now = System.currentTimeMillis();
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
info.warningLevel = BillingCycleSettings.MIB_IN_BYTES;
info.limitLevel = BillingCycleSettings.MIB_IN_BYTES;
final Intent intent = new Intent();
doReturn(info).when(mDataUsageController).getDataUsageInfo(any());
setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS);
mController.updateState(mSummaryPreference);
verify(mSummaryPreference).setWifiMode(true /* isWifiMode */, info.period /* usagePeriod */,
false /* isSingleWifi */);
verify(mSummaryPreference).setLimitInfo(null);
verify(mSummaryPreference).setUsageNumbers(info.usageLevel, -1L, true);
verify(mSummaryPreference).setChartEnabled(false);
verify(mSummaryPreference).setUsageInfo(info.cycleEnd, -1L, null, 0, null);
}
@Test
public void testMobileData_preferenceAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void testMobileData_noSimNoWifi_preferenceDisabled() {
final int subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
mController.init(subscriptionId);
mController.mDataUsageController = mDataUsageController;
doReturn(TelephonyManager.SIM_STATE_ABSENT).when(mTelephonyManager).getSimState();
doReturn(false).when(mController).hasSim();
when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(false);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void testMobileData_noSimWifi_preferenceDisabled() {
final int subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
mController.init(subscriptionId);
mController.mDataUsageController = mDataUsageController;
doReturn(TelephonyManager.SIM_STATE_ABSENT).when(mTelephonyManager).getSimState();
when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.datausage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
@@ -83,7 +84,7 @@ public class DataUsageSummaryTest {
ShadowUserManager.getShadow().setIsAdminUser(true);
shadowContext.setSystemService(Context.NETWORK_POLICY_SERVICE, mNetworkPolicyManager);
mContext = spy(RuntimeEnvironment.application);
mContext = RuntimeEnvironment.application;
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
final ShadowTelephonyManager shadowTelephonyManager = Shadows.shadowOf(mTelephonyManager);
shadowTelephonyManager.setTelephonyManagerForSubscriptionId(
@@ -112,6 +113,7 @@ public class DataUsageSummaryTest {
ShadowDataUsageUtils.HAS_SIM = true;
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());
@@ -125,13 +127,13 @@ public class DataUsageSummaryTest {
}
@Test
@Ignore
public void configuration_withoutSim_shouldShowWifiSectionOnly() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
ShadowDataUsageUtils.HAS_SIM = false;
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());
@@ -145,13 +147,13 @@ public class DataUsageSummaryTest {
}
@Test
@Ignore
public void configuration_withoutMobile_shouldShowWifiSectionOnly() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = false;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
ShadowDataUsageUtils.HAS_SIM = false;
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());
@@ -166,7 +168,6 @@ public class DataUsageSummaryTest {
@Test
@Config(shadows = ShadowSubscriptionManager.class)
@Ignore
public void configuration_invalidDataSusbscription_shouldShowWifiSectionOnly() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
@@ -175,6 +176,7 @@ public class DataUsageSummaryTest {
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());

View File

@@ -16,16 +16,20 @@ package com.android.settings.display;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.display.ColorDisplayManager;
import android.location.LocationManager;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -36,10 +40,14 @@ public class NightDisplayAutoModePreferenceControllerTest {
private Context mContext;
private NightDisplayAutoModePreferenceController mController;
private LocationManager mLocationManager;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mContext = Mockito.spy(RuntimeEnvironment.application);
mLocationManager = Mockito.mock(LocationManager.class);
when(mLocationManager.isLocationEnabled()).thenReturn(true);
when(mContext.getSystemService(eq(LocationManager.class))).thenReturn(mLocationManager);
mController = new NightDisplayAutoModePreferenceController(mContext,
"night_display_auto_mode");
}
@@ -64,7 +72,6 @@ public class NightDisplayAutoModePreferenceControllerTest {
}
@Test
@Ignore
public void onPreferenceChange_changesAutoMode() {
mController.onPreferenceChange(null,
String.valueOf(ColorDisplayManager.AUTO_MODE_TWILIGHT));

View File

@@ -37,7 +37,6 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -102,16 +101,6 @@ public class DarkModeScheduleSelectorControllerTest {
verify(mPreference).setValueIndex(0);
}
@Test
@Ignore
public void nightMode_selectNightMode_locationOff() {
when(mLocationManager.isLocationEnabled()).thenReturn(false);
mController.onPreferenceChange(mPreference,
mContext.getString(R.string.dark_ui_auto_mode_never));
assertFalse(mController.onPreferenceChange(mPreference,
mContext.getString(R.string.dark_ui_auto_mode_auto)));
}
@Test
public void nightMode_updateStateNone_dropDownValueChangedToAuto() {
when(mUiService.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_AUTO);

View File

@@ -0,0 +1,205 @@
/*
* Copyright (C) 2020 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.gestures;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class PowerMenuPrivacyPreferenceControllerTest {
private static final String TEST_KEY = "test_key";
private static final String SETTING_KEY = Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT;
private static final String CARDS_AVAILABLE_KEY =
Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
private static final String CARDS_ENABLED_KEY = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
private static final String CONTROLS_ENABLED_KEY = Settings.Secure.CONTROLS_ENABLED;
private Context mContext;
private ContentResolver mContentResolver;
private PowerMenuPrivacyPreferenceController mController;
@Mock
private Preference mPreference;
@Mock
private LockPatternUtils mLockPatternUtils;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContentResolver = mContext.getContentResolver();
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
when(featureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
.thenReturn(mLockPatternUtils);
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
mController = new PowerMenuPrivacyPreferenceController(mContext, TEST_KEY);
}
@Test
public void isChecked_POWER_MENU_LOCKED_SHOW_CONTENTIs1_returnTrue() {
Settings.Secure.putInt(mContentResolver, SETTING_KEY, 1);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void isChecked_POWER_MENU_LOCKED_SHOW_CONTENTIs0_returnFalse() {
Settings.Secure.putInt(mContentResolver, SETTING_KEY, 0);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_POWER_MENU_LOCKED_SHOW_CONTENTIsNotSet_returnFalse() {
Settings.Secure.putString(mContentResolver, SETTING_KEY, null);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void setChecked_true_POWER_MENU_LOCKED_SHOW_CONTENTIsNot0() {
mController.setChecked(true);
assertThat(Settings.Secure.getInt(mContentResolver, SETTING_KEY, 0)).isNotEqualTo(0);
}
@Test
public void setChecked_false_POWER_MENU_LOCKED_SHOW_CONTENTIs0() {
mController.setChecked(false);
assertThat(Settings.Secure.getInt(mContentResolver, SETTING_KEY, 0)).isEqualTo(0);
}
@Test
public void getSummary_notSecureLock_isPower_menu_privacy_not_secureString() {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
assertThat(mController.getSummary()).isEqualTo(
mContext.getText(R.string.power_menu_privacy_not_secure));
}
@Test
public void getSummary_cardsAvailable_isPower_menu_privacy_showString() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
assertThat(mController.getSummary()).isEqualTo(
mContext.getText(R.string.power_menu_privacy_show));
}
@Test
public void getSummary_cardsUnavailable_isPower_menu_privacy_show_controlsString() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 0);
assertThat(mController.getSummary()).isEqualTo(
mContext.getText(R.string.power_menu_privacy_show_controls));
}
@Test
public void updateState_onPreferenceRefreshed_preferenceEnabledAndSummaryChanged() {
mController.updateState(mPreference);
verify(mPreference).setEnabled(anyBoolean());
verify(mPreference, atLeastOnce()).setSummary(mController.getSummary());
}
@Test
public void getAvailabilityStatus_allOff_returnsDisabled() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 0);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 0);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
}
@Test
public void getAvailabilityStatus_cardsUnavailableControlsOff_returnsDisabled() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 0);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 0);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
}
@Test
public void testAvailabilityStatus_cardsOnControlsOff_returnsAvailable() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 1);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 0);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_cardsOffControlsOn_returnsAvailable() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 0);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_allOn_returnsAvailable() {
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 1);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_allOnNotSecure_returnsDisabled() {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
Settings.Secure.putInt(mContentResolver, CARDS_AVAILABLE_KEY, 1);
Settings.Secure.putInt(mContentResolver, CARDS_ENABLED_KEY, 1);
Settings.Secure.putInt(mContentResolver, CONTROLS_ENABLED_KEY, 1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
}
}

View File

@@ -48,6 +48,7 @@ import org.robolectric.shadows.ShadowAlertDialog;
@Config(shadows = ShadowAlertDialog.class)
public class ContactDiscoveryDialogFragmentTest {
private static final int TEST_SUB_ID = 2;
private static final String TEST_CARRIER = "TestMobile";
@Mock private ImsManager mImsManager;
@Mock private ImsRcsManager mImsRcsManager;
@@ -60,7 +61,8 @@ public class ContactDiscoveryDialogFragmentTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mActivity = Robolectric.buildActivity(FragmentActivity.class).setup().get();
mDialogFragmentUT = spy(ContactDiscoveryDialogFragment.newInstance(TEST_SUB_ID));
mDialogFragmentUT = spy(ContactDiscoveryDialogFragment.newInstance(TEST_SUB_ID,
TEST_CARRIER));
doReturn(mImsManager).when(mDialogFragmentUT).getImsManager(any());
doReturn(mImsRcsManager).when(mImsManager).getImsRcsManager(TEST_SUB_ID);
doReturn(mRcsUceAdapter).when(mImsRcsManager).getUceAdapter();

View File

@@ -48,6 +48,7 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.SwitchPreference;
import com.android.settings.network.SubscriptionUtil;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -59,6 +60,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Collections;
@RunWith(RobolectricTestRunner.class)
public class ContactDiscoveryPreferenceControllerTest {
@@ -99,6 +102,8 @@ public class ContactDiscoveryPreferenceControllerTest {
mPreferenceControllerUT = new ContactDiscoveryPreferenceController(mContext,
"ContactDiscovery");
// Ensure subscriptionInfo check doesn't fail.
SubscriptionUtil.setAvailableSubscriptionsForTesting(Collections.emptyList());
mPreferenceControllerUT.init(mFragmentManager, TEST_SUB_ID, mLifecycle);
mSwitchPreferenceUT = spy(new SwitchPreference(mContext));
mSwitchPreferenceUT.setKey(mPreferenceControllerUT.getPreferenceKey());

View File

@@ -17,12 +17,12 @@
package com.android.settings.network.telephony;
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.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.content.Intent;
@@ -30,21 +30,22 @@ import android.net.TrafficStats;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.preference.SwitchPreference;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.net.DataUsageController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowTelephonyManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class DataUsagePreferenceControllerTest {
@@ -71,7 +72,7 @@ public class DataUsagePreferenceControllerTest {
doReturn(mNetworkStatsManager).when(mContext).getSystemService(NetworkStatsManager.class);
mPreference = new SwitchPreference(mContext);
mController = new DataUsagePreferenceController(mContext, "data_usage");
mController = spy(new DataUsagePreferenceController(mContext, "data_usage"));
mController.init(SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
}
@@ -114,8 +115,9 @@ public class DataUsagePreferenceControllerTest {
@Test
public void updateState_noUsageData_shouldDisablePreference() {
ReflectionHelpers.setField(
mController, "mDataUsageInfo", new DataUsageController.DataUsageInfo());
final DataUsageController.DataUsageInfo usageInfo =
new DataUsageController.DataUsageInfo();
doReturn(usageInfo).when(mController).getDataUsageInfo(any());
mController.updateState(mPreference);
@@ -124,9 +126,10 @@ public class DataUsagePreferenceControllerTest {
@Test
public void updateState_shouldUseIECUnit() {
final DataUsageController.DataUsageInfo usageInfo = new DataUsageController.DataUsageInfo();
final DataUsageController.DataUsageInfo usageInfo =
new DataUsageController.DataUsageInfo();
usageInfo.usageLevel = TrafficStats.MB_IN_BYTES;
ReflectionHelpers.setField(mController, "mDataUsageInfo", usageInfo);
doReturn(usageInfo).when(mController).getDataUsageInfo(any());
mController.updateState(mPreference);

View File

@@ -86,5 +86,10 @@ public class ToggleFeaturePreferenceFragmentTest {
public int getMetricsCategory() {
return 0;
}
@Override
int getUserShortcutTypes() {
return 0;
}
}
}